Skip to content

Commit 5b9aae5

Browse files
Merge pull request #81 from RtlZeroMemory/focus-system-hardening
Focus system hardening: traversal, zones, traps, layers, and persistence
2 parents 6288f03 + 8afacab commit 5b9aae5

9 files changed

Lines changed: 2224 additions & 26 deletions

File tree

docs/guide/input-and-focus.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ ui.column({}, [
4343
])
4444
```
4545

46+
Focus persistence is ID-based across commits:
47+
48+
- If the currently focused `id` still exists after re-render, focus stays on that `id` even if position changes.
49+
- If that `id` disappears, focus falls back to the first focusable widget in traversal order (or `null` if none remain).
50+
- Deferred/pending focus requests are resolved during finalize against the newly committed tree using the same rules.
51+
4652
### Focus Zones
4753

4854
Group related widgets with focus zones for organized Tab navigation:
@@ -62,6 +68,12 @@ ui.column({}, [
6268

6369
Tab moves between zones; arrow keys navigate within zones.
6470

71+
Zone traversal order is deterministic:
72+
73+
- Zones are traversed by ascending `tabIndex`.
74+
- Ties on `tabIndex` preserve tree traversal order.
75+
- Empty zones are skipped during Tab/Shift+Tab traversal.
76+
6577
### Focus Traps
6678

6779
Constrain focus within modals and overlays:
@@ -74,6 +86,11 @@ ui.focusTrap({ id: "modal", active: state.showModal }, [
7486
])
7587
```
7688

89+
Trap activation focus rules:
90+
91+
- `initialFocus` should point to an element inside the trap for guaranteed containment.
92+
- If `initialFocus` is not focusable in the committed tree, focus falls back to the first focusable element inside the trap.
93+
7794
## Keybinding System
7895

7996
### Key string syntax

0 commit comments

Comments
 (0)