Put the showcase in the app shell, with a page per section
tests / lint (push) Has been cancelled
tests / feature (8.4) (push) Has been cancelled
tests / feature (8.5) (push) Has been cancelled
tests / browser (chrome, chromium) (push) Has been cancelled
tests / browser (firefox, firefox) (push) Has been cancelled
tests / browser (safari, webkit) (push) Has been cancelled
tests / lint (push) Has been cancelled
tests / feature (8.4) (push) Has been cancelled
tests / feature (8.5) (push) Has been cancelled
tests / browser (chrome, chromium) (push) Has been cancelled
tests / browser (firefox, firefox) (push) Has been cancelled
tests / browser (safari, webkit) (push) Has been cancelled
The showcase is now an overview and one page per section behind a grouped navigation rail, moved between with wire:navigate, instead of one long page under a scrolling top bar. The switch exposed a WebKit bug in the menu: inside a focusable region, WebKit moves focus out of the closing popover before its toggle event, so Escape no longer returned focus to the trigger. The menu now reads it on beforetoggle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
This commit is contained in:
co-authored by
Claude Opus 5
parent
23218431bf
commit
889f8a8aa1
+11
-1
@@ -15,6 +15,7 @@ document.addEventListener('alpine:init', () => {
|
||||
window.Alpine.data('materialMenu', () => ({
|
||||
closedAt: -Infinity,
|
||||
returnFocus: true,
|
||||
focusWasInside: false,
|
||||
listeners: [],
|
||||
|
||||
init() {
|
||||
@@ -26,6 +27,13 @@ document.addEventListener('alpine:init', () => {
|
||||
// and close() have already done their part, synchronously, because this event is
|
||||
// queued and a screen reader or a test reading aria-expanded in between would be told
|
||||
// the menu is shut.
|
||||
// Whether focus was in the menu is read before it closes: once closed, a browser may
|
||||
// already have handed focus to what had it before the menu opened (WebKit does, when
|
||||
// that was a focusable region around the trigger).
|
||||
this.listen(menu, 'beforetoggle', (event) => {
|
||||
this.focusWasInside = event.newState === 'closed' && menu.contains(document.activeElement)
|
||||
})
|
||||
|
||||
this.listen(menu, 'toggle', (event) => {
|
||||
const opened = event.newState === 'open'
|
||||
|
||||
@@ -37,9 +45,11 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
this.closedAt = performance.now()
|
||||
|
||||
if (this.returnFocus && menu.contains(document.activeElement)) {
|
||||
if (this.returnFocus && (this.focusWasInside || menu.contains(document.activeElement))) {
|
||||
this.control()?.focus()
|
||||
}
|
||||
|
||||
this.focusWasInside = false
|
||||
})
|
||||
|
||||
// A press outside closes the menu without pulling focus back to the trigger.
|
||||
|
||||
Reference in New Issue
Block a user