Adds item-level search inside Settings so users can find concrete settings like provider auth, agent mode, terminal font size, tunnel options, notification events, and similar controls instead of only filtering top-level pages. Groups search results by Settings page and shows localized labels plus optional descriptions where useful. Supports keyboard navigation with Arrow Up/Down, Enter, and Escape, matching the existing autocomplete interaction style. Opens the correct Settings page or split-page draft state before scrolling to the matching control. Highlights the matched setting with a subtle token-based background so users can see where they landed without an aggressive outline. Adds explicit data-settings-item anchors across Settings pages and a centralized search registry with runtime/mobile availability guards. Updates Settings UI skill guidance so future Settings changes keep search registry entries, anchors, localization, and availability guards in sync.
151 lines
7.3 KiB
Markdown
151 lines
7.3 KiB
Markdown
# Settings Item Search Plan
|
|
|
|
## Goal
|
|
|
|
Add Settings search that finds individual settings items, not only top-level pages.
|
|
|
|
The search should behave like this:
|
|
|
|
- User types a query in the Settings navigation area.
|
|
- Results show matching concrete settings, grouped or labeled by their Settings page.
|
|
- Each result shows the item title and, when available, its description.
|
|
- Clicking a result opens the correct Settings page.
|
|
- After the page renders, the matching row/card/section scrolls into view.
|
|
- The matched item gets a short visual highlight so the user can see where they landed.
|
|
|
|
## Current Architecture Notes
|
|
|
|
- Settings shell lives in `packages/ui/src/components/views/SettingsView.tsx`.
|
|
- Page metadata and slugs live in `packages/ui/src/lib/settings/metadata.ts`.
|
|
- Settings localization lives in `packages/ui/src/lib/i18n/messages/*.settings.ts`.
|
|
- Settings UI text is read through `useI18n()` and `t(key)`.
|
|
- Standard page wrappers live in `packages/ui/src/components/sections/shared/`.
|
|
|
|
## Proposed Architecture
|
|
|
|
Use an explicit searchable item registry instead of scraping React or the DOM.
|
|
|
|
Each searchable item should contain:
|
|
|
|
- `id`: stable item id, for example `appearance.language`.
|
|
- `page`: target `SettingsPageSlug`, for example `appearance`.
|
|
- `titleKey`: localized title key.
|
|
- `descriptionKey`: optional localized description key.
|
|
- `keywords`: optional non-visible search helpers.
|
|
- `isAvailable`: optional runtime/mobile guard for item-level availability.
|
|
|
|
Example:
|
|
|
|
```ts
|
|
{
|
|
id: 'appearance.language',
|
|
page: 'appearance',
|
|
titleKey: 'settings.appearance.language.label',
|
|
descriptionKey: 'settings.appearance.language.description',
|
|
keywords: ['locale', 'translation', 'ui language'],
|
|
}
|
|
```
|
|
|
|
## Implementation Steps
|
|
|
|
1. Create `packages/ui/src/lib/settings/search.ts`.
|
|
- Export `SETTINGS_SEARCH_ITEMS`.
|
|
- Export a helper to build localized search results from `t()`.
|
|
- Filter by page availability and `visiblePageSlugs`.
|
|
|
|
2. Add search UI to `SettingsView.tsx`.
|
|
- Search input should live in the left Settings navigation area on desktop.
|
|
- On mobile, keep behavior simple: show results in the nav stage and open target page on select.
|
|
- When query is empty, keep the existing navigation list.
|
|
- When query has text, replace the normal nav list with concrete search results.
|
|
|
|
3. Add click behavior for a search result.
|
|
- Set `settingsPage` to the result page.
|
|
- Store pending target item id in component state/ref.
|
|
- After content renders, find `[data-settings-item="<id>"]`.
|
|
- Scroll it into view.
|
|
- Add a temporary highlight using a data attribute or CSS class.
|
|
|
|
4. Add a tiny shared anchor/highlight pattern.
|
|
- Prefer adding `data-settings-item="..."` to existing row/card containers.
|
|
- Avoid wrappers that change layout.
|
|
- Keep highlight styling generic, for example a short ring/background transition.
|
|
|
|
5. Add initial searchable coverage.
|
|
- Start with high-value pages that already use many localized strings:
|
|
- `appearance`
|
|
- `chat`
|
|
- `sessions`
|
|
- `notifications`
|
|
- `git`
|
|
- `providers`
|
|
- `agents`
|
|
- Add more pages incrementally.
|
|
|
|
6. Validation.
|
|
- Run `bun run type-check`.
|
|
- Run `bun run lint`.
|
|
- Manually verify search result navigation for at least one single page and one split page.
|
|
|
|
## Current Implementation Status
|
|
|
|
Done:
|
|
|
|
- `packages/ui/src/lib/settings/search.ts` exists and exports the explicit registry plus localized result builder.
|
|
- Search input is wired into `SettingsView.tsx`.
|
|
- Results are grouped by page header.
|
|
- ArrowUp, ArrowDown, Enter, and Escape work while the search input is focused.
|
|
- Result click opens the target page and scrolls to `[data-settings-item="..."]`.
|
|
- Matching target gets a temporary highlight via `data-settings-search-highlight`.
|
|
- Search respects page availability, `visiblePageSlugs`, and item-level platform/runtime/mobile guards.
|
|
- Initial anchors exist for `appearance`, `chat`, `sessions`, `notifications`, `git`, and `usage`.
|
|
|
|
Covered pages/items so far:
|
|
|
|
- `appearance`: themes, localization, PWA/mobile-only controls, layout controls, navigation controls, usage reports.
|
|
- `chat`: render mode, transport, reasoning, layout/message toggles, mobile status bar, dotfiles, queue/draft/spellcheck.
|
|
- `sessions`: defaults, retention, desktop network controls, OpenCode CLI controls.
|
|
- `notifications`: delivery, events, background push.
|
|
- `git`: GitHub account, identities, changes view, Gitmoji, gitignored files.
|
|
- `usage`: header menu visibility, model quotas section.
|
|
- `agents`: create action plus static editor fields for name, mode, model, temperature, Top P, system prompt, and permissions.
|
|
- `commands`: create action plus static editor fields for name, agent, model, and template.
|
|
- `mcp`: create action plus static editor sections for server, command/URL, environment variables, and advanced remote options.
|
|
- `plugins`: add action plus static editor fields for spec, options JSON, and file content.
|
|
- `snippets`: create action plus snippet content editor.
|
|
- `providers`: connect action plus auth, connection details, and models sections.
|
|
- `skills.installed`: create action plus basic information, instructions, and supporting files sections.
|
|
- `behavior`: global AGENTS.md and response style sections.
|
|
- `projects`: static project metadata fields and worktree section, excluding individual projects.
|
|
- `skills.catalog`: source repository, catalog search, and add catalog action, excluding individual catalog skills/sources.
|
|
- `magic-prompts`: visible prompt, instructions, and reset-all action, excluding individual prompt result generation beyond the selected editor page.
|
|
- `shortcuts`: keyboard shortcut editor section.
|
|
- `voice`: voice setup, speech recognition, and playback sections.
|
|
- `tunnel`: provider, tunnel type, TTLs, managed remote/local configuration, and start/connect link sections.
|
|
- `remote-instances`: client auth/pairing and desktop direct-host sections; SSH instance dialog fields stay out of search because they require selected-instance state.
|
|
|
|
Still pending:
|
|
|
|
- Add state-aware filtering for settings that are hidden based on current settings values, not just platform. Examples: `chat.activity-default-mode`, `chat.collapsible-reasoning`.
|
|
- Add focused tests for `buildSettingsSearchResults`, especially runtime/mobile filtering.
|
|
|
|
Out of scope by decision:
|
|
|
|
- Do not generate search results from dynamic store entities such as individual agents, commands, MCP servers, snippets, plugins, skills, providers, or projects.
|
|
- For split pages, search should cover predictable static create actions, editor fields, and sections only.
|
|
|
|
## Important Constraints
|
|
|
|
- Do not rely on localized key naming alone for navigation. The registry is the source of truth.
|
|
- Do not parse JSX or scrape the DOM to discover settings automatically.
|
|
- Search should use current locale strings, with English fallback already handled by i18n.
|
|
- Do not introduce broad Zustand state for transient search query/highlight state. Keep it local to `SettingsView` unless another surface needs it.
|
|
- Keep page behavior unchanged when the query is empty.
|
|
- If a page is unavailable in the current runtime, its search items must not appear.
|
|
|
|
## Future Improvements
|
|
|
|
- Add fuzzy ranking instead of simple substring matching.
|
|
- Support deep-linking to settings items from URLs or app commands.
|
|
- Add complete registry coverage for all Settings pages.
|