From f4fc9b82c33ea230d1d58a412356ad7b6160aff7 Mon Sep 17 00:00:00 2001 From: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> Date: Tue, 7 Jul 2026 21:23:52 +0000 Subject: [PATCH] feat: redesign mobile space sidebar with card-based layout. (#318) Co-authored-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> Co-committed-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> --- src/app/components/SpaceMenu.svelte | 410 +++++++++++-------- src/app/components/SpaceMenuRoomItem.svelte | 11 +- src/lib/components/SecondaryNavHeader.svelte | 3 +- src/lib/components/space-menu.css | 125 ++++++ src/lib/components/theme.css | 1 + src/routes/spaces/[relay]/+page.svelte | 8 +- 6 files changed, 370 insertions(+), 188 deletions(-) create mode 100644 src/lib/components/space-menu.css diff --git a/src/app/components/SpaceMenu.svelte b/src/app/components/SpaceMenu.svelte index 240db66d..0acfa2d2 100644 --- a/src/app/components/SpaceMenu.svelte +++ b/src/app/components/SpaceMenu.svelte @@ -1,5 +1,6 @@ -
- -
- - {#if showMenu} - - - - {/if} + {#if $notificationSettings.push && !$shouldNotify} + + {/if} + +
-
- - Space Details - - {#if hasNip29($relay)} - - Recent Activity - - {:else} - - Chat - + {displayRelayUrl(url)} + + {#if showMenu} + + + + {/if} +{/snippet} + +{#snippet spaceNavItems()} + + Space Details + + {#if hasNip29($relay)} + + Recent Activity + + {:else} + + Chat + + {/if} + + Directory + + {#if showLibrary} + + Library + + {/if} + {#if ENABLE_ZAPS && $spaceKinds.has(ZAP_GOAL)} + + Goals + + {/if} + {#if $spaceKinds.has(THREAD)} + + Threads + + {/if} + {#if $spaceKinds.has(CLASSIFIED)} + + Classifieds + + {/if} + {#if $spaceKinds.has(EVENT_TIME)} + + Calendar + + {/if} + {#if $spaceKinds.has(POLL)} + + Polls + + {/if} + {#if hasNip29($relay)} + + Search + + {/if} +{/snippet} + +{#snippet spaceRooms()} + {#if hasNip29($relay)} + {#if $userRooms.length > 0} + {#if !mobile} +
{/if} - - Directory - - {#if showLibrary} - - Library - + Your Rooms + {/if} + {#each $userRooms as h (h)} + + {/each} + {#if $otherRooms.length > 0} + {#if !mobile} +
{/if} - {#if ENABLE_ZAPS && $spaceKinds.has(ZAP_GOAL)} - - Goals - - {/if} - {#if $spaceKinds.has(THREAD)} - - Threads - - {/if} - {#if $spaceKinds.has(CLASSIFIED)} - - Classifieds - - {/if} - {#if $spaceKinds.has(EVENT_TIME)} - - Calendar - - {/if} - {#if $spaceKinds.has(POLL)} - - Polls - - {/if} - {#if hasNip29($relay)} - - Search - + {#if $userRooms.length > 0} -
- Your Rooms - {/if} - {#each $userRooms as h (h)} - - {/each} - {#if $otherRooms.length > 0} -
- - {#if $userRooms.length > 0} - Other Rooms - {:else} - Rooms - {/if} - - {/if} - {#if $otherRooms.length > 20} - - {/if} - {#each $roomSearch.searchValues(term) as h (h)} - - {/each} - {#if $otherVoiceRooms.length > 0} -
- Voice Rooms - {#each $otherVoiceRooms as h (h)} - - {/each} - {/if} - {#if $canCreateRoom} - - - Create room - + Other Rooms + {:else} + Rooms {/if} +
+ {/if} + {#if $otherRooms.length > 20} + + {/if} + {#each $roomSearch.searchValues(term) as h (h)} + + {/each} + {#if $otherVoiceRooms.length > 0} + {#if !mobile} +
{/if} -
+ Voice Rooms + {#each $otherVoiceRooms as h (h)} + + {/each} + {/if} + {#if $canCreateRoom} + + + Create room + + {/if} + {/if} +{/snippet} + +{#snippet spaceFooter()} + + + + +{/snippet} + +
+ {#if mobile} + +
+ {@render spaceHeader()} +
+
+
+ Space + {@render spaceNavItems()} +
+ {#if hasNip29($relay) && ($userRooms.length > 0 || $otherRooms.length > 0 || $otherVoiceRooms.length > 0 || $canCreateRoom)} +
+ {@render spaceRooms()} +
+ {/if} +
+
+ {@render spaceFooter()} +
+
+ {:else} + +
+ {@render spaceHeader()} +
+
+ {@render spaceNavItems()} + {@render spaceRooms()} +
+
+
+
+ {@render spaceFooter()}
- -
- - - - -
+ {/if}
diff --git a/src/app/components/SpaceMenuRoomItem.svelte b/src/app/components/SpaceMenuRoomItem.svelte index 0c22ad92..1800d124 100644 --- a/src/app/components/SpaceMenuRoomItem.svelte +++ b/src/app/components/SpaceMenuRoomItem.svelte @@ -10,13 +10,14 @@ import {notifications} from "@app/notifications" import {makeRoomPath} from "@app/routes" - interface Props { - url: any - h: any + type Props = { + url: string + h: string replaceState?: boolean + tooltip?: boolean } - const {url, h, replaceState = false}: Props = $props() + const {url, h, replaceState = false, tooltip = true}: Props = $props() const room = deriveRoom(url, h) const roomType = $derived(getRoomType($room)) @@ -31,7 +32,7 @@ {#if roomType === RoomType.Voice} {:else} - + {#if showDifferenceIcon} diff --git a/src/lib/components/SecondaryNavHeader.svelte b/src/lib/components/SecondaryNavHeader.svelte index d15f77ff..bcb3f176 100644 --- a/src/lib/components/SecondaryNavHeader.svelte +++ b/src/lib/components/SecondaryNavHeader.svelte @@ -6,6 +6,7 @@ const {children}: Props = $props() -
+
{@render children?.()}
diff --git a/src/lib/components/space-menu.css b/src/lib/components/space-menu.css new file mode 100644 index 00000000..a5271a98 --- /dev/null +++ b/src/lib/components/space-menu.css @@ -0,0 +1,125 @@ +@layer components { + @media (max-width: 768px) { + .secondary-nav--mobile-space { + @apply mt-sai bg-backdrop mb-0 w-full max-w-full grow border-0; + + .tip[data-tip]::before { + display: none !important; + } + + .secondary-nav__nav-item { + @apply rounded-2xl font-medium; + + &:hover { + @apply bg-surface-less text-content; + transform: none; + box-shadow: none; + } + + &:active { + transform: none; + box-shadow: none; + } + } + + .secondary-nav__nav-item--active { + @apply text-content; + background-color: color-mix(in srgb, var(--primary) 14%, var(--surface)); + box-shadow: none; + + &:hover { + @apply text-content; + background-color: color-mix(in srgb, var(--primary) 18%, var(--surface)); + } + } + } + + .space-menu { + @apply gap-3 p-3 pt-2; + } + + .space-menu__card { + @apply p-2; + } + + .space-menu__card .secondary-nav__header { + @apply text-content-muted px-2 py-1 text-xs font-semibold tracking-wider uppercase; + } + + .space-menu__card .secondary-nav__header:first-child { + @apply text-content pb-0.5 font-bold; + } + + .space-menu__card .secondary-nav__header:not(:first-child) { + @apply border-line-less mt-2 border-t pt-3; + } + + .space-menu__header { + @apply p-3; + } + + .space-menu__header-button { + @apply rounded-2xl p-0; + + &:hover { + @apply bg-transparent; + } + } + + .space-menu__scroll { + @apply min-h-0 flex-1 gap-3 overflow-y-auto; + } + + .space-menu__status { + @apply flex w-full flex-col gap-2; + } + + .space-menu__status > .card { + @apply w-full gap-1 border-0 bg-transparent p-0 shadow-none; + } + + .space-menu__status-link { + @apply h-auto w-full border-0 bg-transparent p-0 shadow-none; + + &:hover { + @apply text-content border-0 bg-transparent; + } + } + + .space-menu__status-link .flex { + @apply justify-start px-1; + } + } +} + +@media (max-width: 768px) { + [data-theme="dark"] .secondary-nav--mobile-space { + @apply bg-surface-less; + } + + [data-fl-theme="clay"] .secondary-nav--mobile-space { + .secondary-nav__nav-item:hover, + .secondary-nav__nav-item:active { + background-color: var(--surface-less); + transform: none; + box-shadow: none; + } + + .secondary-nav__nav-item--active, + .secondary-nav__nav-item--active:hover { + background-color: color-mix(in srgb, var(--primary) 14%, var(--surface)); + color: var(--content); + box-shadow: none; + } + } + + [data-fl-theme="clay"] .space-menu__status-link:hover, + [data-fl-theme="clay"] .space-menu__status-link:active { + transform: none; + box-shadow: none; + } + + .space-menu__status .text-sm { + @apply font-medium; + } +} diff --git a/src/lib/components/theme.css b/src/lib/components/theme.css index 6040e49c..3fcb5168 100644 --- a/src/lib/components/theme.css +++ b/src/lib/components/theme.css @@ -36,6 +36,7 @@ @import "./room.css"; @import "./spinner.css"; @import "./secondary-nav.css"; +@import "./space-menu.css"; @import "./tooltip.css"; @config "../../../tailwind.config.js"; diff --git a/src/routes/spaces/[relay]/+page.svelte b/src/routes/spaces/[relay]/+page.svelte index 064927c5..890db7a9 100644 --- a/src/routes/spaces/[relay]/+page.svelte +++ b/src/routes/spaces/[relay]/+page.svelte @@ -4,7 +4,6 @@ import SecondaryNav from "@lib/components/SecondaryNav.svelte" import {decodeRelay} from "@app/relays" import {goToSpace} from "@app/routes" - import PrimaryNavSpaces from "@app/components/PrimaryNavSpaces.svelte" import SpaceMenu from "@app/components/SpaceMenu.svelte" const url = decodeRelay($page.params.relay!) @@ -22,10 +21,7 @@ {#if width <= md} -
- -
- - + + {/if}