Scroll a menu that is too long for the window

The popover was fit-content with overflow visible, so a long menu ran past the
edge of the top layer, where the page's own scrolling cannot reach it. It now
caps at 18rem — less on a short window — and scrolls, as M3's menu behaviour
asks, and the keyboard brings the item it moves to into view. Plan step 11,
actions.md ACT-04.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold
2026-09-14 05:55:38 +02:00
co-authored by Claude Opus 5
parent 6e24ff2cf8
commit c1ca157341
3 changed files with 20 additions and 4 deletions
+9 -3
View File
@@ -183,10 +183,16 @@ document.addEventListener('alpine:init', () => {
return [...this.$refs.menu.querySelectorAll(ITEMS)].filter((item) => item.getAttribute('aria-disabled') !== 'true')
},
/** The menu scrolls when it is too long for the window, so the item taken has to be shown. */
focusItem(which) {
const items = this.items()
;(which === 'last' ? items.at(-1) : items[0])?.focus()
this.reach(which === 'last' ? items.at(-1) : items[0])
},
reach(item) {
item?.focus()
item?.scrollIntoView({ block: 'nearest' })
},
navigate(event) {
@@ -195,7 +201,7 @@ document.addEventListener('alpine:init', () => {
const move = (index) => {
event.preventDefault()
items[(index + items.length) % items.length]?.focus()
this.reach(items[(index + items.length) % items.length])
}
switch (event.key) {
@@ -226,7 +232,7 @@ document.addEventListener('alpine:init', () => {
if (match) {
event.preventDefault()
match.focus()
this.reach(match)
}
}
},