frontend-patterns/research/reviews/NavigationFocusExperiment.md
tegwick 26d7c4523b Measure keyboard continuation and navigation feedback
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
2026-09-27 00:22:14 +02:00

85 lines
5.9 KiB
Markdown

# Keyboard continuation and navigation feedback — 2026-09-27
LEARN-0012; Codex author-model review. [Preregistered protocol](../evolution/cycles/2026-09-27-navigation-focus.md)
committed as `2b1c9a4` before implementation/execution. New stream-F comparison group
F-navigation-focus-v1, not comparable to the preceding HTTP/cache question's group.
[Runner](../experiments/navigation-history/focus.mjs),
[authored policy](../experiments/navigation-history/focus-policy.js),
[receipt](../experiments/navigation-history/focus-result.json).
## Evidence and result
Pinned htmx 2.0.11, Playwright 1.63.0; same binary versions/hashes as the previous
navigation cycle: Chromium 151.0.7922.34 and Firefox 155.0. One run, no harness
corrections or discarded failures. 22/22 registered rows completed: two native cases,
ten raw observation cases, ten managed-policy cases. A passing raw observation row
means it was recorded successfully, not that it satisfies the managed obligations.
All browser actions initiating navigation use Tab/Enter; background update is
explicitly script-triggered and browser history uses Playwright's history command.
| Claim | Cases | Observations in both browsers |
| --- | --- | --- |
| NF01 | K01 | With scripts disabled, Tab reaches the native link and Enter loads beta with its full-document title |
| NF02 | K02 | Raw htmx retains focus on the new same-ID `next` link, but this fragment response leaves alpha's title over beta content and produces no completion status. Managed policy focuses beta's heading, updates title and writes `Loaded beta` |
| NF03 | K03 | Enhanced 503 preserves alpha URL/content and the invoking link's focus in both variants. Only managed policy writes the failure/recovery message; native recovery works by keyboard in both |
| NF04 | K04 | While a response is held at the server, the user tabs to persistent search. Both variants preserve search focus on release; managed policy reports completion without moving focus |
| NF05 | K05 | History restores alpha. Raw focus is the same-ID link; managed focus is the heading with matching title/status |
| NF06 | K06 | An unrelated background region update preserves search focus and does not emit navigation feedback in either variant |
The raw result narrows our anticipation of focus loss: stable IDs let htmx restore
focus to a replacement element. Here that link now leads back to the other article.
DOM identity retention alone is not proof of an appropriate next task, but neither is
this observation proof that retaining the link is always wrong. The server deliberately
returns a fragment without title metadata; this is an application contract gap, not
a claim that htmx cannot update document titles.
## Mechanism and interpretation
The authored policy remembers the request source, checks focus ownership immediately
before a zero-delay swap, and applies the continuation synchronously on afterSwap,
after the library's own focus restoration. It updates heading/title/status only for
registered content navigation. It leaves a surviving search control alone if focus
has moved there. Errors keep focus on the invoker and provide a visible polite status
message with a native recovery action already present. History uses a separate explicit
heading policy. It is a small experiment, not a production navigation library.
[W3C focus-order guidance](https://www.w3.org/WAI/WCAG22/Understanding/focus-order.html)
allows more than one meaningful focus order and does not prescribe one universal target.
[Status-message guidance](https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html)
informs making feedback programmatically available without requiring focus movement.
[htmx events](https://htmx.org/events/) supplies the lifecycle hooks. Living primary
pages accessed 2026-09-27; exact documentation revisions unknown. Package implementation
is pinned and hashed. DOM status/ARIA observations are not evidence that a screen reader
spoke the message; no assistive technology or human evaluation was run.
## Disposition and limits
**Corroboration**, one bounded outcome. Existing Progressive Enhancement already calls
for focus, feedback and recovery semantics; Focus Return explicitly excludes automatic
generalization from modal closure to route transitions. The experiment makes that
boundary concrete and adds an ownership-sensitive candidate mechanism. No newly
invented pattern, canonical promotion, independent recurrence or usefulness gain.
Add scoped implementation guidance: distinguish successful route continuation, failed
navigation, history and background updates. Test whether a late response still owns
focus before moving it. Returning to a modal invoker and continuing into a new page
are different decisions. Keep both candidates as hypotheses.
Unverified: screen-reader speech (including possible heading/status duplication),
focus visibility, complete names/order audit, actual usability, pointer modality,
nonzero swap delays, overlapping/superseded route requests, delayed history responses
while the user moves focus, script-late activation, interrupted transport and offline
availability. The explicit history policy always focuses a heading in the tested
immediate restore; it is not proven safe for an asynchronous history miss. Public
single-response success does not settle these ownership races. No writes or production
application were exercised.
[Effort receipt](../evolution/cycles/2026-09-27-navigation-focus-effort.json) separates
monotonic active agent time from experiment/check subprocess time; final administrative
refresh/commit/snapshot/sync overhead excluded. No token/cost estimate. One cycle in
this new comparison group cannot establish a trend, even though the ledger now has
two prospective cycles in different groups.
WP-0003 T01 retains delayed history restoration/overlapping navigation ownership and
interrupted enhancement. WP-0003 T02 retains independent human/AT validation and the
offline branch. WP-0006 T03 retains comparable-window and remaining review-date work.