# UI conventions Shared renderer rules for dialogs, utility windows, icon toggles, surfaces and scrollbars. ## Agent conventions - Authentication recovery uses `lib/auth-recovery.ts` and `components/auth-recovery-dialog.tsx`: confirm CodeNomad auth status before showing an expired-login form, reconnect in place to preserve drafts, and never replay failed mutations. Its shared window styles live in `styles/components/auth-recovery.css`. - Confirmation dialogs (`components/alert-dialog.tsx`) keep Kobalte's initial focus on Cancel, so Enter never confirms by reflex, while the confirm button stays the filled primary action. Alert-dialog buttons show the accent focus ring on any `:focus` (`styles/components/alert-dialog.css`), including the initial focus of a mouse-opened dialog, so the ring marks the button Enter acts on. Prompts focus their input, where Enter submits. Covered by `tests/browser/alert-dialog.test.ts`. - Persistent command/search utility windows use `components/dismissible-window.tsx`: non-modal, no scrim, outside interactions keep them open, and explicit toggles use `.icon-toggle` with `aria-expanded`/`aria-controls`. Keep search state scoped to its instance/session and close it when that view becomes inactive. - The `.icon-toggle` active state (`aria-pressed`/`aria-expanded`/`data-active`) is one shared rule in `styles/utilities.css`: one uniform partial accent tint for every palette (an ink of accent leaning 20% toward `--text-on-accent`, then 10% toward `--surface-base`, at 40% opacity, 50% on hover) over the surface beneath, primary-text icon, disabled toggles excluded. It is for icon toggles only: text list rows select through `--list-item-highlight-*` instead (Mission past runs). The only active override is `.tool-call-output-rail`, which keeps its compact output-rail toggles transparent. `tests/browser/icon-toggle-active.test.ts` samples real active toggles on every ready-made palette over the session header (search), sessions sidebar header, right-panel tab bar, user and assistant message cards (speech button), interruption dock header and transcript canvas (overlay windows share the canvas colour): OKLab ΔE ≥ 8 from the surface on the header and ≥ 5 elsewhere, ≥ 6 from the header's idle hover, ≥ 1.4 from active to active hover, icon ≥ 3:1 on both fills. - Movable utility windows opt into `DismissibleWindow.draggable` and mark their existing top bar with `data-window-drag-handle`; keep drag geometry shared and controls interactive. `--window-visible-height` bounds their height to the visual viewport; native scrolling and a sticky existing top bar keep results, pagination and drag/close controls reachable. - Appearance mode and the saved light/dark selections are independent (`lib/appearance-preferences.ts`). Message/tool cards use the muted surface; preferences use the same secondary surface as the main panels. Show a subtle local rollover with `--surface-hover-overlay` over the preserved selected background, never by substituting a generic panel or the secondary surface; right-panel canvas button rollover overrides live in `styles/panels/control-hover.css`. - `index.css` re-anchors `box-sizing: border-box` on every `details > :not(summary)`: the component library resets elements to `box-sizing: inherit`, so folded content would inherit content-box from the browser's own details slot and overflow full-width controls. Keep that rule rather than patching individual disclosures. - Large brand logos (home page, empty states, loading screen) follow their title, never the window. Their image is the square `CodeNomad-Icon.png`, which the mark spans edge to edge: 5.55rem beside a `text-3xl` title, 4.44rem beside the narrow session column's 1.5rem title, and 7.4rem beside the loading screen's larger title. Resize the logo whenever its title's size changes. - Keep the global scrollbar-width default at zero specificity (`:where(...)` in `src/index.css`) so component visibility rules win. The timeline shares the transcript's standard native scrollbar (geometry, rail ownership and thumb drags: `dev-docs/SESSION_HISTORY_NAVIGATION.md`); validate with the full stylesheet and real thumb gestures on mixed-height transcripts.