Files
pad/web/src
xarmian 441f624584 feat(web): mobile navbar workspace switcher always present, preserve sidebar state on switch (TASK-761) (#245)
* feat(web): mobile workspace switcher always present, preserve sidebar state on switch (TASK-761)

Implements IDEA-760.

- web/src/routes/+layout.svelte: replace the mobile-header workspace-name link
  with <WorkspaceSwitcher mobile /> so the switcher is reachable from both
  sidebar states. Add `.mobile-switcher-slot` to flex-fill the gap next to the
  hamburger; drop the now-unused `.mobile-title` rules.
- web/src/lib/components/layout/WorkspaceSwitcher.svelte: drop uiStore.onNavigate()
  from select() so workspace switching no longer collapses the mobile sidebar —
  the user's sidebar state carries over to the new workspace per IDEA-760. Add
  same-workspace dashboard parity (mirrors TopBar.handleWsClick) so tapping the
  current workspace still gives a one-tap path back to the dashboard.

openCreateModal() retains its uiStore.onNavigate() — separate modal-overlay UX.

* fix(web): tighten WorkspaceSwitcher dashboard URL + a11y on switcher trigger

Codex P2 + nit follow-up to TASK-761:

- WorkspaceSwitcher.select(): same-workspace dashboard branch now reads
  owner_username from workspaceStore.current rather than ws.owner_username
  (which is typed optional). When isCurrent is true `current` is non-null and
  shares the slug, so its owner_username is guaranteed present. Avoids the
  edge case where a caller passing a workspace without owner_username would
  produce `//slug` (scheme-relative URL) instead of an in-app path.
- WorkspaceSwitcher trigger: add aria-haspopup="menu", aria-expanded={open},
  and aria-hidden on the chevron glyph so screen readers get the menu
  semantics + open/closed state on the new primary mobile navbar control.

* fix(web): aria-haspopup type matches actual popup (dialog mobile, menu desktop)

Codex follow-up nit on TASK-761: the WorkspaceSwitcher trigger advertised
aria-haspopup="menu" unconditionally, but on mobile the popup is a
role="dialog" BottomSheet and on desktop it's a dropdown of buttons.
Make the hint match the actual surface by deriving from isMobile.

* fix(web): drop aria-haspopup on desktop WorkspaceSwitcher popup

Codex follow-up nit on TASK-761: the desktop popup is a plain dropdown
<div> of buttons without role=menu/menuitem or arrow-key keyboard nav,
so aria-haspopup="menu" overstated the semantics. Mobile keeps
aria-haspopup="dialog" because that branch genuinely renders a
role="dialog" BottomSheet. Desktop falls back to aria-expanded alone,
which is sufficient for "button toggles a popup" without claiming
specific popup type semantics that aren't backed by roles.
2026-04-25 09:57:28 -04:00
..
2026-03-26 01:52:36 +00:00