Skip to content

Settings Rearchitecture — Single Page with Subnav

Consolidate all user-facing settings into a single page at /settings, with Workspace settings at the top and Account settings below. Reuse the existing “user menu subnav” visual style for an indented in-page subnav. The subnav must support scrollspy (active highlight on scroll) and smooth-scrolling when clicking items.

  • Page: /settings
  • Sections and anchors (top-to-bottom):
    • Workspace
      • #workspace
      • #workspace-users
      • #workspace-locations
      • #workspace-data-sources
      • #workspace-billing
    • Account
      • #account
      • #profile
      • #auth
      • #connections
      • #billing-profiles

Redirects:

  • Legacy Data Sources → /settings#workspace-data-sources
  • Legacy Connections → /settings#connections
  • Legacy Workspace Settings → /settings#workspace
  • Legacy Account Settings → /settings#account

Sidebar (left app nav):

  • Top:
    • Expand/collapse
    • Workspace selector
    • Grids
    • Leads
    • Settings → /settings (replaces Workspace Settings)
  • Bottom (user menu popover):
    • Keep the current subnav style and component. Update its items/links to:
      • Account settings → /settings#account
      • Billing settings → /settings#billing-profiles

Notes:

  • We are keeping the existing subnav styling; only the labels and hrefs change to point into the single page.

New route and layout:

  • apps/web-app/src/routes/Settings/SettingsPage.tsx — renders the whole settings page
  • apps/web-app/src/components/Settings/SettingsLayout.tsx — two-column layout
    • Left: sticky subnav using the existing “user menu subnav” styles (indented list)
    • Right: stacked section blocks with matching id attributes for anchors

Subnav and scrollspy:

  • apps/web-app/src/components/Settings/SettingsSubnav.tsx
    • Reuse user menu subnav component styles (same tokens/classes)
    • Items are grouped headings (Workspace, Account) with indented child items (users, locations, etc.)
  • apps/web-app/src/hooks/useScrollSpy.ts (IntersectionObserver) — existing or new hook

Sections (content components):

  • Workspace
    • WorkspaceOverviewSection (optional minimal anchor header) — id workspace
    • UsersSection — id workspace-users
    • LocationsSection — id workspace-locations
    • DataSourcesSection — id workspace-data-sources (moved here)
    • WorkspaceBillingSection — id workspace-billing
  • Account
    • AccountOverviewSection (optional anchor header) — id account
    • ProfileSection — id profile
    • AuthSection — id auth (change password, connect google)
    • ConnectionsSection — id connections (moved here)
    • BillingProfilesSection — id billing-profiles
  • apps/web-app/src/routes/routes.ts
    • Add Routes.Settings = '/settings'
    • Remove prior WorkspaceSettings and AccountSettings constants if present
  • Legacy redirects
    • Add lightweight redirect components for old paths to /settings#…
  • Keep the exact look-and-feel of the current user menu subnav (typography, spacing, hover/active states)
  • Indentation to visually indicate subsections under Workspace and Account
  • Smooth scroll on click; update history.replaceState to reflect the hash
  • Scrollspy updates active item based on visible section (offset to account for header height)
  • Keyboard and screen-reader friendly (focus moves to section heading on navigation)
  • Reuse existing queries/mutations for users, locations, data sources, connections, and billing profiles
  • Place forms and actions within their respective sections; show toasts and inline validation
  • Permissions:
    • Workspace sections gated by role (owner/admin vs member)
    • Account sections available to the authenticated user
  • Emit events for subnav navigation and settings updates, including section and result (success/failure)
  • Unit: useScrollSpy, subnav renders and active state handling
  • Integration: form submit → mutation → refetch per section
  • E2E: deep-link to anchors, ensure scrollspy highlights correct item; verify legacy redirects
  1. Routing and Sidebar
  • Add /settings route constant and page; add legacy redirects
  • Update sidebar: replace “Workspace Settings” with “Settings” → /settings
  • Update user menu subnav items to anchor into /settings
  1. Subnav and Layout
  • Build SettingsLayout two-column layout; sticky subnav (desktop), collapsible on mobile
  • Implement SettingsSubnav using existing user menu styles; wire useScrollSpy
  1. Workspace Sections
  • Implement Users, Locations, Data Sources, Workspace Billing sections; connect existing hooks
  1. Account Sections
  • Implement Profile, Auth, Connections, Billing Profiles; connect existing hooks
  1. QA and Accessibility
  • Responsive polish; keyboard focus to section headings on nav
  • Tests and telemetry validation; copy/empty states

✅ Milestone 1 — Shell, Nav, and Scaffolding (COMPLETED)

Section titled “✅ Milestone 1 — Shell, Nav, and Scaffolding (COMPLETED)”
  • ✅ Routing: added /settings route and legacy redirects to anchors
  • ✅ Sidebar: replaced Workspace Settings with Settings → /settings, moved Toggle Sidebar above Grids
  • ✅ Subnav: implemented SettingsSubnav with user menu styling, scrollspy, and smooth scroll
  • ✅ Scaffolding: rendered all section headers in page order with ids
  • ✅ User menu: updated to use React Router Links instead of page reload, removed modal components
  • Status: All acceptance criteria met. Deep-linking works, scrollspy active highlighting works, legacy redirects functional.

