Snackbar

The snackbar uses the Popover API internally.

Usage

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

<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-single-line-snackbar">Show snackbar</Button>
<Snackbar
	{icon}
	id="two-single-line-snackbar"
	label="Two line snackbar"
	supportingText="with action and icon"
	actionLabel="Action"
/>

Manual control

A snackbar is a popover, so command and commandfor on a trigger open and close it with no script at all. Reach for this first: it is the same pair every overlay in the library takes, and it works before the page has hydrated. With timeout=0 it 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" />

Where there is no trigger to point at the snackbar, call show() and close() on the component, as under Methods. bind:open reports whether the snackbar is showing and follows it when it times out on its own, so it is there to read rather than to drive.

open: false
<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 is role="alert", an atomic live region, so a screen reader reads the whole thing out when it appears: the label, the supportingText and the action label together. It takes no name of its own, which is what the ARIA alert pattern asks for, and it never takes focus. Pass aria-label if you do want to name it, and iconAriaLabel to translate the close button.

The timeout waits while the snackbar is hovered or holds focus and starts over once it is left alone, so an action stays reachable with a keyboard. Give a snackbar that must not vanish timeout=0.

Theming

Tokens

TokenDefault value
--np-snackbar-container-color--np-color-inverse-surface
--np-snackbar-container-shape0.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

AttributeTypeDefaultDescription
labelstringText to display in the snackbar
supportingTextstring | undefinedundefinedSupporting text to display in the snackbar
actionLabelstring | undefinedundefinedText to display in the action button. If undefined, the action button will not be shown.
iconSnippet | undefinedundefinedIcon for the close affordance
iconAriaLabelstring'Close'Accessible label of the icon button.
timeoutnumber4000Time in milliseconds before the snackbar closes. If set to <= 0, the snackbar will stay open until another action triggers it.
popover'auto' | 'manual''manual'With manual the snackbar closes on its timeout or when you hide it. Use auto to also let a click elsewhere or Escape dismiss it, at the cost of other popovers closing it.
onactionclick(event: Event) => void | undefinedundefinedFunction that is triggered when clicking on the action button.
oniconclick(event: Event) => voidclose()Function that is triggered when clicking on the icon button.
...attributesHTMLAttributes<HTMLDivElement>Attributes are passed to the component container.

Bindables

AttributeTypeDescription
openbooleanWhether the snackbar is shown. Defaults to false. Set it to true to show the snackbar and false to hide it; the snackbar writes back when it opens or closes on its own.
elementHTMLElementA reference to the root DOM element of the component. This variable is bound using bind:this, allowing direct access to the underlying HTML element for manipulation or querying within the component's logic.

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()}
/>
MethodTypeDescription
show() => voidShows the snackbar. A no-op if it is already showing.
close() => voidHides the snackbar.