Add buttons, menus and the rest of M3 Expressive's actions
tests / browser (firefox, firefox) (push) Successful in 1m54s
tests / browser (safari, webkit) (push) Successful in 2m17s
tests / lint (push) Successful in 59s
tests / feature (8.4) (push) Successful in 1m7s
tests / feature (8.5) (push) Successful in 1m0s
tests / browser (chrome, chromium) (push) Successful in 1m49s
tests / browser (firefox, firefox) (push) Successful in 1m54s
tests / browser (safari, webkit) (push) Successful in 2m17s
tests / lint (push) Successful in 59s
tests / feature (8.4) (push) Successful in 1m7s
tests / feature (8.5) (push) Successful in 1m0s
tests / browser (chrome, chromium) (push) Successful in 1m49s
<x-button> (label buttons, icon buttons and toggles in five sizes, with filled, tonal, outlined, elevated and text variants in any colour role), <x-tooltip>, <x-menu> with items, groups and separators, <x-button-group>, <x-group> as a connected button group, <x-split-button>, <x-fab>, <x-fab-menu> and <x-loading>. Sizes, colours and shapes come from androidx Compose Material 3's tokens; the loading indicator ports its Morph into SVG + SMIL. Menus follow WAI-ARIA's menu button pattern on popovers placed by CSS anchor positioning. Browser tests run in Chromium, Firefox and WebKit. The showcase fetches the icon names on demand: inlined, they tripped Pest's test server into HTTP 431s under Firefox. 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
b48e879254
commit
cd64f4f371
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* `materialTooltip`: shows an `<x-tooltip>` popover for the control it belongs to.
|
||||
*
|
||||
* The trigger is the popover's parent element (the button, or the standalone wrapper). Hover
|
||||
* counts only for a pointer that can hover, after a short delay so a pointer passing over a
|
||||
* toolbar does not flash every label; keyboard focus shows it at once. A press, leaving, blur
|
||||
* and Escape hide it.
|
||||
*/
|
||||
const HOVER_DELAY_MS = 500
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
window.Alpine.data('materialTooltip', () => ({
|
||||
timer: null,
|
||||
listeners: [],
|
||||
|
||||
init() {
|
||||
const tip = this.$el
|
||||
const trigger = tip.parentElement
|
||||
|
||||
const open = () => tip.matches(':popover-open')
|
||||
|
||||
const show = (delay) => {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => {
|
||||
if (tip.isConnected && !open()) {
|
||||
tip.showPopover()
|
||||
}
|
||||
}, delay)
|
||||
}
|
||||
|
||||
const hide = () => {
|
||||
clearTimeout(this.timer)
|
||||
|
||||
if (open()) {
|
||||
tip.hidePopover()
|
||||
}
|
||||
}
|
||||
|
||||
this.listen(trigger, 'pointerenter', (event) => event.pointerType === 'mouse' && show(HOVER_DELAY_MS))
|
||||
this.listen(trigger, 'pointerleave', hide)
|
||||
this.listen(trigger, 'pointerdown', hide)
|
||||
this.listen(trigger, 'focusin', () => trigger.matches(':focus-within:has(:focus-visible), :focus-visible') && show(0))
|
||||
this.listen(trigger, 'focusout', hide)
|
||||
this.listen(document, 'keydown', (event) => event.key === 'Escape' && hide())
|
||||
},
|
||||
|
||||
listen(target, type, handler) {
|
||||
target.addEventListener(type, handler)
|
||||
this.listeners.push(() => target.removeEventListener(type, handler))
|
||||
},
|
||||
|
||||
destroy() {
|
||||
clearTimeout(this.timer)
|
||||
this.listeners.forEach((remove) => remove())
|
||||
},
|
||||
}))
|
||||
})
|
||||
Reference in New Issue
Block a user