🔄 Milestone 2 — Workspace Sections Wiring (IN PROGRESS)

Section titled “🔄 Milestone 2 — Workspace Sections Wiring (IN PROGRESS)”
  • Users Section: Fully implemented with ListRecordLayout pattern
    • ✅ Table and card views with toggle
    • ✅ Add User panel (Sheet-based RecordPanel)
    • ✅ Perfect table borders: light gray/brown top, font-color header bottom, light gray/brown row bottoms
    • ✅ Zero state with proper padding and styling
  • Locations Section: Fully implemented with ListRecordLayout pattern
    • ✅ Table and card views with toggle
    • ✅ Add Location panel with Google Places integration
    • ✅ Consistent table border styling matching Users
    • ✅ Zero state with proper padding
  • 🚧 Data Sources Section: Needs conversion to ListRecordLayout pattern
  • 🚧 Connections Section: Needs conversion to ListRecordLayout pattern
  • Current Status: Users and Locations sections complete with consistent UI patterns. Need to convert remaining sections.
  • Profile, Auth (password/google connect), Connections (moved): connect live data/actions
  • Remove “(coming soon)” from wired Account sections
  • Acceptance:
    • Profile edits persist; auth flows functional; connections settings parity with legacy

Milestone 4 — Billing Scaffolding (Follow-up Project)

Section titled “Milestone 4 — Billing Scaffolding (Follow-up Project)”
  • Keep Workspace Billing and Billing Profiles headers rendered with “(coming soon)”
  • Add read-only placeholders and telemetry for interest; no live mutations
  • Acceptance:
    • Sections present, clearly labeled; no dead links or broken actions
  • A11y focus management on in-page nav; keyboard nav verified
  • E2E for anchors, scrollspy, redirects, and critical edits
  • Observability: events for subnav navigation and successful saves
  • Acceptance:
    • All checks pass; no regressions in legacy entry points
  • apps/web-app/src/routes/Settings/SettingsPage.tsx - Main settings page with Section/SubSection layout
  • apps/web-app/src/components/Settings/SettingsSubnav.tsx - Indented subnav with scrollspy
  • apps/web-app/src/hooks/useScrollSpy.ts - IntersectionObserver-based scrollspy hook
  • apps/web-app/src/hooks/usePanelState.ts - URL-driven state management for List/Record panels
  • apps/web-app/src/components/ui/section.tsx - Section, SubSection, SectionHeading primitives
  • apps/web-app/src/components/ListRecordLayout/ - Reusable List/Record panel pattern
    • ListRecordLayout.tsx - Main layout orchestrator
    • ListPanel.tsx - Left panel with search, view toggle, add button
    • RecordPanel.tsx - Right slide-in Sheet for record CRUD
  • apps/web-app/src/components/Settings/Users/ - Complete Users section
    • Users.tsx - Main component using ListRecordLayout
    • UsersTable.tsx - Table view with perfect border styling
    • UsersCards.tsx - Card view
    • UserRecordPanel.tsx - User invitation/editing form
  • apps/web-app/src/components/Settings/Locations/ - Complete Locations section
    • LocationsList.tsx - Main component using ListRecordLayout
    • LocationsTable.tsx - Table view with consistent border styling
    • LocationsCards.tsx - Card view
    • LocationRecordPanel.tsx - Location creation/viewing form
  • apps/web-app/src/components/app-sidebar.tsx - Updated with single Settings link and Toggle Sidebar
  • apps/web-app/src/components/nav-user.tsx - Updated user menu with React Router Links
  • apps/web-app/src/routes/LegacyRedirects/SettingsRedirects.tsx - Legacy URL redirects
  • Convert Data Sources section to ListRecordLayout pattern
  • Convert Connections section to ListRecordLayout pattern
  • Implement Account sections (Profile, Authentication, Billing Profiles)

A consistent pattern for sections with lists of records (Users, Locations, Data Sources, Connections):

  • ListPanel (left): Title, search, table/card view toggle, “Add” button
  • RecordPanel (right): Slide-in Sheet for viewing/creating/editing records
  • URL State: Entity, view mode, recordId, and panel mode managed via query parameters
  • Consistent Styling: All tables use the same 3-border pattern with brand colors

Established consistent table styling across all sections:

  1. Top border: 1px light gray/brown (border-t-[#3A2E2F]/20)
  2. Header bottom border: 1px standard font color (border-b-[#3A2E2F])
  3. Row borders: 1px light gray/brown bottom borders (border-b-[#3A2E2F]/20)
  • Section: py-8 vertical padding, contains multiple SubSections
  • SubSection: py-6 vertical padding, optional separator line
  • Consistent horizontal padding: Applied at page level (px-6) for perfect alignment