feat(settings): wire up and rebuild the account & app settings surface#746
Conversation
Turn the settings dialog from a mostly-static display into a fully functional, persisted preferences surface, and polish the design. Behaviour - Add a per-browser app-preferences store (use-app-preferences.ts) mirroring the existing external-store pattern: density, motion, jurisdiction, population, answer style, default landing, personalisation, and notification toggles, with defensive normalisation of stored values. - Extend the theme hook to a light/dark/system preference (setPreference) while keeping theme/toggleTheme; "system" follows the OS and stores no pin. - Density and reduce-motion now take real effect via html[data-density] font scaling and an html[data-motion="reduced"] suppression block, applied before first paint by the layout pre-hydration script so nothing flashes in. - Privacy actions clear recent searches / saved items and reset preferences, with live counters that disable the action when there is nothing to clear. UI - Functional desktop scroll-spy navigation across eight sections. - Interactive controls: wrapping segmented controls (readable long labels on narrow screens), accessible native selects, and role="switch" toggles, all design-token based and legible in light/dark and forced-colors. - Complete Account, Clinical defaults, App preferences, Personalisation, Notifications, Privacy, Keyboard shortcuts, and Help & About sections. Drops the now-unused theme/onToggleTheme props from the two call sites; the required headings, row test ids, and close affordance are preserved. Tests: add theme preference and app-preference normalisation coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiRMGogS7jxgngFRYEHjw3
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Warning Review limit reached
Next review available in: 24 seconds Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe pull request adds persisted application preferences, expanded theme preference state, density and motion attributes, and a reworked settings dialog with section navigation, privacy actions, accessibility controls, callback wiring, and validation tests. ChangesSettings and Preference Controls
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Clinician
participant SettingsDialog
participant useAppPreferences
participant useTheme
participant BrowserStorage
participant documentElement
Clinician->>SettingsDialog: Change application or theme preference
SettingsDialog->>useAppPreferences: setPreference(key, value)
SettingsDialog->>useTheme: setPreference(theme)
useAppPreferences->>BrowserStorage: Persist normalized preferences
useTheme->>BrowserStorage: Persist theme preference
useAppPreferences->>documentElement: Apply data-density and data-motion
useTheme->>documentElement: Apply dark class and theme-color metadata
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@copilot resolve the merge conflicts in this pull request |
…components-xe4zky # Conflicts: # src/components/clinical-dashboard/settings-dialog.tsx
Merge conflicts resolved in |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/clinical-dashboard/recent-query-storage.ts`:
- Around line 23-33: Update the recent-query counting logic in the
sessionStorage iteration so JSON parsing failures for one key are caught and
ignored locally, while processing continues for other matching keys. Keep valid
array entries counted as before, and reserve the outer fallback for broader
storage-access failures rather than malformed individual values.
In `@src/components/clinical-dashboard/settings-dialog.tsx`:
- Line 695: Update the privacy notice fallback in the settings dialog to avoid
claiming that the app never stores patient-identifying information; use wording
that clearly warns users that recent queries are retained verbatim in
sessionStorage and should not contain such information. Preserve the
privacyNotice override behavior.
In `@src/components/clinical-dashboard/use-theme.ts`:
- Around line 29-31: Update getPreferenceSnapshot and the corresponding
theme-preference write logic to guard localStorage reads and writes against
storage exceptions. When storage is unavailable or blocked, preserve the
in-memory/session-only theme state and continue returning or applying the
preference without crashing; retain the existing localStorage behavior when
access succeeds.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d40debce-fbbf-4778-b27a-920573072370
📒 Files selected for processing (11)
src/app/globals.csssrc/app/layout.tsxsrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/global-search-shell.tsxsrc/components/clinical-dashboard/recent-query-storage.tssrc/components/clinical-dashboard/settings-dialog.tsxsrc/components/clinical-dashboard/use-app-preferences.tssrc/components/clinical-dashboard/use-theme.tssrc/lib/theme.tstests/app-preferences.test.tstests/theme.test.ts
💤 Files with no reviewable changes (2)
- src/components/ClinicalDashboard.tsx
- src/components/clinical-dashboard/global-search-shell.tsx
…privacy copy - countRecentQueries: isolate a corrupt sessionStorage entry to its own key so one malformed value no longer zeroes the total and wrongly disables the "Clear recent searches" action. - use-theme: guard localStorage reads/writes against blocked-storage throws (Safari private mode, quota) with an in-memory fallback, matching the use-sidebar-collapsed / use-app-preferences pattern, so a blocked store no longer crashes the settings render or aborts a theme change. - settings-dialog: replace the inaccurate "never stores patient-identifying information" privacy notice — recent searches are retained verbatim in this browser — with wording that reassures on local-only storage while warning against entering PHI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiRMGogS7jxgngFRYEHjw3
…rences Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiRMGogS7jxgngFRYEHjw3
…components-xe4zky
…components-xe4zky
…components-xe4zky
…components-xe4zky
Summary
The settings dialog was largely a static display: the left-hand navigation didn't navigate, and most rows (clinical defaults, density, notifications…) were read-only labels with no persistence or effect. This PR turns it into a fully wired, persisted, and polished preferences surface without changing any clinical logic.
New preferences store —
use-app-preferences.ts, mirroring the existinguse-theme/use-sidebar-collapsedexternal-store pattern (localStorage + custom event, SSR-safe, in-memory fallback). Persists density, motion, jurisdiction, population, answer style, default landing, personalisation, and notification toggles, with defensive per-field normalisation of stored values.Theme → light / dark / system — extended the theme hook with a
preference+setPreference(keepingtheme/toggleTheme). "System" follows the OS and stores no pin, so the existing pre-hydration script keeps resolving it.Preferences that take real effect
html[data-density](comfortable is the untouched default).html[data-motion="reduced"]suppression block mirroring theprefers-reduced-motionrules.layout.tsxinline script so nothing flashes in.Privacy actions — clear recent searches, clear saved items, and reset preferences, wired to the real storage helpers with live counters that disable the action when there's nothing to clear.
UI / design
role="switch"toggles — all design-token based, legible in light/dark and forced-colors.Drops the now-unused
theme/onToggleThemeprops from the two call sites. The required section headings, rowdata-testids, and the close affordance are preserved so the existingui-smokesettings contract still holds.Verification
npm run typecheck— clean for allsrc/files (pre-existing test-only failures come from@testing-library/@axe-coredev-deps missing in this environment, unrelated to this change).npm run lint— clean on every changed file.pdf-extraction-budgetPython-subprocess kill timing). Added coverage for the new theme preference resolver and app-preference normalisation.next buildcompiled successfully in 35.2s; the subsequent TS pass fails only ontests/setup/jsdom.setup.ts(@testing-librarydev-dep missing in this env — pre-existing, also fails onmain).npm run verify:pr-local— Verification not run: this environment'snode_modulesis missing the@testing-library/@axe-coredev-dependencies, which breaks the build's TS pass and the DOM/UI suites regardless of this change; substituted the checks above.npm run verify:ui— UI verification not run: the@testing-library/@axe-coredev-dependencies are absent from this environment, so the Chromium UI gate cannot run here; substituted manual cross-theme, cross-viewport Playwright QA and recommend running the formal gate in CI.Risk and rollout
Clinical Governance Preflight
This change is a local, non-PHI preferences UI and does not alter ingestion, answer generation, search/ranking, source rendering, document access, or clinical output logic; every item below remains true and unchanged.
Clinical KB Database(sjrfecxgysukkwxsowpy)Notes
main(an iOS Safari sizing fix on the settings layout div) was resolved on-branch in83ae1ae9, keepingmain'sh-full/max-h-fullfix alongside this branch's desktop sizing.Generated by Claude Code
Summary by CodeRabbit