Skip to content

Commit a36d41c

Browse files
intendednullclaude
andauthored
docs(ux-nav): close out spec — flip [active]→[landed], refresh sections 1/4/5 to match realised UX (#655)
Audit-and-align pass surfaced 5 findings against docs/specs/2026-03-25-ux-navigation-improvements-design.md: 1. SettingsTab enum has 5 variants in code (Profile, Server, Roles, Presence, Notifications); spec listed only the original 3. Presence + Notifications were added by Phase 1e/1f. Updated the enum example + tab listing to match. 2. Server context menu has 2 items in code (Server Settings, Leave Server), not the 3 the spec listed. The standalone "Invite" entry was dropped because invite generation is reachable from the Server settings tab. Documented the dropped item with the rationale. 3. Quick Peer ID Copy lives in the profile-card popover, not as a sidebar icon. Phase 2c consolidated all self-profile actions into the popover to keep the always-visible sidebar uncluttered. Rewrote §5 to describe the realised shape and note the supersession. 4. `ServerList` was renamed to `GroveRail` during the Phase 1a desktop-shell refactor. Updated §4 implementation note. 5. `leave_server` is now actor-based (mutates `server_registry_addr` via `willow_actor::state::mutate`); the spec described direct SharedState mutation + explicit storage calls. Rewrote the `leave_server()` block to describe the actor-pipeline shape and added a migration note. Added Date/Status/Implementation plan header per the docs-organization convention (PR #653). README master index flipped [active] → [landed]. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 3332bac commit a36d41c

2 files changed

Lines changed: 32 additions & 9 deletions

File tree

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Every entry below carries one of:
106106

107107
- [Willow UI — target UX bundle](specs/2026-04-19-ui-design/README.md) — 20+ child specs covering desktop and mobile target UX across layout, components, and interactions. `[active]`
108108
- [Pinned-message metadata](specs/2026-05-21-pinned-message-metadata-design.md) — extends Channel pinned_messages to carry pinner + pin-time. `[landed]`
109-
- [UX navigation improvements](specs/2026-03-25-ux-navigation-improvements-design.md) — unifies settings, adds confirmation dialogs, breadcrumbs, and command palette. `[active]`
109+
- [UX navigation improvements](specs/2026-03-25-ux-navigation-improvements-design.md) — unifies settings, adds confirmation dialogs, breadcrumbs, and command palette. `[landed]`
110110
- [Video, screen sharing + call page](specs/2026-03-26-screen-sharing-call-page-design.md) — adds camera video, screen sharing, and full call page UI to voice chat. `[active]`
111111
- [Async client + UI refactor](specs/2026-03-24-async-client-ui-refactor-design.md) — eliminates polling by splitting `Client` into `ClientHandle` + async event loop. `[landed]`
112112

docs/specs/2026-03-25-ux-navigation-improvements-design.md

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# UX Navigation Improvements Design
22

3+
**Date:** 2026-03-25
4+
**Status:** landed — unified settings panel, confirmation dialogs, breadcrumbs, server context menu, peer-ID copy affordance (relocated to profile card), and Ctrl+K palette all shipped via [`docs/plans/2026-03-25-ux-navigation-improvements.md`](../plans/2026-03-25-ux-navigation-improvements.md). Spec sections 1, 4, 5 below were refreshed after a 2026-05 audit to match the realised UX (extra Presence/Notifications tabs, GroveRail rename, actor-based `leave_server`, peer-ID copy via profile card).
5+
**Implementation plan:** [`docs/plans/2026-03-25-ux-navigation-improvements.md`](../plans/2026-03-25-ux-navigation-improvements.md)
6+
37
## Problem
48

59
The Willow web UI has several navigation and UX friction points:
@@ -26,6 +30,8 @@ Replace the three separate panels (`SettingsPanel`, `ServerSettingsPanel`, `Role
2630
- **Profile** — display name, peer ID copy (current SettingsPanel content)
2731
- **Server** — server name, description, invite generation (current ServerSettingsPanel content minus roles)
2832
- **Roles** — role CRUD, permission toggles, assignment (current RoleManager content)
33+
- **Presence** — self-presence override menu and 7-state catalog (added by Phase 1e)
34+
- **Notifications** — per-surface mute overrides and OS push contract (added by Phase 1f)
2935

3036
**State changes:**
3137
- Remove `show_server_settings` signal entirely from `UiState`/`UiWriteSignals`.
@@ -39,6 +45,8 @@ pub enum SettingsTab {
3945
Profile,
4046
Server,
4147
Roles,
48+
Presence,
49+
Notifications,
4250
}
4351
```
4452

@@ -99,27 +107,42 @@ Right-click (desktop) or long-press (mobile) on a server icon shows a popup menu
99107

100108
**Menu items:**
101109
- **Server Settings** — opens settings panel to "server" tab
102-
- **Invite** — opens settings panel to "server" tab
103110
- **Leave Server** — with confirmation dialog (destructive)
104111

112+
(A standalone "Invite" item was considered and dropped — invite generation is
113+
reachable from the Server settings tab, so a separate menu entry would be
114+
redundant.)
115+
105116
**Implementation:**
106117
- New `components/context_menu.rs` — reusable positioned popup rendering at cursor/touch position.
107-
- Context menu state is local to the `ServerList` component (not in global `UiState`), since it doesn't need to be shared. Uses local signals: `show_context_menu`, `menu_position` (x/y), `context_server_id`.
118+
- Context menu state is local to the `GroveRail` component (formerly `ServerList`; renamed during the Phase 1a desktop-shell refactor and now the canonical name for the leftmost server-list rail). Uses local signals: `show_context_menu`, `menu_position` (x/y), `context_server_id`.
108119
- Desktop: `on:contextmenu` on `.server-icon`, prevent default, show menu at mouse position.
109120
- Mobile: reuse the same long-press pattern from `message.rs` (500ms timer, touchstart/touchend, haptic feedback) for consistency. Extract the long-press detection into a shared utility if practical, or duplicate the pattern with a comment noting the shared approach.
110121
- Click outside or Escape dismisses.
111122

112-
**`leave_server()` in client:** This is a **local-only** operation (no P2P event, no state machine change). It removes the server from `SharedState.state.servers`, removes associated data from persistence (`storage::save_server_list`, `storage::save_server_by_id`), and switches to the next available server or clears `active_server` (returning to welcome if no servers remain). The event history for the left server is retained in storage (not purged).
123+
**`leave_server()` in client:** This is a **local-only** operation (no P2P event, no state machine change). It mutates the `server_registry_addr` actor (via `willow_actor::state::mutate`) to remove the server from the registry, and switches to the next available server or clears `active_server` (returning to welcome if no servers remain). Persistence flows through the actor pipeline rather than direct `storage::save_*` calls — see `crates/client/src/servers.rs::leave_server`. The event history for the left server is retained in storage (not purged).
124+
125+
> Note on migration shape: the design originally sketched direct `SharedState.state.servers` mutation + explicit `storage::save_server_list`/`save_server_by_id` calls. The client was migrated to the actor model after this spec landed, so the post-migration shape (mutate the registry actor, let persistence flow through it) replaces the original sketch. Observable behaviour is unchanged.
113126
114127
**Files:** Modify `crates/client/src/lib.rs` to add `leave_server()` on `ClientHandle`.
115128

116129
### 5. Quick Peer ID Copy
117130

118-
Add a copy icon button in the sidebar user area (next to display name) that copies the user's peer ID to clipboard with a brief "Copied!" tooltip.
119-
120-
Both sides of the invite flow need to share peer IDs. Having it one click away in the always-visible sidebar eliminates navigating to settings just to copy your ID.
121-
122-
**Implementation:** Small copy icon button in the sidebar user area. `on:click` copies `handle.peer_id()` to clipboard via `navigator.clipboard.writeText()`. Shows "Copied!" tooltip briefly (CSS animation, auto-hides after 1.5s). The `peer_id` is available via `ClientHandle` from context — no new props needed on `Sidebar`.
131+
Provide a single-click affordance to copy the user's peer ID for sharing in invite flows, without making the user navigate to settings.
132+
133+
**Realised shape (post-migration):** The me-strip in the channel sidebar
134+
(`crates/web/src/components/channel_sidebar.rs`) is a single profile-open
135+
button. Clicking it opens the profile card popover
136+
(`crates/web/src/components/profile_card.rs`), which surfaces the peer-ID
137+
fingerprint plus copy affordance. This is one extra click compared to the
138+
original "icon button directly in the sidebar" sketch, but it intentionally
139+
keeps the always-visible sidebar uncluttered and consolidates all self-
140+
profile actions in a single popover. The peer-ID copy lives next to the
141+
trust fingerprint, the display-name editor, and other profile-card content.
142+
143+
(The original design sketched a copy icon button next to the display name
144+
in the sidebar with a `"Copied!"` tooltip. That UX was superseded by the
145+
profile-card consolidation during Phase 2c.)
123146

124147
### 6. Command Palette (Ctrl+K)
125148

0 commit comments

Comments
 (0)