Snackbar - Elements ​
A Snackbar shows brief user feedback messages that overlay content, with an optional action such as Undo.
Accessibility ​
From an accessibility perspective the snackbar component is problematic.
- Since the snackbar items disappear on their own users might not even see them, especially when zoomed in.
- The snackbar items are in practice impossible to reach with keyboard since they appear in the DOM away from the element that triggered them.
- Important elements on the page might get hidden behind the snackbar item.
A snackbar must never be the backbone of your user experience, it should only ever include information and actions that are available elsewhere.
- Keep messages and actions short since the snackbar item is available only for a short time.
- Ensure any information and action in the snackbar, such as Undo, is possible to do elsewhere.
<w-snackbar> creates an ARIA live region so messages you add to the snackbar get announced to assistive technologies.
Keyboard behavior ​
<w-snackbar> is problematic from a keyboard user perspective. We do not override the default Tab behavior, with the result that the focusable buttons in a snackbar item probably come first or last in the focus order, depending on what end of <body> you put <w-snackbar>. We're investigating ways to provide keyboard shortcuts for moving focus to the snackbar item, but have yet to conclude on a design.
<w-snackbar> sets up a keyboard event listener on document. Pressing Escape while a snackbar item is open will close it. If more than one item is open the oldest one will close.
Usage ​
Add <w-snackbar> as a direct child of <body>.
If you use a shared HTML template this may already have been done for you. You can check to see by running a query in your browser console:
// this should find an element,
// if not you should add <w-snackbar></w-snackbar> to <body>
document.querySelector("w-snackbar");<w-snackbar> sets up an ARIA live region that's ready for snackbar messages. We set this up ahead of time since some browsers and screen reader combinations have known issues when it comes to adding a live region and content at the same time.
<body>
<w-snackbar></w-snackbar>
</body><w-snackbar> JS API ​
The <w-snackbar> element includes a create function which you can use to create snackbar items.
const snackbar = document.querySelector("w-snackbar");
const snackbarItem = snackbar.create("Snackbar message");Snackbar item lifecycle ​
A snackbar item animates in from and out of the bottom of the screen unless the user has indicated a preference for reduced motion, in which case it appears and disappears without animation.
If more than one snackbar item is active at a time they will stack, with the new messages animating in above existing ones with the topmost item as the starting point of the animation.
However, only one snackbar item should be visible at a time. Be mindful of what triggers snackbars in your application to avoid creating a wall of snackbar items, for example in bulk editing operations.
Duration ​
Snackbar items automatically close after either:
- 4 seconds (short)
- 10 seconds (long)
You can also have a snackbar item last indefinitely, forcing users to dismiss it. We strongly encourage you to reconsider whether a snackbar is the right choice for you if you feel you need an indefinite snackbar item though, for the accessibility reasons outlined above.
Pausing the countdown ​
To give people a better chance to read the snackbar message and consider taking action the duration countdown timer pauses when:
- A pointer hovers over the snackbar item.
- Either the action or close buttons have keyboard focus.
Closing ​
Users can close a snackbar item ahead of its configured duration by:
- Pressing the close button (present by default).
- Pressing the action button (if present).
- Pressing Escape on a keyboard.
Examples ​
Default ​
Snackbar uses the neutral variant with a short duration by default.
<w-button data-testid="neutral-noaction">Neutral variant</w-button>
<script>
document.querySelector('w-button[data-testid="neutral-noaction"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message");
};
</script>With action ​
You can include an action in the snackbar by providing a label and an onclick handler. By default the action button and close button are inline with the text.
Clicking an action button automatically closes the snackbar item. If you want to prevent this call event.preventDefault().
You can use an action with any variant.
<w-button data-testid="neutral-action">Neutral variant with action</w-button>
<script>
document.querySelector('w-button[data-testid="neutral-action"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
action: {
label: "Undo",
onclick(e) {
console.log(e);
}
}
});
};
</script>With long action label ​
By default a long label will result in the action and close buttons on a separate row. A label gets treated as long if it contains whitespace.
Clicking an action button automatically closes the snackbar item. If you want to prevent this call event.preventDefault().
You can use an action with any variant.
<w-button data-testid="neutral-longlabel">Neutral variant, long label</w-button>
<script>
document.querySelector('w-button[data-testid="neutral-longlabel"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
action: {
label: "Undo this thing",
onclick(e) {
console.log(e);
}
}
});
};
</script>Positive ​
<w-button data-testid="positive-noaction">Positive variant</w-button>
<script>
document.querySelector('w-button[data-testid="positive-noaction"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
variant: "positive",
});
};
</script>Warning ​
<w-button data-testid="warning-noaction">Warning variant</w-button>
<script>
document.querySelector('w-button[data-testid="warning-noaction"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
variant: "warning",
});
};
</script>Negative ​
<w-button data-testid="negative-noaction">Negative variant</w-button>
<script>
document.querySelector('w-button[data-testid="negative-noaction"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
variant: "negative",
});
};
</script>Info ​
<w-button data-testid="info-noaction">Info variant</w-button>
<script>
document.querySelector('w-button[data-testid="info-noaction"]').onclick = () => {
const snackbar = document.querySelector("w-snackbar");
snackbar.create("Snackbar message", {
variant: "info",
});
};
</script>Neutral with custom icon ​
If you have cases not covered by the create API you can change the item returned by create.
For example, here is how you can add a custom icon to the neutral variant.
const snackbar = document.querySelector<WarpSnackbar>('w-snackbar');
// the default neutral variant is without an icon
const snackbarItem = snackbar!.create('The message should be short');
const customIcon = document.createElement('w-icon');
customIcon.name = 'Rocket';
customIcon.slot = 'icon';
snackbarItem.prepend(customIcon);Create <w-snackbar-item> manually ​
Alternatively you can create a w-snackbar-item manually and call prepend on <w-snackbar>. The snackbar item handles its entire lifecycle on its own.
Note that by not using snackbar.create() you have to create and wire up event handlers any close- and action button.
const snackbar = document.querySelector("w-snackbar");
const item = document.createElement("w-snackbar-item");
item.variant = "info";
item.innerHTML = /* html */ `
<w-icon slot="icon" name="Rocket"></w-icon>
Warp speed engaged!
`;
snackbar.prepend(item);Styling ​
Snackbar supports styling through component tokens (CSS custom properties with a --w-c- prefix) and parts.
Parts ​
Use ::part(...) from outside the component.
<w-snackbar> parts ​
container- the live region that positions messages on the screen.
<w-snackbar-item> parts ​
item- the container wrapping the message, icon and actions.icon- the icon for the variant.message- the default slot, body of the snackbar item.action- close and action button.
Component tokens ​
<w-snackbar> tokens ​
Set these on w-snackbar to override visuals.
w-snackbar {
--w-c-snackbar-position-bottom: 32px;
}Layout and typography ​
--w-c-snackbar-container-gap--w-c-snackbar-position-bottom--w-c-snackbar-position-left--w-c-snackbar-position-right--w-c-snackbar-position-top--w-c-snackbar-z-index
<w-snackbar-item> tokens ​
Set these on w-snackbar-item to override visuals.
w-snackbar-item {
--w-c-snackbar-item-box-shadow: var(--w-shadow-s);
}Layout and typography ​
--w-c-snackbar-item-radius--w-c-snackbar-item-max-width--w-c-snackbar-item-min-width--w-c-snackbar-item-padding
Background ​
--w-c-snackbar-item-bg--w-c-snackbar-item-action-bg-active--w-c-snackbar-item-action-bg-hover
Text color ​
--w-c-snackbar-item-color--w-c-snackbar-item-action-color-active--w-c-snackbar-item-action-color-hover
Shadow ​
--w-c-snackbar-item-box-shadow
<w-snackbar> API ​
Unless otherwise noted all properties are HTML attributes (as opposed to JavaScript object properties).
Properties ​
| Name | Type | Default | Summary |
|---|---|---|---|
| create (JS only) | create(message: string, options: CreateSnackbarOptions = {}) => void | - | Creates a snackbar item and immediately adds it to the snackbar. |
Property Details ​
create (JS only) ​
Creates a snackbar item and immediately adds it to the snackbar.
By default the snackbar item automatically closes after 4 seconds (SnackbarDuration.Short).
If you include an action in the options the default duration is set to 10 seconds (SnackbarDuration.Long) and can not be made shorter.
A duration of 10 seconds or longer forces the close button to be visible.
The default variant is neutral which does not have an icon.
Set duration to SnackbarDuration.Infinite if you want a persistent message.
- Type:
create(message: string, options: CreateSnackbarOptions = {}) => void - Default:
-
Questions? ​
Feel free to ask any questions on usage in the Warp DS Slack channel: #warp-design-system