refactor(desktop): migrate voice settings onto the design system
D27 of the design-system migration (Desktop stack, base feature/desktop-d26-integration-connection-controls, #3405).
What
Settings āŗ Voice (apps/desktop/src/renderer/settings/voice-page.tsx) moves off the hand-rolled settings-group/settings-row markup onto @luke/ui:
- Each stage is a
SettingsSection: the sign-in line while voice can't run, Permissions once it can, and Conversation once the microphone is allowed. - Each line is a
SettingsRow. The name and its check or attention mark are the row's label, and the microphone's detail is its description. - The System Settings door is a quiet
IconButton, still under its "System Settings" tooltip and named "Open Privacy & Security in System Settings". Allow is the outlineButton. - The Microphone row's search anchor sits on a wrapper, as the Account rows' anchors do, because the shared row takes no caller attributes.
.settings-actionshad no other caller, so it's removed..link-icon, the 9px glyph that sits beside a link's words, is unlayered, so it beat the button's layered icon size and shrank the External glyph to 9px. It now leaves a glyph inside aluke-button-facealone.
What's unchanged: which stage shows, which control each microphone answer offers (Allow before macOS is asked, System Settings once it has answered), and both callbacks. No caller here imported @luke/ui/compat. The Keys section below this one is D28's.
Visible changes
- The Permissions and Conversation headings use
SettingsSection's section heading, which has a little more room under it than the old group title. - Allow uses the contract's label weight, 500. It was 600.
- The System Settings button draws the shared quiet icon button. Its glyph stays at the control icon size.
Tests
- New
voice-page.test.ts(jsdom) walks the stages throughSettingsPanel:- With voice off, only the sign-in line shows: no Permissions, no Conversation, no Allow.
- Before macOS is asked, the controls wait. Allow asks, and once macOS grants access (simulated by redrawing the panel), Conversation appears and Allow is gone.
- After a denial, the row shows the System Settings path and the button opens it.
- Once access is granted, Conversation appears under Permissions.
settings-panel.test.tspasses unchanged.pnpm check:affectedexits 0.
Evidence
Captured on Linux with headless Chrome at 1280Ć840, using #3405's method. A throwaway, uncommitted test rendered the real SettingsPanel on the Voice page in four synthetic states. That output was framed in SettingsPage markup with the built desktop stylesheet. Linux has no font for the ā glyph, so it's missing.
| Light | Dark | |
|---|---|---|
| Before | ![]() | ![]() |
| After | ![]() | ![]() |
Not verified on a Mac
- SF Pro rendering and the tooltip's native timing.
- The real macOS microphone prompt and the System Settings deep link. Only the jsdom tests cover them.
š¤ Generated with Claude Code



