fix(frontend): robust Escape handling + deep-link back navigation
focus-trap: focus the trapped container synchronously on mount instead of only after a deferred rAF. The keydown listener is node-scoped, so an Escape pressed before the rAF moved focus into the sheet landed on an element outside the node and was silently dropped — a real keyboard-a11y gap (open a sheet, immediately press Escape → nothing happened). The rAF still refines focus to the first control once laid out. recover: replace the `window.history.length > 1` back-chevron heuristic with SvelteKit's afterNavigate `from` signal. history.length is 2 on a fresh-tab deep link (about:blank + page), so history.back() landed on the blank entry. `from` is null only on a full-page load, so deep-linked users now correctly fall back to /join (or /feed when authed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -64,11 +64,16 @@ export function focusTrap(
|
||||
node.addEventListener('keydown', onKeyDown);
|
||||
|
||||
if (opts.autoFocus !== false) {
|
||||
// Defer one frame so the element is fully laid out (sheets animate in).
|
||||
// Focus the container synchronously on mount so the trap owns the keyboard
|
||||
// immediately — otherwise an Escape pressed before the deferred focus below
|
||||
// lands on an element *outside* the node, where this node-scoped listener
|
||||
// never sees it (the keystroke is silently dropped). Then defer one frame to
|
||||
// move focus onto the first control once the sheet has laid out / animated in.
|
||||
if (!node.hasAttribute('tabindex')) node.setAttribute('tabindex', '-1');
|
||||
node.focus({ preventScroll: true });
|
||||
requestAnimationFrame(() => {
|
||||
const list = focusables(node);
|
||||
const target = list[0] ?? node;
|
||||
if (!node.hasAttribute('tabindex')) node.setAttribute('tabindex', '-1');
|
||||
target.focus({ preventScroll: true });
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user