From 9c68f66c39740b5623712053b26c3b1cfc19aaf5 Mon Sep 17 00:00:00 2001
From: Aditya Chaudhary <30+useradityaa@noreply.coracle.social>
Date: Fri, 7 Aug 2026 21:05:17 +0000
Subject: [PATCH] fix: replace mobile space menu popover with a bottom-sheet
action menu (#330)
Co-authored-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social>
---
src/app/components/SpaceMenu.svelte | 396 +-----------------
src/app/components/SpaceMenuActions.svelte | 122 ++++++
.../components/SpaceMenuActionsMobile.svelte | 118 ++++++
src/app/components/SpaceMenuHeader.svelte | 74 ++++
src/app/components/SpaceMenuMobile.svelte | 19 +
src/app/components/SpaceMenuNavItems.svelte | 103 +++++
src/app/components/SpaceMenuRooms.svelte | 106 +++++
src/app/routes.ts | 8 +-
8 files changed, 566 insertions(+), 380 deletions(-)
create mode 100644 src/app/components/SpaceMenuActions.svelte
create mode 100644 src/app/components/SpaceMenuActionsMobile.svelte
create mode 100644 src/app/components/SpaceMenuHeader.svelte
create mode 100644 src/app/components/SpaceMenuMobile.svelte
create mode 100644 src/app/components/SpaceMenuNavItems.svelte
create mode 100644 src/app/components/SpaceMenuRooms.svelte
diff --git a/src/app/components/SpaceMenu.svelte b/src/app/components/SpaceMenu.svelte
index 3f1d9244..114f0a5c 100644
--- a/src/app/components/SpaceMenu.svelte
+++ b/src/app/components/SpaceMenu.svelte
@@ -1,79 +1,13 @@
-{#snippet spaceHeader()}
-
- {#if showMenu}
-
-
-
- {/if}
-{/snippet}
-
-{#snippet spaceNavItems()}
-
- Space Details
-
- {#if hasNip29}
-
- 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}
-
- Search
-
- {/if}
-{/snippet}
-
-{#snippet spaceRooms()}
- {#if hasNip29}
- {#if $userRooms.length > 0}
- {#if !mobile}
-
+
{#if mobile}
{:else}
- {@render spaceHeader()}
+
- {@render spaceFooter()}
+
+
+
+
{/if}
diff --git a/src/app/components/SpaceMenuActions.svelte b/src/app/components/SpaceMenuActions.svelte
new file mode 100644
index 00000000..e4ee3940
--- /dev/null
+++ b/src/app/components/SpaceMenuActions.svelte
@@ -0,0 +1,122 @@
+
+
+{#snippet actionButton(
+ onclick: () => void,
+ icon: string,
+ label: string,
+ variant?: "error" | "primary",
+)}
+
+
+
+{/snippet}
+
+{@render actionButton(createInvite, LinkRound, "Create Invite")}
+{#if $userIsAdmin}
+
+
+
+{/if}
+{#if $relay?.pubkey && $relay.pubkey !== $user.pubkey}
+ {@render actionButton(contactOwner, Letter, "Contact Owner")}
+{/if}
+{#if $notificationSettings.push}
+ {@render actionButton(
+ toggleSpaceNotifications,
+ $shouldNotify ? Bell : BellOff,
+ `${$shouldNotify ? "Turn off" : "Turn on"} notifications`,
+ )}
+{:else}
+
+
+
+ Enable notifications
+
+
+{/if}
+{#if HOSTING_ENABLED && $hostedRelay.relay}
+
+
+
+ Hosting settings
+
+
+{:else if $userIsAdmin}
+ {@render actionButton(startEdit, Pen, "Edit Space")}
+{/if}
+{#if $userSpaceUrls.includes(url)}
+ {@render actionButton(leaveSpace, Exit, "Leave Space", "error")}
+{:else}
+ {@render actionButton(joinSpace, Login, "Join Space", "primary")}
+{/if}
diff --git a/src/app/components/SpaceMenuActionsMobile.svelte b/src/app/components/SpaceMenuActionsMobile.svelte
new file mode 100644
index 00000000..fb6ba2b0
--- /dev/null
+++ b/src/app/components/SpaceMenuActionsMobile.svelte
@@ -0,0 +1,118 @@
+
+
+{#snippet actionButton(
+ onclick: () => void,
+ icon: string,
+ label: string,
+ variant?: "error" | "primary",
+)}
+
+{/snippet}
+
+{@render actionButton(createInvite, LinkRound, "Create Invite")}
+{#if $userIsAdmin}
+
+{/if}
+{#if $relay?.pubkey && $relay.pubkey !== $user.pubkey}
+ {@render actionButton(contactOwner, Letter, "Contact Owner")}
+{/if}
+{#if $notificationSettings.push}
+ {@render actionButton(
+ toggleSpaceNotifications,
+ $shouldNotify ? Bell : BellOff,
+ `${$shouldNotify ? "Turn off" : "Turn on"} notifications`,
+ )}
+{:else}
+
+
+ Enable notifications
+
+{/if}
+{#if HOSTING_ENABLED && $hostedRelay.relay}
+
+
+ Hosting settings
+
+{:else if $userIsAdmin}
+ {@render actionButton(startEdit, Pen, "Edit Space")}
+{/if}
+{#if $userSpaceUrls.includes(url)}
+ {@render actionButton(leaveSpace, Exit, "Leave Space", "error")}
+{:else}
+ {@render actionButton(joinSpace, Login, "Join Space", "primary")}
+{/if}
diff --git a/src/app/components/SpaceMenuHeader.svelte b/src/app/components/SpaceMenuHeader.svelte
new file mode 100644
index 00000000..723dcd59
--- /dev/null
+++ b/src/app/components/SpaceMenuHeader.svelte
@@ -0,0 +1,74 @@
+
+
+
+{#if showMenu && !mobile}
+
+
+
+{/if}
diff --git a/src/app/components/SpaceMenuMobile.svelte b/src/app/components/SpaceMenuMobile.svelte
new file mode 100644
index 00000000..8f4eca2b
--- /dev/null
+++ b/src/app/components/SpaceMenuMobile.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/app/components/SpaceMenuNavItems.svelte b/src/app/components/SpaceMenuNavItems.svelte
new file mode 100644
index 00000000..36cedae9
--- /dev/null
+++ b/src/app/components/SpaceMenuNavItems.svelte
@@ -0,0 +1,103 @@
+
+
+
+ Space Details
+
+{#if hasNip29}
+
+ 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}
+
+ Search
+
+{/if}
diff --git a/src/app/components/SpaceMenuRooms.svelte b/src/app/components/SpaceMenuRooms.svelte
new file mode 100644
index 00000000..ec6d4216
--- /dev/null
+++ b/src/app/components/SpaceMenuRooms.svelte
@@ -0,0 +1,106 @@
+
+
+{#snippet content()}
+ {#if $userRooms.length > 0}
+ {#if !mobile}
+
+ {/if}
+
Your Rooms
+ {/if}
+ {#each $userRooms as h (h)}
+
+ {/each}
+ {#if $otherRooms.length > 0}
+ {#if !mobile}
+
+ {/if}
+
+ {#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}
+ {#if !mobile}
+
+ {/if}
+
Voice Rooms
+ {#each $otherVoiceRooms as h (h)}
+
+ {/each}
+ {/if}
+ {#if $canCreateRoom}
+
+
+ Create room
+
+ {/if}
+{/snippet}
+
+{#if ($relay?.hasNip(29) ?? false) && ($userRooms.length > 0 || $otherRooms.length > 0 || $otherVoiceRooms.length > 0 || $canCreateRoom)}
+ {#if mobile}
+
+ {:else}
+ {@render content()}
+ {/if}
+{/if}
diff --git a/src/app/routes.ts b/src/app/routes.ts
index c171488f..f150126e 100644
--- a/src/app/routes.ts
+++ b/src/app/routes.ts
@@ -57,13 +57,13 @@ export const makeRoomPath = (url: string, h: string) => `/spaces/${encodeRelay(u
export const makeSpaceChatPath = (url: string) => makeRoomPath(url, "chat")
-export const goToChat = (pubkeys: string[] = []) => {
+export const goToChat = (pubkeys: string[] = [], options: {replaceState?: boolean} = {}) => {
if (messagingRelayLists.get().urls(user.get().pubkey).get().length === 0) {
- pushModal(ChatEnable, {next: () => goToChat(pubkeys)})
+ pushModal(ChatEnable, {next: () => goToChat(pubkeys, options)})
} else if (pubkeys.length === 0) {
- goto(lastChatUrl ?? "/chat")
+ goto(lastChatUrl ?? "/chat", options)
} else {
- goto(makeChatPath(pubkeys))
+ goto(makeChatPath(pubkeys), options)
}
}