description:Use when creating or modifying UI components, styling, or visual elements related to Settings in OpenChamber.
license:MIT
compatibility:opencode
---
# Settings UI Patterns Skill
## Purpose
This skill provides instructions for creating or redesigning Settings pages, informational panels, and configuration interfaces within the OpenChamber application.
## Current Canonical Look (2026)
Use this as source of truth for new settings UI work.
- **No unnecessary wrappers**: Avoid extra section wrappers that mix unrelated controls.
- **No redundant section titles**: Do not add headers like `Theme Preferences` or `Scaling & Layout` when controls are already self-explanatory.
- **Compact controls**: Option chips and radio rows should be dense, not tall.
- **Left-leading state icon**: Radio/checkbox state icon appears before text.
- **Subtle state contrast**: Inactive radio labels should be visibly dimmer than active labels.
- **Minimal row chrome**: Avoid row hover/background highlighting by default; keep only where explicitly needed.
## Typography Guidelines
Always utilize the standard OpenChamber typography classes defined in `packages/ui/src/lib/typography.ts`.
- **Page Title**: Use `typography-ui-header font-semibold text-foreground` for the top-most title of a settings page/dialog.
- **Section Header**: Use `typography-ui-header font-medium text-foreground` for settings sections (e.g. `Notification Events`, `Session Defaults`).
- **Control Group Header**: Use `typography-ui-header font-medium text-foreground` (or `font-normal` if it reads too loud) for grouped controls inside a section (e.g. `Default Tool Output`, `Diff Layout`).
- **Values / Primary Text**: Use `typography-ui-label text-foreground`. Add `tabular-nums` if displaying numbers or stats to ensure vertical alignment.
- **Option Labels**: Use non-bold label text in compact option controls (`font-normal` when needed to override).
- **Meta / Helper Text**: Use `typography-meta text-muted-foreground` or `typography-small text-muted-foreground` for supplemental text.
## Layout and Spacing Patterns
### 1. Main Backgrounds
Main wrappers should generally use `bg-background` or `bg-[var(--surface-background)]`. Ensure adequate padding (e.g., `px-5 py-6` or `p-6`).
### 2. Subsection Grouping
Group related controls with vertical spacing, not mandatory cards.
- Use `space-y-3` between logical subsections.
- Use `p-2` for subsection internal padding.
- Avoid adding `bg-[var(--surface-elevated)]` unless there is a clear reason.
- Avoid extra row decorations (`rounded-md`, hover fills) unless there is explicit UX value.
### 3. Header-to-Content Hierarchy (critical)
When removing cards/background wrappers, spacing must be rebalanced so header ownership stays clear.
- Keep **section-to-section spacing larger** than **header-to-own-content spacing**.
- Typical pattern:
- header wrapper `mb-1 px-1`
- content wrapper `pt-0 pb-2 px-2`
- outer section spacing `mb-8`
- Do not leave legacy `mb-3` style gaps after flattening a section; it makes headers look detached.
### 4. Headerless Blocks (when context is obvious)
If the page title already provides enough context, remove redundant local headers and place controls directly below the title.
- Example: project page identity controls can sit directly under project name/path.
- Tighten top gap for this pattern (e.g. top header `mb-4` instead of larger section spacing).
```tsx
<divclassName="space-y-3">
<sectionclassName="p-2">...</section>
<sectionclassName="p-2">...</section>
</div>
```
## Structural Patterns
### 1. Segmented Option Buttons (compact)
Use for short option sets where button-style segmented choice reads best (e.g. Default Tool Output).
Use compact stepper input (`- value +`) plus reset button.
- Prefer shared `NumberInput` stepper style over slider + numeric combo in dense settings pages.
- Keep reset button adjacent to control (`gap-2`).
- Avoid using Tailwind `overflow-hidden` on mobile for controls; `packages/ui/src/styles/mobile.css` forces `.overflow-hidden { overflow-y: auto !important; }`.
Use `overflow-x-hidden overflow-y-hidden` if you truly need clipping.
- Touch devices: `packages/ui/src/styles/mobile.css` enforces `min-height: 36px` on `button`. If you build custom segmented controls with `<button>`, ensure the container height can accommodate that (e.g. `h-9`).
#### Optional numeric overrides
For "override unless empty" fields (e.g. agent Temperature/Top P), keep the value optional and provide a fallback for stepping.
Every Settings UI addition must preserve item search. The registry is explicit: search does not scrape JSX or infer fields automatically.
### Required Files
- Add or update search items in `packages/ui/src/lib/settings/search.ts`.
- Add matching `data-settings-item="..."` anchors in the rendered Settings UI.
- Reuse existing localized labels/descriptions where possible; otherwise add keys to all `packages/ui/src/lib/i18n/messages/*.settings.ts` files.
- If adding a new top-level Settings page, add metadata in `packages/ui/src/lib/settings/metadata.ts` and at least one searchable item unless the page is purely navigational like `home`.
### What To Index
- Index stable user-facing controls, section headers, and static create/connect actions.
- Use item IDs that match the page and target, for example `appearance.language`, `agents.mode`, `remote-instances.client-auth`.
- Prefer the exact visible label key as `titleKey`; use a concise visible/help text key as `descriptionKey` only when it adds useful context.
- Add `keywords` for common synonyms, acronyms, and words users may type that are not in the label.
### What Not To Index
- Do not generate search items from dynamic entities: individual agents, commands, MCP servers, snippets, plugins, skills, providers, projects, catalog rows, remote hosts, or SSH instances.
- Do not index controls hidden behind selected-entity dialogs unless search selection prepares the required state before highlighting.
- Do not add a registry entry for a conditional control unless its `isAvailable` guard matches actual render visibility.
### Split Page Pattern
For split pages, search should target predictable static surfaces only.
- Index sidebar create/connect actions like `agents.create` or `providers.connect`.
- Index editor fields/sections that exist after the existing search preparation opens a draft.
- If a new create result needs draft setup, update `prepareSettingsSearchTarget` in `SettingsView.tsx` so the target is rendered before highlight runs.
### Availability Guards
- Match runtime/page availability exactly: VS Code, web, desktop, mobile, and local desktop origin when relevant.
- Page-level guards belong in `metadata.ts`; item-specific guards belong in `search.ts`.
- If a target renders only inside desktop shell UI, guard it with `ctx.isDesktop` or `ctx.isDesktopLocalOrigin` as appropriate.
### Highlight Target Rules
- Put `data-settings-item` on the smallest stable container that visually owns the setting.
- Avoid adding layout-only wrappers just for search anchors.
- Highlight styling is intentionally subtle and lives in `packages/ui/src/index.css` under `[data-settings-search-highlight="true"]`; keep it token-based and non-aggressive.
### Audit Checklist
- All registry IDs have matching anchors.
- All `titleKey` and `descriptionKey` values exist in every settings locale file.
- Every non-navigational `SettingsPageSlug` has item coverage.
- **Reuse via composition**: Prefer a single settings component with a `visibleSettings` subset (like `OpenChamberVisualSettings`) for multiple tabs (Appearance/Chat) instead of duplicating markup.
- **Hierarchy**: Page title = `font-semibold`; section header = `font-medium`; control group header = `font-medium` (or `font-normal` if needed); option labels = non-bold.
- **Subsection depth**: Nested subgroup headings under a section should usually be one step lighter than parent heading weight.
- **Hierarchy sanity check**: after flattening UI, verify visual grouping by spacing first (not color).
- **Helper blocks**: For small notes/errors under a section, use `mt-1 px-2` with `typography-meta text-muted-foreground/70` (and status token for errors).
- **Truncation**: Always consider long text. Use `min-w-0 flex-1 truncate` on text containers that sit next to buttons or icons to prevent layout breakage.
- **Theme Variables**: *Always* use CSS variables for colors (e.g., `var(--status-success)`) rather than hardcoded hex values or generic Tailwind colors when indicating semantic states.