Snackbar
import { useState } from 'react'
import { Button, Snackbar, Surface, Text } from '@language-lit/material3-expressive'
export function SnackbarExample() {
const [savedOpen, setSavedOpen] = useState(false)
const [removedOpen, setRemovedOpen] = useState(false)
const [sentOpen, setSentOpen] = useState(false)
return (
<Surface
as="section"
aria-labelledby="snackbar-example-title"
color="surface-container-low"
shape="extra-large"
className="snackbar-example"
>
<Text as="h2" id="snackbar-example-title" variant="titleLarge" emphasis="emphasized">
Snackbar
</Text>
<Text as="p" variant="bodyMedium">
Transient status feedback that auto-dismisses unless it carries an
action, and pauses its countdown while hovered or focused.
</Text>
<div className="snackbar-example__row">
<Button variant="outlined" onClick={() => setSavedOpen(true)}>
Show short snackbar
</Button>
<Button variant="outlined" onClick={() => setRemovedOpen(true)}>
Show snackbar with action
</Button>
<Button variant="outlined" onClick={() => setSentOpen(true)}>
Show snackbar with action and dismiss
</Button>
</div>
<Snackbar message="Saved" open={savedOpen} onOpenChange={setSavedOpen} dismissible />
<Snackbar
message="Conversation removed"
action={{ label: 'Undo', onClick: () => setRemovedOpen(false) }}
open={removedOpen}
onOpenChange={setRemovedOpen}
/>
<Snackbar
message="Message sent"
action={{ label: 'Undo', onClick: () => setSentOpen(false) }}
dismissible
open={sentOpen}
onOpenChange={setSentOpen}
/>
</Surface>
)
}Snackbar renders a portaled, transient status message fixed to the bottom
of the viewport. It is a single controlled component, not a queue — a
consumer wanting several queued messages manages that in their own state.
import { useState } from 'react'
import { Snackbar } from '@language-lit/material3-expressive'
import '@language-lit/material3-expressive/styles.css'
const [open, setOpen] = useState(false)
<Snackbar
message="Conversation removed"
action={{ label: 'Undo', onClick: handleUndo }}
open={open}
onOpenChange={setOpen}
/>Contract
open/defaultOpen/onOpenChangefollow the same controlled/ uncontrolled shape as every other stateful component.onOpenChangefires whenever the snackbar closes itself — the auto-dismiss timer, the action, or the dismiss button.messageis the required body.action?: { label, onClick }renders one inline text button; activating it callsonClickthen closes.dismissible(defaultfalse) renders a close icon button;dismissLabel(default'Dismiss') sets its accessible name.durationaccepts'short'(4000ms),'long'(10000ms),'indefinite', or an exact millisecond count. It defaults to'short'with noactionand'indefinite'with one — matching the pinned Material source's own default logic.
Behavior
The auto-dismiss countdown pauses while the snackbar is hovered or
focused and resumes the remaining time on leave, so a user reading a
longer message or reaching for the action never has it disappear from
under them. role="status" announces the message politely without
stealing focus.
Tokens and boundaries
All color, geometry, and motion values live in one --m3e-comp-snackbar-*
registration. Theme overrides remain scoped to Material3Provider;
Snackbar injects no runtime styles. It imports no Next.js,
Vite, router, animation library, or private application code.