Make every settings row reachable, and every accessibility switch honest

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 21:03:36 -04:00
parent e1ff25fc66
commit 9ffaf45a4d
33 changed files with 2384 additions and 76 deletions
@@ -18,9 +18,33 @@ Item {
property bool activatable: false
signal activated
// Keyboard and screen-reader reach, added without changing a single thing
// about how the row looks or behaves under the pointer.
//
// Only an activatable row becomes a Tab stop. A row that does nothing when
// clicked must not collect focus either -- Tab landing on inert text is how
// keyboard navigation stops being usable long before it stops working.
function activate(): void {
if (root.activatable)
root.activated();
}
width: parent ? parent.width : 620
implicitHeight: Math.max(56, copy.implicitHeight + 20)
activeFocusOnTab: root.activatable
Accessible.role: root.activatable ? Accessible.Button : Accessible.StaticText
Accessible.name: root.label
Accessible.description: root.detail
Accessible.focusable: root.activatable
Accessible.focused: root.activeFocus
Accessible.onPressAction: root.activate()
Keys.onReturnPressed: root.activate()
Keys.onEnterPressed: root.activate()
Keys.onSpacePressed: root.activate()
Text {
id: iconLabel
anchors.left: parent.left
@@ -104,6 +128,20 @@ Item {
border.width: 0
}
// The focus ring: the hover plate's geometry with a border added, so a row
// reached by Tab reads as the same target the pointer would have hit. Drawn
// only while this row holds keyboard focus, so nothing changes at rest.
Rectangle {
anchors.fill: parent
anchors.bottomMargin: 1
radius: 8
z: -1
visible: root.activatable && root.activeFocus
color: Theme.alpha(Theme.fg, 0.05)
border.width: 2
border.color: Theme.accentSecondary
}
HoverHandler {
id: rowHover
enabled: root.activatable