Snackbar
A lightweight feedback bar anchored to the bottom (or top) center. The open attribute is controlled; multiple bars stack vertically automatically (up to 3 per direction); the timer pauses on hover/focus/hidden tab and resumes with the remaining time; oas-close carries detail.reason (timeout / escape / close / swipe / evict / group) and the host is responsible for removing open.
Basic usage
Controlled open
Latest event: —
closable shows a close button (recommended whenever duration="0"); pressing Esc dismisses — the focused snackbar when focus is inside one, otherwise the oldest.
Action buttons
Action button (undo)
Rich content slot
Slotted content supports icons, links and emphasis; when present, the message attribute is not rendered (nor merged by grouping).
Direction & offset
Direction & offset
Stacking & queueing
Stack / queue
Latest event: —
Multiple bars in the same direction stack vertically without overlapping, newest closest to the screen edge; by default exceeding the limit (3) evicts the oldest (reason: evict). With queue, overflow bars wait and fill slots as earlier ones close (oas-open fires only when actually shown).
Timer pause & progress
hover/focus pause + timing progress bar
The timer pauses on hover, focus (Tab to the action/close button) or switching browser tabs, then resumes with the remaining time (full duration is not reset); the progress bar freezes while paused. no-pause disables all automatic pausing.
Same-content grouping
group merging + count badge
With group set, a new message with the same group and text does not open another bar — it merges into the existing one, shows a ×n badge and resets its timer (the merged element receives oas-close with reason: group).
Swipe dismiss & persistent
Swipe dismiss (touch) / persistent bar
swipe enables vertical swipe-to-dismiss (release beyond the threshold throws the bar away, reason: swipe); duration="0" keeps the bar open — always provide a dismissal path (closable or an action button).
API
oas-snackbar
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
action-text | Action button text | string | — |
closable | Show a ✕ close button on the right (clicking dismisses with oas-close detail.reason=close) | boolean | — |
direction | Position direction | — | — |
duration | Auto-dismiss duration (ms) | string | 4000 |
group | Grouping key for same-content merge: a new entry with the same direction + group + message merges into the existing one (×N count badge + timer reset) while it emits oas-close (reason=group) and never shows; default-slot content does not merge | string | — |
message | Message text | string | — |
no-pause | Disable auto-pause: hover / focus / page hidden no longer freeze the timer (all three pause by default) | boolean | — |
offset | Offset from the screen edge (px) | string | 24 |
open | Whether shown (controlled) | boolean | — |
progress | Show the countdown progress bar (2px at the bottom, JS-driven scaleX, freezes while paused) | boolean | — |
queue | Queue when full: with 3 visible entries in the direction, new ones wait FIFO for a free slot (unset: the oldest is evicted with reason=evict) | boolean | — |
swipe | Enable swipe-to-dismiss: a vertical drag of ≥48px dismisses (flinging out along the gesture) | boolean | — |
Events
| Event | Description |
|---|---|
oas-action | Dispatched when the action button is clicked |
oas-close | Dispatched when auto-dismissing after timeout (controlled mode does not clear open itself), detail: { reason } |
oas-open | Dispatched when opened |
Slots
| Name | Description |
|---|---|
| default | Notification content |
CSS Variables
| CSS Variable | Description | Default |
|---|---|---|
--oas-glass-blur | — | none |
--oas-glass-refraction | Liquid-glass edge refraction filter (active under data-glass, default none); for local opt-out override with an empty value (--oas-glass-refraction: ;)—not none (mixing none with button-state brightness() invalidates the whole filter declaration) | none |
--oas-glass-ring | — | transparent |
openis controlled: onlyoas-closeis dispatched on timeout and the host removesopen; reusing one instance with a changedmessagedoes not restart the timer — close it first or create a new element.- At most 3 bars stack per direction (vertical, no overlap, newest at the edge); the oldest receives
oas-close(reason: evict) when exceeded;queueswitches to FIFO backfilling. - Accessibility: always
role="status"+aria-live="polite"+aria-atomic="true"(feedback bars never use assertive announcements); only the newest bar's buttons join the tab order while stacked (others areinert); the component never steals focus.