Skip to content

Redesign settings & presence UX: profile popover + modal overlay#238

Open
wesbillman wants to merge 4 commits intomainfrom
settings-presence-ux
Open

Redesign settings & presence UX: profile popover + modal overlay#238
wesbillman wants to merge 4 commits intomainfrom
settings-presence-ux

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

Summary

Redesigns how users interact with settings and presence in the desktop app, inspired by Slack's lightweight profile popover and Goose 2's modal settings pattern.

Changes

Profile Popover (new)

  • Clicking the sidebar footer avatar now opens a lightweight popover instead of navigating to full settings
  • Shows user identity (avatar, display name, nip05, presence badge)
  • Single-click availability toggle — switch between online/away/offline without leaving your conversation
  • Quick access to Settings (with ⌘, / Ctrl+, shortcut hint)
  • Proper ARIA menu semantics, semantic <hr> separators

Settings as Modal Overlay (refactored)

  • Settings no longer takes over the entire app — renders as a centered modal overlay
  • Sidebar stays visible behind the backdrop blur overlay
  • Entrance animation: scale + fade on modal, staggered slide-in on nav items
  • Proper accessibility: focus trap via @radix-ui/react-focus-scope, role="dialog", aria-modal, Escape key dismissal
  • All animations use motion-safe: prefixes for prefers-reduced-motion support
  • Proper header bar with title and close button (no more overlapping content)

Presence removed from Settings

  • Presence panel removed from settings entirely — now accessible via the popover
  • Cleaner settings with fewer sections

Cleanup

  • "settings" removed from AppView type — settings is a separate boolean overlay, not a view mode
  • Dead lastNonSettingsViewRef removed
  • Stale "settings" variant removed from ChatHeader.mode type

Files Changed

  • desktop/src/features/profile/ui/ProfilePopover.tsx (new)
  • desktop/src/app/AppShell.tsx
  • desktop/src/features/settings/ui/SettingsView.tsx
  • desktop/src/features/settings/ui/SettingsPanels.tsx
  • desktop/src/features/sidebar/ui/AppSidebar.tsx
  • desktop/src/features/chat/ui/ChatHeader.tsx
  • desktop/package.json + pnpm-lock.yaml (@radix-ui/react-focus-scope)

Testing

  • TypeScript: clean tsc --noEmit
  • Biome: zero lint/format errors
  • Manual: settings modal opens/closes, popover toggles presence, Escape/⌘, shortcuts work, focus trap active

Redesign settings and presence UX inspired by Slack and Goose 2:

Profile Popover (new):
- Clicking sidebar footer avatar opens a lightweight popover
- Shows user identity, current presence status
- Single-click availability toggle (online/away/offline)
- Quick access to Settings and Sign out
- Platform-aware keyboard shortcut hint (⌘, / Ctrl+,)
- Proper ARIA menu roles and semantic separators

Settings as Modal Overlay (refactored):
- Settings renders as a centered modal overlay instead of full-width takeover
- Sidebar stays visible behind the backdrop blur
- Entrance animations: scale+fade modal, slide-in sidebar nav, staggered nav items
- Section transition micro-animation on panel switch
- Focus trap via @radix-ui/react-focus-scope
- role=dialog, aria-modal, aria-labelledby for accessibility
- motion-safe: prefixed animations for prefers-reduced-motion
- Escape, backdrop click, and X button to dismiss

Cleanup:
- Remove 'settings' from AppView type (no longer a view mode)
- Remove dead lastNonSettingsViewRef
- Clean stale 'settings' variant from ChatHeader mode type
- Separate settingsOpen boolean from view routing
- Remove sign out from ProfilePopover (not functional)
- Make popover menu items full-width for better click targets
- Add proper header bar to settings modal (fixes close button overlap)
- Remove presence section from settings (now in popover)
- Clean up stale presence/signout props across AppShell and AppSidebar
Remove the isTransitioning fade-out/fade-in effect that fired backwards
(after content swap instead of before), causing a double visual pop.
Section changes are now instant. The entrance animation (isLoaded) is
preserved.
@wesbillman
Copy link
Copy Markdown
Collaborator Author

Screenshot 2026-04-04 at 9 03 58 PM Screenshot 2026-04-05 at 9 30 30 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant