Skip to content

🎛️ feat: Redesign Settings with Registry-Driven Dialog, Search, and Mobile Drill-In#13722

Merged
danny-avila merged 25 commits into
devfrom
settings-refactor
Jun 18, 2026
Merged

🎛️ feat: Redesign Settings with Registry-Driven Dialog, Search, and Mobile Drill-In#13722
danny-avila merged 25 commits into
devfrom
settings-refactor

Conversation

@berry-13

@berry-13 berry-13 commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

The settings dialog had grown into eight tabs of uneven weight, with a few settings in odd places (for example "Display username in messages" living under Account), no way to find a setting without knowing its tab, and a layout that felt cramped. This reworks it.

Everything now renders from a single registry of settings, so the tab view and the new search share one source of truth.

Layout. Six tabs (General, Chat, Speech, Data & Privacy, Account, About) with named sections. A few settings moved to where they actually belong (username display to Chat, keep-screen-awake to General > Accessibility). The one-toggle Personalization tab is gone and Memory folded into Data & Privacy.

No advanced disclosure. All settings are visible. Destructive actions (clear chats, delete cache, revoke keys, delete account) sit in an always-visible Danger zone with its own styling.

Search. A search box filters every setting by label plus keyword synonyms, and results render the real controls so you can change a setting straight from there.

Mobile. The horizontal tab strip is replaced with a drill-in: a full-width list of tabs, tap one to open its content with a back button. Desktop keeps the sidebar and content side by side.

Also in here: the new About panel is wired in (its copy button now uses the shared CopyButton), Archived chats moved out of settings into the account menu next to My Files, dark mode color tokens were fixed where labels and the close/clear buttons were invisible on the dark panel, the speech engine/voice/language dropdowns and the autoplay switch now disable along with their parent toggle (this needed a disabled prop on the shared Dropdown), and row spacing was standardized.

Leaf controls are reused as-is and no store atom keys changed, so existing preferences carry over. The eight old settings container components are removed.

c95a681f-7e7b-4e40-acee-270ce197312f

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Translation update

Testing

Added unit and component tests for the registry, the search filter, the sidebar, the dialog shell, and the disclosure behavior. Also verified by hand against a running dev build:

  • Tab navigation and the section grouping on each tab.
  • Search filtering and clearing, including results rendering live controls.
  • The Danger zone styling, and that destructive actions are always visible.
  • Speech: toggling STT/TTS off disables the dependent dropdowns and switches.
  • Mobile drill-in: list, drill into a tab, back, and search.
  • Archived chats opening from the account menu.

Checked the above in both light and dark mode, at desktop and mobile widths.

Test Configuration:

  • Node 24, local dev build (frontend and backend), Chromium.

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

berry-13 added 20 commits June 12, 2026 19:50
… search, results a11y

- SpeechControls.tsx: read sttExternal/ttsExternal from useGetCustomConfigSpeechQuery
  instead of hardcoding false, so external engine options appear on qualifying deployments
- Sidebar: Escape clears search input when non-empty, stops propagation to avoid closing dialog
- Content: persistent aria-live="polite" wrapper covers both populated results and empty state
- context: useMemo on returned ctx object so Content's useMemo deps are referentially stable
- locales/README.md: update stale path from deleted General.tsx to Selectors.tsx
…, add About

- Re-categorize settings into logical groups (username display -> Chat/Messages,
  keep-screen-awake -> Accessibility, fork/prompts surfaced into Chat sections)
- Dissolve thin Personalization tab; move Memory into Data & Privacy
- Remove the Advanced collapsible; all settings always visible, destructive
  actions grouped in an always-visible Danger zone
- Wire the new About tab into the registry-driven dialog
- Standardize spacing with bordered, evenly-divided section cards
- Use semantic text-text-* / border tokens so dark mode renders correctly
- Sync LangSelector language-loading indicator from dev
Add an Archived chats item to the account dropdown next to My Files,
opening the archived chats table in a modal. Removes it from the
settings dialog where it no longer fit the data/privacy grouping.
- Flatten the build-info into a single divided key/value list (drop the
  redundant inner card now that it sits inside a section card)
- Replace the hand-rolled copy button with the shared animated CopyButton
- Shorten the copied label so it fits the button without clipping
Leaf control labels rendered without a text color and fell back to the
browser default (black), making them invisible on the dark panel. Set
text-text-primary on the section and search-results row containers so
labels inherit a visible color, matching the old container behavior.
The plain multiplication-sign close button had no text color and was
invisible on the dark panel. Replace it with the lucide X icon using
text-text-secondary/hover:text-text-primary so it shows in both themes.
… only

The account-settings popover drew a 2px ring around the active menu item.
Remove that override so items show only the standard hover background,
consistent with every other menu.
The settings search used type=search, whose native WebKit clear control
rendered as a blue X. Switch to a text input and add a real lucide X
clear button styled text-text-secondary, shown only when there's a query.
… off

Add a disabled prop to the shared Dropdown component, then gate the
speech engine/voice/language dropdowns and the automatic-playback switch
on their parent toggle (speechToText / textToSpeech), matching the
controls that already disabled correctly.
On small screens the horizontal scrolling tab row is replaced with a
full-width vertical list (with chevrons); tapping a tab drills into its
content with a Back header. Searching shows results full-width. Desktop
keeps the side-by-side sidebar + content layout unchanged.
Copilot AI review requested due to automatic review settings June 13, 2026 00:34
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_nav_about_diagnostics_heading
  • com_nav_about_version_heading
  • com_nav_chat_commands
  • com_nav_chat_commands_info
  • com_nav_commands
  • com_nav_setting_balance
  • com_nav_setting_data
  • com_nav_setting_personalization
  • com_ui_no_personalization_available
  • com_ui_settings_label_archived
  • com_ui_settings_section_advanced
  • com_ui_settings_section_history
  • com_ui_settings_section_input
  • com_ui_settings_section_rendering
  • com_ui_settings_section_shared
  • com_ui_simple

⚠️ Please remove these unused keys to keep the translation files clean.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR redesigns the client Settings UI into a registry-driven dialog with unified search and an improved mobile “drill-in” navigation, while keeping existing preference storage intact.

Changes:

  • Replaced the legacy multi-tab settings containers with a single SettingsDialog driven by a centralized settings registry (tabs/sections/visibility).
  • Added full-settings search that filters by localized labels and keyword synonyms, rendering the real controls in results.
  • Improved control behavior and UI polish (e.g., Dropdown gains disabled, speech dropdowns/switches disable when their parent toggle is off; About copy uses shared CopyButton; archived chats moved to account menu).

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/client/src/components/Dropdown.tsx Adds disabled support and disabled styling for shared dropdown control.
client/src/style.css Removes a popover-specific active-item ring style.
client/src/locales/README.md Updates locale docs to point to new language selector file location.
client/src/locales/en/translation.json Tweaks About copy text and adds many new settings/search/section labels.
client/src/components/Share/ShareView.tsx Updates imports for moved theme/language selectors.
client/src/components/Nav/SettingsTabs/Speech/TTS/VoiceDropdown.tsx Disables voice dropdown when TTS is off.
client/src/components/Nav/SettingsTabs/Speech/TTS/EngineTTSDropdown.tsx Disables TTS engine dropdown when TTS is off.
client/src/components/Nav/SettingsTabs/Speech/TTS/AutomaticPlaybackSwitch.tsx Disables autoplay switch when TTS is off.
client/src/components/Nav/SettingsTabs/Speech/STT/LanguageSTTDropdown.tsx Disables STT language dropdown when STT is off.
client/src/components/Nav/SettingsTabs/Speech/STT/EngineSTTDropdown.tsx Disables STT engine dropdown when STT is off.
client/src/components/Nav/SettingsTabs/Speech/Speech.tsx Removes legacy Speech tab container implementation.
client/src/components/Nav/SettingsTabs/Personalization.tsx Removes legacy Personalization tab (memory folded elsewhere).
client/src/components/Nav/SettingsTabs/index.ts Updates exports to match new Settings organization.
client/src/components/Nav/SettingsTabs/General/ThemeSelector.spec.tsx Updates test import path for Theme selector.
client/src/components/Nav/SettingsTabs/General/Selectors.tsx Splits selectors out of the old General container; keeps Theme/Lang controls.
client/src/components/Nav/SettingsTabs/General/LangSelector.spec.tsx Updates test import path for Language selector.
client/src/components/Nav/SettingsTabs/General/ArchivedChatsModal.tsx New archived chats modal for account menu entry.
client/src/components/Nav/SettingsTabs/General/ArchivedChats.tsx Removes archived chats control from Settings (moved to menu).
client/src/components/Nav/SettingsTabs/Data/Data.tsx Removes legacy Data tab container implementation.
client/src/components/Nav/SettingsTabs/Commands/Commands.tsx Removes legacy Commands tab container implementation.
client/src/components/Nav/SettingsTabs/Chat/Chat.tsx Removes legacy Chat tab container implementation.
client/src/components/Nav/SettingsTabs/Balance/Balance.tsx Removes legacy Balance tab container implementation.
client/src/components/Nav/SettingsTabs/Account/Account.tsx Removes legacy Account tab container implementation.
client/src/components/Nav/SettingsTabs/Account/Account.spec.tsx Removes tests for legacy Account container.
client/src/components/Nav/SettingsTabs/About/About.tsx Updates About layout and uses shared CopyButton UX.
client/src/components/Nav/Settings/types.ts Introduces Settings tab/section metadata and context types.
client/src/components/Nav/Settings/SpeechControls.tsx Adds wrappers to wire custom speech config into engine dropdowns.
client/src/components/Nav/Settings/Sidebar.tsx New sidebar with search box and tab list (mobile chevrons supported).
client/src/components/Nav/Settings/Section.tsx New section wrapper with optional “danger” styling.
client/src/components/Nav/Settings/search.ts Implements diacritic-insensitive search matching + filtering.
client/src/components/Nav/Settings/registry.tsx Central registry of settings entries (tab/section/label/visibility/component).
client/src/components/Nav/Settings/MemoryToggle.tsx Rehomes memory preference toggle from removed Personalization tab.
client/src/components/Nav/Settings/index.ts Exposes the new SettingsDialog entry point.
client/src/components/Nav/Settings/Dialog.tsx New settings dialog shell with mobile drill-in and search mode.
client/src/components/Nav/Settings/controls.tsx New registry-friendly wrappers for toggles and theme/lang settings.
client/src/components/Nav/Settings/context.tsx Computes visibility context (permissions, config flags, provider state).
client/src/components/Nav/Settings/Content.tsx Renders sections or search results using the registry.
client/src/components/Nav/Settings/BillingControls.tsx Extracts balance controls into registry-friendly components.
client/src/components/Nav/Settings/tests/Sidebar.spec.tsx Adds unit tests for sidebar rendering and search input behavior.
client/src/components/Nav/Settings/tests/search.spec.ts Adds unit tests for normalization and query matching.
client/src/components/Nav/Settings/tests/registry.spec.ts Adds unit tests validating registry integrity and translation keys.
client/src/components/Nav/Settings/tests/Dialog.spec.tsx Adds component tests for dialog default render and search mode switching.
client/src/components/Nav/Settings.tsx Switches top-level Settings entry to render the new SettingsDialog.
client/src/components/Nav/Settings.spec.tsx Removes tests for legacy Settings dialog implementation.
client/src/components/Nav/AccountSettings.tsx Adds “Archived chats” entry to account menu and renders new modal.
client/src/components/Audio/Voices.tsx Adds disabled prop to voice dropdowns and forwards to shared Dropdown.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client/src/components/Nav/Settings/controls.tsx Outdated
berry-13 added 2 commits June 13, 2026 16:27
…ew notes

