Tier: MEDIUM | Test: required (AppKit) | Modules: AppKit
What a user cannot do
No button on any Settings page can take keyboard focus. Someone who navigates with the
keyboard, or with an assistive technology that follows focus, can reach the text fields on a
page and nothing else. In a sheet that means Cancel, Save and Delete are unreachable: the only
key that works is Escape, which SettingsActionButton's shortcut: .cancelAction binds on the
Cancel button.
Measured, not inferred
Taken during #3018's Live UAT on 2026-09-17, against the dev build, with the accessibility API
rather than synthetic key presses (the app was NOT frontmost, so nothing was typed anywhere):
each control in the New snippet sheet had AXFocused set to true and then read back.
| Control |
Role |
AXFocused after set |
| trigger field |
AXTextField |
true |
| expansion editor |
AXTextArea |
true |
Today's date |
AXButton |
none |
Time now |
AXButton |
none |
Last copied |
AXButton |
none |
Cancel |
AXButton |
none |
Save |
AXButton |
none |
A second, independent observation of the same fact: pressing Tab fourteen times with the sheet
frontmost left fourteen \t characters in the expansion editor and never moved focus, because
TextEditor consumes Tab as a character and no sibling control is a focus candidate.
Where it comes from
SettingsActionButton (Sources/EnviousWisprAppKit/Views/Settings/SettingsComponents.swift)
applies .buttonStyle(.plain) to its whole body. That is what makes every Settings button a
non-focusable control. It is used at 66 call sites across 25 Settings files
(/usr/bin/grep -rn "SettingsActionButton(" Sources/EnviousWisprAppKit/ | wc -l = 66 at
0c455d7c), so this is one root cause with an app-wide blast radius, not a per-sheet defect.
Why it is filed rather than fixed inside #3018
#3018 added three of the affected buttons; the other 63 predate it, including the Cancel and
Save that make a sheet usable at all. A fix changes the focus ring, the focus order and the
keyboard behaviour of every Settings page, which is its own plan, its own review and its own
Live UAT. Founder's call on 2026-09-17: ship #3018, file this.
Scope to settle when this is planned
- Whether the fix is a focusable button style or a custom
.focusable() + .onKeyPress
treatment, and what the focus ring looks like against the dark Settings surfaces.
- Focus ORDER inside a sheet, including how a
TextEditor is escaped (Tab is consumed by the
text view; Ctrl+Tab is the AppKit convention and was not tested).
- Whether
Save should also carry .defaultAction, which today it does not.
- The regression test. The Live UAT instrument above is the right shape for it: it needs no
synthetic keystrokes and no frontmost app, so it can assert focusability per control.
Related: #3018 (added three of the buttons), #2447 (the destructive-role finding on this same
type).
Tier: MEDIUM | Test: required (AppKit) | Modules: AppKitWhat a user cannot do
No button on any Settings page can take keyboard focus. Someone who navigates with the
keyboard, or with an assistive technology that follows focus, can reach the text fields on a
page and nothing else. In a sheet that means Cancel, Save and Delete are unreachable: the only
key that works is Escape, which
SettingsActionButton'sshortcut: .cancelActionbinds on theCancel button.
Measured, not inferred
Taken during #3018's Live UAT on 2026-09-17, against the dev build, with the accessibility API
rather than synthetic key presses (the app was NOT frontmost, so nothing was typed anywhere):
each control in the
New snippetsheet hadAXFocusedset totrueand then read back.AXFocusedafter setAXTextFieldtrueAXTextAreatrueToday's dateAXButtonTime nowAXButtonLast copiedAXButtonCancelAXButtonSaveAXButtonA second, independent observation of the same fact: pressing Tab fourteen times with the sheet
frontmost left fourteen
\tcharacters in the expansion editor and never moved focus, becauseTextEditorconsumes Tab as a character and no sibling control is a focus candidate.Where it comes from
SettingsActionButton(Sources/EnviousWisprAppKit/Views/Settings/SettingsComponents.swift)applies
.buttonStyle(.plain)to its whole body. That is what makes every Settings button anon-focusable control. It is used at 66 call sites across 25 Settings files
(
/usr/bin/grep -rn "SettingsActionButton(" Sources/EnviousWisprAppKit/ | wc -l= 66 at0c455d7c), so this is one root cause with an app-wide blast radius, not a per-sheet defect.Why it is filed rather than fixed inside #3018
#3018 added three of the affected buttons; the other 63 predate it, including the Cancel and
Save that make a sheet usable at all. A fix changes the focus ring, the focus order and the
keyboard behaviour of every Settings page, which is its own plan, its own review and its own
Live UAT. Founder's call on 2026-09-17: ship #3018, file this.
Scope to settle when this is planned
.focusable()+.onKeyPresstreatment, and what the focus ring looks like against the dark Settings surfaces.
TextEditoris escaped (Tab is consumed by thetext view;
Ctrl+Tab is the AppKit convention and was not tested).Saveshould also carry.defaultAction, which today it does not.synthetic keystrokes and no frontmost app, so it can assert focusability per control.
Related: #3018 (added three of the buttons), #2447 (the destructive-role finding on this same
type).