-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Settings page comprehensive redesign -- bring to dashboard quality bar #936
Description
Overview
The Settings page is functionally complete but visually and interactively far behind every other page in the dashboard. While the Dashboard has MetricCards with sparklines and count-up animations, the Task Board has drag-drop with optimistic updates, and the Providers page has polished card grids with health badges -- the Settings page is a flat form with collapsible sections. It looks and feels like a different product.
This issue covers a comprehensive redesign to bring the Settings page to the same quality bar as the rest of the dashboard, plus a dedicated sink configuration sub-page (absorbing #565).
Current Problems
Systemic issues (the page as a whole)
- No "at a glance" summary -- you cannot tell if your config is healthy, broken, or needs attention. Every other page opens with status indicators.
- Flat, repetitive layout -- every setting looks the same: label + badge + control. No visual hierarchy, no sense of importance. Wall of form fields.
- No animation or interaction polish -- no stagger entrance, no hover effects, no flash on WebSocket update, no transitions. Static and lifeless compared to Task Board cards.
- No sense of system health -- the Dashboard shows MetricCards with sparklines; the Settings page shows nothing about the impact or state of your configuration.
- Source badges are confusing -- "YAML" means nothing to most users. "DEFAULT" shown on every untouched setting is noise.
- "Restart" badge is unclear -- restart what? Container restart? Server restart? And there is no restart button anywhere on the page to act on it.
- Basic/advanced classification is wrong -- settings were categorized mechanically, not from a user perspective. CORS Allowed Origins and Rate Limiting are "basic" when they are clearly ops/advanced settings.
- Dependency messaging is robotic -- "Requires Enabled to be enabled" reads like a code comment, not a UI label.
Specific control issues (from visual inspection)
- Server Port (1-65535) as a slider -- nobody drags a slider to pick port 3001. Must be a number input.
- Rate Limit Max Requests (1-10000) as a slider -- same problem. Precise numeric values need text inputs, not sliders.
- Sliders should be reserved for settings where the exact number matters less and the user is choosing a position on a spectrum (e.g., opacity, volume, aggressiveness level). Most numeric settings in this page are precise values.
- "DEFAULT" badge on every untouched setting -- default is the normal state. It should not have a badge at all. Only show a badge when the value deviates from default (e.g., "Modified", "ENV override", "Config file"). Default = no badge.
- "YAML" badge -- confusing. If the value matches the default, show nothing. If it was explicitly set via config file, show something like "Config file" or just a subtle icon, not a prominent colored badge.
- Backup section: "Requires Enabled to be enabled" -- the dependency system works but the messaging is terrible. When "Enabled" is off, dependent settings should be visually greyed out/disabled with at most a subtle tooltip explaining why -- not a text label.
- CORS Allowed Origins should not be a "basic" setting -- it is a developer/ops concern.
- Rate Limiting section should not be "basic" -- same reasoning.
- Every single setting's level (basic vs advanced) needs to be re-evaluated from a user perspective, not a developer perspective. "Basic" should mean: settings a first-time user running a small org would reasonably want to adjust.
Design Decisions (from UX interview)
| Decision | Choice | Rationale |
|---|---|---|
| Health section | Compact row of StatPills/StatusBadges at top | Shows config health at a glance without dominating the page |
| Sink configuration | Dedicated sub-page (Settings > Observability) | Rich enough to warrant its own page -- sink cards, health, test buttons, log preview |
| Complexity management | Keep basic/advanced toggle | Conceptually fine, just needs correct classifications and better visual treatment |
| Impact awareness | Nice-to-have | Basic warnings (requires restart, affects N agents) but do not over-engineer |
| Row polish | Full treatment | Hover lift, flash on WS update, stagger entrance, status badge transitions |
| Code editor | Improve significantly | Visual diff, inline validation, split-pane, schema autocomplete (CodeMirror already integrated) |
| Namespace grouping | Keep as-is | Structure is fine, presentation needs overhaul |
Scope
1. Compact config health section
Add a compact summary row at the top of the Settings page, before the namespace sections. Shows at-a-glance system configuration health using existing design system components (StatPill, StatusBadge, ProgressGauge).
- Config completeness (how many settings are explicitly configured vs. running on defaults)
- Security posture indicator (e.g., auth enabled, scanning enabled, trust level)
- Budget status (limit set, current utilization if available)
- Backup status (enabled/disabled, last backup time, schedule)
- Settings needing attention count (e.g., settings with validation warnings, deprecated values)
2. Setting row redesign
Complete overhaul of how individual settings are presented.
Source badges:
- Remove "DEFAULT" badge entirely -- default is the absence of a badge, not the presence of one
- Rename "YAML" to "Config file" or remove if value matches default. Only show when the value was explicitly set in the config file to a non-default value.
- "ENV" badge stays -- important to know a value is locked by environment variable (read-only)
- "DB" becomes "Modified" -- clearer that the user changed this from default
- Default values should have subtle muted styling -- slightly lower opacity or lighter text to visually distinguish "untouched" from "explicitly configured"
Restart badge:
- Clarify what "Restart" means -- tooltip or label should say "Requires container restart to take effect"
- Consider: after saving a setting that requires restart, show an actionable banner at the top: "N settings require a container restart to take effect. [Restart now]" (if restart API exists) or "Restart containers via CLI:
synthorg restart"
Control type audit:
- Audit every setting and assign the correct control type based on the value's nature:
- Slider: Only for spectrum/preference values where exact number is less important (e.g., aggressiveness, quality level)
- Number input: For precise values like ports, request counts, time intervals, byte limits
- Text input: For strings, paths, hosts
- Toggle: For booleans
- Select/dropdown: For enums
- Tag input/chip list: For array settings (replace "one entry per line" textarea with a proper tag input)
- Specific fixes: Server Port, Rate Limit Max Requests, Schedule Hours, JWT Expiry Minutes, Min Password Length -- all should be number inputs, not sliders
Level (basic/advanced) re-evaluation:
- Re-evaluate every setting from the perspective of: "Would a first-time user running a small synthetic org reasonably want to adjust this?"
- Move to advanced: CORS, Rate Limiting, Server Host/Port, JWT settings
- Keep as basic: Budget limits, backup enable/disable, security scanning toggle, company name
- Document the rationale for each classification in the backend definition comments
Dependency UX:
- When a controller toggle (e.g., "Backup Enabled") is off, dependent settings should be:
- Visually greyed out (opacity + disabled state on controls)
- Non-interactive (disabled attribute)
- No text label like "Requires Enabled to be enabled" -- the visual state is self-explanatory
- Optional subtle tooltip on hover: "Enable backups to configure this setting"
3. Animation and interaction polish
Bring the Settings page to the same interaction quality as the Task Board and Dashboard.
Entrance animations:
- StaggerGroup/StaggerItem on namespace sections when the page loads
- StaggerItem on setting rows when a section expands (subtle, fast)
- Spring animation on the floating save bar (already exists, keep it)
Hover and focus:
- Setting rows: subtle background highlight on hover (bg-card-hover or similar)
- Optional: very subtle translate-y lift on hover (like Provider cards) -- evaluate if it feels right for dense rows
- Clear focus ring for keyboard navigation
Real-time feedback:
- Flash/highlight animation when a setting updates via WebSocket (like Task Board cards use useFlash)
- Smooth transition on source badge changes
- Count animation on the health section metrics (like Dashboard MetricCards)
Keyboard shortcuts:
- Cmd/Ctrl+S to save (when dirty state exists)
- Cmd/Ctrl+/ to focus search
- Escape to discard / close expanded section
Save/discard UX:
- Add discard confirmation dialog when there are unsaved changes (ConfirmDialog component)
- After save, brief success flash on the floating save bar before it dismisses
- If save partially fails, show which settings failed with inline error indicators
4. Sink configuration sub-page
Absorbs #565. When a user clicks into the Observability namespace (or a dedicated "Log Sinks" link), they navigate to a dedicated sub-page that looks like a mini version of the Providers page.
Layout:
- Header with "Log Sinks" title + "Add Sink" button
- Card grid (responsive, like Providers page) showing each configured sink
- Each sink card shows: name, type (console/file/custom), log level, format (JSON/text), enabled toggle, health indicator
- Click card to expand/open detail panel or inline editor
Sink card details:
- Enable/disable toggle (prominent, on the card)
- Log level dropdown
- Format selector (JSON/text)
- For file sinks: path, rotation config (max size, backup count), current file size
- "Test" button -- sends a test log line and shows it in a live preview area
- Real-time log preview: shows last N log lines from this sink (if API supports it)
Add sink flow:
- Modal or slide-in panel (Drawer component)
- Step-by-step: choose type > configure path/endpoint > set level > set format > enable
- Validation at each step
Dependencies:
- Requires feat: runtime sink configuration via SettingsService (add/remove/reconfigure log sinks) #564 (runtime sink configuration backend) to be complete first
5. Code editor improvements
Build on the existing CodeMirror 6 integration.
- Split-pane view: Original (read-only, left) vs. edited (right) with synchronized scrolling
- Visual diff gutters: Highlight changed lines with diff markers (green for additions, yellow for modifications)
- Inline validation: Show validation errors as CodeMirror diagnostics (red underlines with hover tooltips), not just a banner at the top
- Schema autocomplete: CodeMirror completions based on the settings schema -- suggest valid keys, enum values, and value ranges
- Format improvements: Better JSON/YAML formatting with consistent indentation
- Diff summary: Before save, show a summary "N settings changed" with expandable list of specific changes
6. Miscellaneous polish
- Empty state: If no settings exist (defensive), show EmptyState component with icon
- Error boundaries: Wrap each namespace section in ErrorBoundary level="section" (if not already)
- Loading: Individual namespace skeleton loading (currently one global skeleton)
- Search improvements: Highlight matching text in search results, show result count
- Responsive: Verify settings page works well at all breakpoints
- Accessibility: aria-live announcements on save success/error, proper heading hierarchy for sections/groups
Planning Directive
During implementation planning, proactively seek additional opportunities to bring the Settings page to first-in-class quality. The items above are the known issues -- but there will be patterns, interactions, or visual treatments from the Dashboard, Task Board, Org Chart, or Providers pages that could be adopted here but were not identified during this review. The planner must:
- Compare every interaction pattern on the Settings page against the best equivalent on other pages
- Look for missing micro-interactions (transitions, feedback loops, loading states)
- Evaluate whether any settings would benefit from visualization (e.g., budget settings showing a gauge, rate limits showing current utilization)
- Consider whether any new shared components should be created (e.g., a NumberInput component distinct from SliderField, a TagInput for array settings)
- Identify any accessibility gaps not listed above
- Review the settings page on both dark and light themes for visual consistency
- Study best-in-class settings UIs from other products (VS Code settings, Grafana, Vercel dashboard) for inspiration
The goal is not just to fix the listed issues but to make the Settings page something you would show off in a demo -- on par with the Dashboard and Task Board.
Acceptance Criteria
Config health section
- Compact health row renders above namespace sections
- Shows config completeness, security posture, budget status, backup status
- Health indicators update in real-time via WebSocket
- Uses existing design system components (StatPill, StatusBadge)
Setting row redesign
- "DEFAULT" badge removed -- default settings have no badge, just muted styling
- "YAML" badge replaced with "Config file" (only shown for non-default values)
- "Restart" badge has tooltip explaining what restart means
- Actionable restart banner appears when restart-requiring settings are saved
- Every setting audited for correct control type (no sliders for precise values)
- Server Port, Rate Limit Max Requests, Schedule Hours, JWT Expiry = number inputs
- Array settings use tag/chip input instead of "one per line" textarea
- Every setting's basic/advanced level re-evaluated from user perspective
- CORS, Rate Limiting, Server Host/Port, JWT moved to advanced
- Dependencies: dependents greyed out when controller is off, no text labels
- Dependency tooltip on hover explains what needs to be enabled
Animation and interaction
- StaggerGroup entrance on page load for namespace sections
- StaggerItem entrance on section expand for setting rows
- Hover highlight on setting rows
- Flash animation on WebSocket-driven setting updates
- Cmd/Ctrl+S keyboard shortcut for save
- Cmd/Ctrl+/ keyboard shortcut to focus search
- Discard confirmation dialog when unsaved changes exist
- Success flash on save bar before dismissal
Sink configuration sub-page
- Dedicated route: /settings/observability/sinks (or similar)
- Card grid layout showing all configured sinks
- Each card: name, type, level, format, enabled toggle, health indicator
- Click-to-expand detail editing
- Add sink flow (modal or Drawer)
- Test button with live log preview
- Enable/disable per sink
- Level and format adjustment per sink
- File sink: path, rotation config, current size display
Code editor improvements
- Split-pane view (original vs. edited)
- Diff gutter markers on changed lines
- Inline validation via CodeMirror diagnostics
- Schema-aware autocomplete for keys, enum values, ranges
- Diff summary before save ("N settings changed" with list)
General polish
- Search highlights matching text in results
- Search shows result count
- Error boundaries per namespace section
- aria-live announcements on save/error
- Proper heading hierarchy (h2 for namespaces, h3 for groups)
- Responsive layout verified at all breakpoints
- Dark and light theme visual consistency verified
Supersedes
- Absorbs feat: sink configuration UI in web dashboard settings page #565 (sink configuration UI) -- the sink sub-page scope here is a superset
Dependencies
- feat: runtime sink configuration via SettingsService (add/remove/reconfigure log sinks) #564 (runtime sink configuration via SettingsService) -- backend must be complete before the sink sub-page can be built. All other items in this issue can proceed independently.
References
- Dashboard page (DashboardPage.tsx) -- quality bar for metrics and animation
- Task Board page (TaskBoardPage.tsx) -- quality bar for interaction and real-time updates
- Providers page (ProvidersPage.tsx) -- quality bar for card grid layout
Implementation Status (feat/settings-redesign branch)
Completed
- Namespace tab bar with icons for quick filtering (replaces collapsible-only navigation)
- All sliders removed -- every numeric setting uses number inputs
- TagInput chip component for array settings (CORS origins, exclude paths)
- Source badges: only "Modified" (db) and "ENV" shown; yaml/default hidden
- Stagger entrance animations on section expand (theme-preset aware)
- Tab-switch cross-fade using AnimatePresence + animation theme preset
- Flash animation on WebSocket setting updates
- Keyboard shortcuts: Ctrl+S save, Ctrl+/ search focus
- Discard confirmation dialog before losing unsaved changes
- Search highlighting with result count badge
- Code editor split-pane with diff gutters (changed/added/removed), inline validation via @codemirror/lint, schema-aware autocomplete
- JSON-type values properly embedded in code editor (no escaped backslashes)
- Dedicated sink sub-page at /settings/observability/sinks with card grid, full CRUD (add/edit/enable/disable/level/format/rotation/routing), test button, WebSocket auto-refresh
- Manage Log Sinks link inside observability section (matches setting row layout)
- Backend sink endpoints: GET /settings/observability/sinks + POST /settings/observability/sinks/_test with error handling, sanitized responses, consistency validators
- 6 API settings reclassified to advanced (server host/port, CORS, rate limiting, JWT)
- "API" renamed to "Server" for clarity
- Density token system fully adopted (p-card, gap-grid-gap, gap-section-gap)
- Density ordering fix: dense < balanced < medium < sparse (was misordered)
- Generic key display names: "Enabled" -> "Backup Enabled", "Backend" -> "Memory Backend"
- Dependency indicator removed (visual greying of dependents is self-explanatory)
- Responsive layout for narrow screens
- RestartBanner shows only when restart-needed settings are saved
- Error handling: list_sinks catches ValueError/SettingNotFoundError, test_sink_config sanitizes errors
- Pydantic model fixes: allow_inf_nan=False, NotBlankStr, consistency validators
- CONSOLE_SINK_ID deduplicated across modules
- 36 new tests, 8 new Storybook stories, doc updates across 4 design pages + web/CLAUDE.md
- 3 pre-existing flaky test timeouts fixed (Sidebar, LoginPage, TaskDetailPanel)
Additional improvements (beyond original scope)
- Created chore: audit full web dashboard for hardcoded design token violations #938 for full web dashboard design token audit + audit agent
- WebSocket real-time updates for sink sub-page (system channel subscription)
- Animation preset integration across all settings components (useAnimationPreset hook)
Remaining (follow-up)
- Live log preview in sink drawer (needs WebSocket streaming infrastructure)
- Health metrics on Dashboard (user decided these don't belong on Settings page)
- Full design token audit across all pages (chore: audit full web dashboard for hardcoded design token violations #938)