Take the icon off the snackbar and lift the FAB clear of it
M3 says to avoid an icon in a snackbar and gives the supporting text no fourth colour, so the state glyph and the 80% description are gone: a type now only picks the announcement role. The 40px action and close buttons take the shared touch-target, Escape dismisses a snackbar that holds the focus, and the host publishes --material-snackbar-height on <html> so a `fab` button sits above the snackbar instead of under it. Plan step 18, actions.md ACT-17, ACT-18, ACT-20, ACT-34, ACT-35. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
eac7f6a1de
commit
7bc4f740e7
@@ -35,13 +35,27 @@ document.addEventListener('alpine:init', () => {
|
||||
timer: null,
|
||||
remaining: 0,
|
||||
startedAt: 0,
|
||||
escape: null,
|
||||
|
||||
init() {
|
||||
host = this
|
||||
pending.splice(0).forEach((detail) => this.add(detail))
|
||||
|
||||
// M3: Esc dismisses the focused snackbar. Only the focused one — a key pressed
|
||||
// anywhere else on the page belongs to whatever has the focus there.
|
||||
this.escape = (event) => {
|
||||
if (event.key === 'Escape' && this.current && this.$el.contains(document.activeElement)) {
|
||||
this.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', this.escape)
|
||||
},
|
||||
|
||||
destroy() {
|
||||
document.removeEventListener('keydown', this.escape)
|
||||
document.documentElement.style.removeProperty('--material-snackbar-height')
|
||||
|
||||
if (host === this) {
|
||||
host = null
|
||||
}
|
||||
@@ -93,6 +107,7 @@ document.addEventListener('alpine:init', () => {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = null
|
||||
this.current = this.queue.shift() ?? this.sticky
|
||||
this.measure()
|
||||
|
||||
if (this.current?.timeout) {
|
||||
this.remaining = this.current.timeout
|
||||
@@ -100,6 +115,24 @@ document.addEventListener('alpine:init', () => {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Publishes the snackbar's height on <html> as `--material-snackbar-height`, and clears it
|
||||
* when nothing shows. M3 puts a snackbar above a FAB, never in front of or behind one, and
|
||||
* the FAB is somewhere else in the page: a variable is the only thing the two share.
|
||||
*/
|
||||
measure() {
|
||||
this.$nextTick(() => {
|
||||
const snackbar = this.$el.querySelector('[data-toast]')
|
||||
const root = document.documentElement.style
|
||||
|
||||
if (snackbar) {
|
||||
root.setProperty('--material-snackbar-height', `${Math.round(snackbar.getBoundingClientRect().height)}px`)
|
||||
} else {
|
||||
root.removeProperty('--material-snackbar-height')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
pause() {
|
||||
if (!this.current?.timeout || !this.timer) {
|
||||
return
|
||||
@@ -142,9 +175,5 @@ document.addEventListener('alpine:init', () => {
|
||||
window.dispatchEvent(new CustomEvent(action.event))
|
||||
}
|
||||
},
|
||||
|
||||
icon(type) {
|
||||
return ['success', 'error', 'warning', 'info'].includes(type)
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user