Snackbar
The snackbar uses the Popover API internally.
Usage
Show one snackbar at a time, never stacked. To update the message, change the text of the open snackbar instead of opening a second one.
Single-line snackbar
<script lang="ts">
import { Button, Snackbar } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
{#snippet icon()}
<Icon>close</Icon>
{/snippet}
<Button command="toggle-popover" commandfor="single-line-snackbar">Show snackbar</Button>
<Snackbar
{icon}
id="single-line-snackbar"
label="Single line snackbar with action and icon"
actionLabel="Action"
/>
Two-line snackbar
A long label wraps onto a second line. Past two lines it is truncated, so keep the text
short enough to fit.
<script lang="ts">
import { Button, Snackbar } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
{#snippet icon()}
<Icon>close</Icon>
{/snippet}
<Button command="toggle-popover" commandfor="two-line-snackbar-demo">Show snackbar</Button>
<Snackbar
{icon}
id="two-line-snackbar-demo"
label="Your photo was moved to the archive. You can restore it from the archive folder at any time within the next 30 days."
actionLabel="Undo"
/>
Manual control
A snackbar is a popover, so command and commandfor on a trigger open and
close it without script. Use this first. Every overlay in the library takes the same pair, and it
works before the page has hydrated. With timeout=0 the snackbar stays open until something
closes it.
<script lang="ts">
import { Button, Snackbar } from 'noph-ui'
</script>
<Button command="show-popover" commandfor="manual-snackbar">Show snackbar</Button>
<Button command="hide-popover" commandfor="manual-snackbar">Hide snackbar</Button>
<Snackbar id="manual-snackbar" timeout={0} popover="manual" label="Manual controlled snackbar" />
When there is no trigger to point at the snackbar, call show() and close() on the component, as shown under Methods. bind:open reports whether the snackbar is showing, also after it times out.
<script lang="ts">
import { Button, Snackbar } from 'noph-ui'
let open = $state(false)
let snackbar: ReturnType<typeof Snackbar> | undefined = $state()
</script>
<Button onclick={() => snackbar?.show()}>Show snackbar</Button>
<Snackbar bind:this={snackbar} bind:open label="Bound to state" />
<span>open: {open}</span>
Accessibility
The snackbar has role="status", a polite live region. A screen reader finishes what
it is saying and then reads the label, the supportingText and the action
label together. The region is named by its label and never takes focus. Pass aria-label to give it a different name, and iconAriaLabel to translate the close button.
The timeout pauses while the snackbar is hovered or has focus, and starts over when
both end. This keeps the action reachable with a keyboard. For a snackbar that must not close on
its own, set timeout=0.
Theming
Tokens
| Token | Default value |
|---|---|
--np-snackbar-container-color | --np-color-inverse-surface |
--np-snackbar-container-shape | 0.25rem |
--np-snackbar-text-color | --np-color-inverse-on-surface |
--np-snackbar-action-color | --np-color-inverse-primary |
Example
<script lang="ts">
import { Button, Snackbar } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
{#snippet icon()}
<Icon>close</Icon>
{/snippet}
<Button command="toggle-popover" commandfor="themed-snackbar">Show snackbar</Button>
<Snackbar
id="themed-snackbar"
{icon}
actionLabel="Action"
--np-snackbar-container-color="var(--np-color-tertiary)"
--np-snackbar-action-color="var(--np-color-on-tertiary)"
--np-snackbar-container-shape="1rem"
--np-snackbar-text-color="var(--np-color-on-tertiary)"
label="Themed snackbar"
/>
API
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | Text to display in the snackbar | |
supportingText | string | undefined | undefined | Supporting text to display in the snackbar |
actionLabel | string | undefined | undefined | Text of the action button. If undefined, there is no action button. |
icon | Snippet | undefined | undefined | Icon of the close button |
iconAriaLabel | string | 'Close' | Accessible label of the icon button. |
timeout | number | 4000 | Time in milliseconds before the snackbar closes. With <= 0, the snackbar
stays open until something closes it. |
popover | 'auto' | 'manual' | 'manual' | With manual the snackbar closes on its timeout or when you hide
it. With auto, a click elsewhere or Escape also closes it, but so does
opening another popover. |
onactionclick | (event: Event) => void | undefined | undefined | Called when the action button is clicked. |
oniconclick | (event: Event) => void | close() | Called when the icon button is clicked. |
...attributes | HTMLAttributes<HTMLDivElement> | Passed to the container element. |
Bindables
| Attribute | Type | Description |
|---|---|---|
open | boolean | Whether the snackbar is shown. Defaults to false. Set it to true to show the snackbar and false to hide it. It updates when the
snackbar opens or closes on its own. |
element | HTMLElement | The root DOM element of the component, bound with bind:this. |
Methods
Bind a reference to the component with bind:this and type it with ReturnType<typeof Snackbar>. It is undefined until the component
has mounted, so call through ?..
<script lang="ts">
let snackbar: ReturnType<typeof Snackbar> | undefined = $state()
</script>
<Button onclick={() => snackbar?.show()}>Show snackbar</Button>
<Snackbar
bind:this={snackbar}
label="Reservation saved"
actionLabel="Undo"
onactionclick={() => snackbar?.close()}
/>| Method | Type | Description |
|---|---|---|
show | () => void | Shows the snackbar. Does nothing if it is already showing. |
close | () => void | Hides the snackbar. |