feat(settings): inline settings tree in sidenav + flyout on collapsed rail; drop settings submenu column #1104

Closed
opened 2026-05-11 14:34:49 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As an operator, I want the Settings section to surface its inner tree inside the main sidenav — auto-expanded inline on /settings/* when the sidenav is expanded, and as a flyout when the sidenav is collapsed — so that the dashboard uses one nav column instead of two stacked ones, and section nav is discoverable in both rail modes.

Background

After nav-v2 (#1090) shipped, visiting /settings still renders a dedicated left column (SettingsGroupedNav) for section nav. Result: two stacked left columns (main sidenav + settings submenu), narrow content area, redundant hierarchy. Decision (operator review 2026-05-11): drop the settings page submenu, move section nav into the main sidenav with two behaviours — inline tree when expanded, flyout when collapsed.

Behaviour summary

Expanded sidenav + route matches /settings/*:

  • Settings footer item expands inline showing the full grouped tree.
  • Tree mirrors current NAV_GROUPS: GENERAL → General / Appearance / Voice input; AGENTS → Agent types / Agent config; FORGES → Service config / Repos / Labels; DATA → Secrets.
  • Active leaf gets highlighted state.
  • Group accordions default to expanded; toggle on click; not persisted in v1.

Expanded sidenav + non-settings route:

  • Settings footer item renders as plain link with icon (no tree).

Collapsed sidenav (rail mode, any route):

  • Settings icon opens a Base UI Menu flyout anchored to the icon.
  • Flyout contains the same grouped tree.
  • Leaf click → navigate + close flyout.

Settings page (/settings, /settings/*):

  • Drop SettingsGroupedNav left column.
  • Content becomes full-width within the existing AppShell slot.
  • Add thin breadcrumb header: Settings › <Group> › <Leaf>.
  • Existing in-page anchors (Quick Links, etc.) remain.

Acceptance criteria

Shared data

  • NAV_GROUPS extracted from apps/web/src/routes/settings.tsx (lines 45–73) into a new module apps/web/src/lib/settings-nav.ts.
  • NavGroup + NavItem types co-located in the shared module.
  • All current consumers (SettingsGroupedNav, SettingsSideNav in apps/web/src/components/settings-side-nav.tsx, any sub-route side nav) import from the shared module — no duplicated lists.

Sidenav inline tree (expanded mode)

  • apps/web/src/components/sidebar-nav.tsx renders Settings as an expandable section when route matches /settings* and sidenav is not collapsed.
  • Tree renders all groups + leaves from shared NAV_GROUPS.
  • Active leaf highlighted with the same active styles as other nav items.
  • Non-settings routes render Settings as a plain link (no tree).
  • Group accordions toggle on click; default = all expanded; chevron indicates state.

Sidenav flyout (collapsed mode)

  • When data-nav="collapsed" is set on <html>, clicking the Settings rail icon opens a Base UI Menu flyout.
  • Flyout uses existing primitives from @base-ui-components/react/menu — no new dependency.
  • Flyout positioned to the right of the rail icon, dismisses on outside click + Escape.
  • Tree content identical to expanded mode.
  • Leaf click invokes navigate(to) then closes the flyout.
  • Tooltip on the rail Settings icon follows the existing rail-icon tooltip pattern; does not double-fire when flyout is open.

Settings page

  • apps/web/src/routes/settings.tsx no longer renders SettingsGroupedNav.
  • Content laid out full-width within AppShell content slot.
  • Breadcrumb header added: Settings › <Group> › <Leaf> (active group + leaf derived from current sub-route; /settings root shows Settings › General).
  • Breadcrumb segments are links (group label → first leaf of group; root → /settings).
  • SettingsGroupedNav component deleted if no remaining consumers.
  • Sub-routes (e.g. /settings/service.tsx) updated: drop any in-page SettingsSideNav that now duplicates the sidenav tree, OR keep it only where the sub-route has its own deeper sub-tree not covered by NAV_GROUPS — document the decision in the PR description.

Mobile / small viewport

  • Existing mobile drawer behaviour preserved.
  • When the mobile drawer is open on /settings/*, tree renders inline (same as expanded mode).

Tests

  • Vitest browser-mode test for sidebar-nav: route /settings/appearance + expanded → tree renders + Appearance leaf is active.
  • Vitest browser-mode test for sidebar-nav: route /board + expanded → no settings tree visible.
  • Vitest browser-mode test for sidebar-nav: collapsed + click Settings icon → flyout appears with leaves; leaf click navigates + closes flyout.
  • Vitest browser-mode test for routes/settings: SettingsGroupedNav not present in DOM; breadcrumb shows correct trail for sub-routes.

Manual QA

  • Toggle collapse/expand at runtime — no flicker, no layout shift.
  • Active highlight stays in sync when navigating via leaf click vs direct URL change.
  • Resize across the md breakpoint while on /settings/* — drawer/inline tree handover is clean.
  • just qa passes (typecheck + lint + format).

Out of scope

  • Search palette over settings sections — planned in milestone #36 "Settings unification".
  • Persisting per-group accordion expand state — default-expanded is fine for v1.
  • Reusing the flyout primitive for Agents/Forges trees — deferred; can follow if the pattern proves useful.
  • Sticky save bar / dirty-state handling — milestone #36 scope.
  • Renaming or reorganising existing NAV_GROUPS content — keep the current groups; structural changes belong to #36.

References

  • Nav-v2 spec: docs/specs/nav-consolidation.md
  • Settings unification milestone: #36
  • Nav-v2 shipping PR: #1090
  • Current sidebar component: apps/web/src/components/sidebar-nav.tsx (lines 30–304; collapsed state via useNavCollapsed() at line 39; data-nav attribute on <html>)
  • Current settings root: apps/web/src/routes/settings.tsx (NAV_GROUPS lines 45–73, SettingsGroupedNav lines 93–187)
  • Settings side-nav helper: apps/web/src/components/settings-side-nav.tsx
  • Base UI Menu reference: apps/web/src/components/avatar-menu.tsx
  • Tooltip wrapper: apps/web/src/components/tooltip.tsx
  • Decision notes (2026-05-11): operator picked B1 (flyout when collapsed) + Option 1 (inline auto-expand on /settings/* when expanded) + breadcrumb-only header on the settings page.
## User story As an operator, I want the Settings section to surface its inner tree inside the main sidenav — auto-expanded inline on `/settings/*` when the sidenav is expanded, and as a flyout when the sidenav is collapsed — so that the dashboard uses one nav column instead of two stacked ones, and section nav is discoverable in both rail modes. ## Background After nav-v2 (#1090) shipped, visiting `/settings` still renders a dedicated left column (`SettingsGroupedNav`) for section nav. Result: two stacked left columns (main sidenav + settings submenu), narrow content area, redundant hierarchy. Decision (operator review 2026-05-11): drop the settings page submenu, move section nav into the main sidenav with two behaviours — inline tree when expanded, flyout when collapsed. ## Behaviour summary **Expanded sidenav + route matches `/settings/*`:** - Settings footer item expands inline showing the full grouped tree. - Tree mirrors current `NAV_GROUPS`: GENERAL → General / Appearance / Voice input; AGENTS → Agent types / Agent config; FORGES → Service config / Repos / Labels; DATA → Secrets. - Active leaf gets highlighted state. - Group accordions default to expanded; toggle on click; not persisted in v1. **Expanded sidenav + non-settings route:** - Settings footer item renders as plain link with `⚙` icon (no tree). **Collapsed sidenav (rail mode, any route):** - Settings icon opens a Base UI Menu flyout anchored to the icon. - Flyout contains the same grouped tree. - Leaf click → navigate + close flyout. **Settings page (`/settings`, `/settings/*`):** - Drop `SettingsGroupedNav` left column. - Content becomes full-width within the existing AppShell slot. - Add thin breadcrumb header: `Settings › <Group> › <Leaf>`. - Existing in-page anchors (Quick Links, etc.) remain. ## Acceptance criteria ### Shared data - [ ] `NAV_GROUPS` extracted from `apps/web/src/routes/settings.tsx` (lines 45–73) into a new module `apps/web/src/lib/settings-nav.ts`. - [ ] `NavGroup` + `NavItem` types co-located in the shared module. - [ ] All current consumers (`SettingsGroupedNav`, `SettingsSideNav` in `apps/web/src/components/settings-side-nav.tsx`, any sub-route side nav) import from the shared module — no duplicated lists. ### Sidenav inline tree (expanded mode) - [ ] `apps/web/src/components/sidebar-nav.tsx` renders Settings as an expandable section when route matches `/settings*` and sidenav is not collapsed. - [ ] Tree renders all groups + leaves from shared `NAV_GROUPS`. - [ ] Active leaf highlighted with the same active styles as other nav items. - [ ] Non-settings routes render Settings as a plain link (no tree). - [ ] Group accordions toggle on click; default = all expanded; chevron indicates state. ### Sidenav flyout (collapsed mode) - [ ] When `data-nav="collapsed"` is set on `<html>`, clicking the Settings rail icon opens a Base UI Menu flyout. - [ ] Flyout uses existing primitives from `@base-ui-components/react/menu` — no new dependency. - [ ] Flyout positioned to the right of the rail icon, dismisses on outside click + Escape. - [ ] Tree content identical to expanded mode. - [ ] Leaf click invokes `navigate(to)` then closes the flyout. - [ ] Tooltip on the rail Settings icon follows the existing rail-icon tooltip pattern; does not double-fire when flyout is open. ### Settings page - [ ] `apps/web/src/routes/settings.tsx` no longer renders `SettingsGroupedNav`. - [ ] Content laid out full-width within AppShell content slot. - [ ] Breadcrumb header added: `Settings › <Group> › <Leaf>` (active group + leaf derived from current sub-route; `/settings` root shows `Settings › General`). - [ ] Breadcrumb segments are links (group label → first leaf of group; root → `/settings`). - [ ] `SettingsGroupedNav` component deleted if no remaining consumers. - [ ] Sub-routes (e.g. `/settings/service.tsx`) updated: drop any in-page `SettingsSideNav` that now duplicates the sidenav tree, OR keep it only where the sub-route has its own deeper sub-tree not covered by `NAV_GROUPS` — document the decision in the PR description. ### Mobile / small viewport - [ ] Existing mobile drawer behaviour preserved. - [ ] When the mobile drawer is open on `/settings/*`, tree renders inline (same as expanded mode). ### Tests - [ ] Vitest browser-mode test for `sidebar-nav`: route `/settings/appearance` + expanded → tree renders + Appearance leaf is active. - [ ] Vitest browser-mode test for `sidebar-nav`: route `/board` + expanded → no settings tree visible. - [ ] Vitest browser-mode test for `sidebar-nav`: collapsed + click Settings icon → flyout appears with leaves; leaf click navigates + closes flyout. - [ ] Vitest browser-mode test for `routes/settings`: `SettingsGroupedNav` not present in DOM; breadcrumb shows correct trail for sub-routes. ### Manual QA - [ ] Toggle collapse/expand at runtime — no flicker, no layout shift. - [ ] Active highlight stays in sync when navigating via leaf click vs direct URL change. - [ ] Resize across the `md` breakpoint while on `/settings/*` — drawer/inline tree handover is clean. - [ ] `just qa` passes (typecheck + lint + format). ## Out of scope - Search palette over settings sections — planned in milestone #36 "Settings unification". - Persisting per-group accordion expand state — default-expanded is fine for v1. - Reusing the flyout primitive for Agents/Forges trees — deferred; can follow if the pattern proves useful. - Sticky save bar / dirty-state handling — milestone #36 scope. - Renaming or reorganising existing `NAV_GROUPS` content — keep the current groups; structural changes belong to #36. ## References - Nav-v2 spec: `docs/specs/nav-consolidation.md` - Settings unification milestone: #36 - Nav-v2 shipping PR: #1090 - Current sidebar component: `apps/web/src/components/sidebar-nav.tsx` (lines 30–304; collapsed state via `useNavCollapsed()` at line 39; `data-nav` attribute on `<html>`) - Current settings root: `apps/web/src/routes/settings.tsx` (`NAV_GROUPS` lines 45–73, `SettingsGroupedNav` lines 93–187) - Settings side-nav helper: `apps/web/src/components/settings-side-nav.tsx` - Base UI Menu reference: `apps/web/src/components/avatar-menu.tsx` - Tooltip wrapper: `apps/web/src/components/tooltip.tsx` - Decision notes (2026-05-11): operator picked **B1** (flyout when collapsed) + **Option 1** (inline auto-expand on `/settings/*` when expanded) + breadcrumb-only header on the settings page.
claude-desktop added this to the nav-v2 milestone 2026-05-11 14:35:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#1104
No description provided.