- Drop the i18n keys left unused after the refactor (old Commands/Balance/
  Personalization tab labels, the Speech simple/advanced labels, and the
  former About section headings)
- Sort imports in the rebased files the lint-staged hook never touched
- Guard the language fallback against an empty navigator.languages
- Import the RefObject type instead of leaning on the React namespace
Add an opt-in searchable mode to the shared Dropdown (Ariakit Select +
Combobox) and use it for the language selector, which has 40+ options.
The trigger styling is unchanged so it stays consistent with the other
settings rows; only the popover gains a filter input.

Accessibility: the filtered listbox is labeled, the empty state is moved
out of the listbox and announced via an aria-live status region, and the
decorative selected-state checkmark is hidden from assistive tech.
@berry-13 berry-13 marked this pull request as ready for review June 13, 2026 18:59
@berry-13 berry-13 changed the title Settings redesign: registry-driven dialog, search, and mobile drill-in 🎛️ feat: Redesign Settings with Registry-Driven Dialog, Search, and Mobile Drill-In Jun 13, 2026
@danny-avila

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70758ef10f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/components/Nav/Settings/Sidebar.tsx
Comment thread client/src/components/Nav/Settings/SpeechControls.tsx
Comment thread client/src/components/Nav/Settings/registry.tsx
- Fall back to the General tab when the active tab becomes hidden
  (e.g. About when buildInfo is disabled) instead of rendering an
  empty panel.
- Normalize a deprecated/invalid engineTTS (e.g. 'edge') back to
  browser during speech init so read-aloud controls keep rendering.
- Hide the cloud browser voices toggle unless Browser TTS is active.
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77966dd3bb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/components/Nav/Settings/Dialog.tsx Outdated
berry-13 added 2 commits June 16, 2026 21:12
…llision

The agent builder spec asserted the creation toast with a non-exact
getByText, which also matched Radix Toast's transient role="status"
announce region ("Notification Successfully created ..."), causing a
strict-mode violation. Mirror the mcp spec by using { exact: true }.
Wrap the non-search settings body in Tabs.Content so the selected
panel gets role=tabpanel with Radix's id/aria-labelledby wiring,
resolving the aria-controls target on each tab trigger. Search
results stay a labeled live region (the tab list is hidden during
mobile search, so a tabpanel aria-labelledby would dangle).
@danny-avila

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: c884633d54

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila danny-avila merged commit 9de3249 into dev Jun 18, 2026
31 checks passed
@danny-avila danny-avila deleted the settings-refactor branch June 18, 2026 12:51
danny-avila added a commit that referenced this pull request Jun 20, 2026
…le Endpoints (#13864)

Adds a "Provider API keys" entry under Settings → Data controls → API keys
that lists every endpoint requiring a user-provided credential and lets users
set or rotate its key via SetKeyDialog. This is always reachable, so keys can
be managed even when `interface.modelSelect` is hidden by `modelSpecs`.

The endpoint list is filtered the same way the mention popover and model
selector menu are:
- No modelSpecs → every user-provided endpoint.
- modelSpecs configured → limited to spec endpoints ∪ `modelSpecs.addedEndpoints`.
- agents reachable (with access) → expanded to the agents `allowedProviders`
  (all providers when unrestricted).

Reworks #13303 onto the registry-driven Settings dialog (#13722); the prior
standalone tab and the `APIKeys` directory are superseded (the latter also
collided with the agent `ApiKeys` feature from #13819).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants