Skip to content

Toast

<quiet-toast> stable since 1.0.0

Toasts are temporary, non-intrusive notifications that appear above the page's content.

Adding a single <quiet-toast> element to the page gives you the power to dispatch notifications any time. Notifications appear in the toast stack, which renders in the top layer and shows above everything else on the page.

Show notification
<quiet-toast id="toast__overview"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__overview');
  const button = toast.nextElementSibling;

  button.addEventListener('click', () => { 
    toast.create(`
      <quiet-avatar slot="icon" label="Meowy McGee's avatar" image="https://images.unsplash.com/photo-1672487209629-4d52e0c043d0?q=80&w=256&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"></quiet-avatar>
      <strong>Meowy McGee</strong><br>
      <small style="color: var(--quiet-text-muted);">has sent you a message</small>
    `, {
      allowHtml: true,
      variant: 'primary'
    });
  });
</script>

You can put the <quiet-toast> element anywhere in the DOM, as long as its somewhere inside the <body>.

Examples Jump to heading

Creating notifications Jump to heading

Start by placing a <quiet-toast> somewhere on the page and obtain a reference to it. To dispatch a notification, call the toast's create() method as shown below.

<quiet-toast></quiet-toast>

<script>
  const toast = document.querySelector('quiet-toast');
  const button = document.querySelector('quiet-button');

  button.addEventListener('click', () => { 
    toast.create('The notification has been sent', {
      variant: 'primary',
      duration: 5000
    });
  });
</script>

The first argument is the content to show in the notification. The second argument is an object containing any of the following properties, all of which are optional.

Property Description Default
allowHtml Set this to true to allow HTML content. Make sure you trust the included content, otherwise your app may become vulnerable to XSS exploits! false
duration The length of time in milliseconds to show the notification before removing it. Set this to 0 to show the notification until the user dismisses it. 5000
variant The type of notification to render, either primary, constructive, destructive, or default. default

Creating notifications from templates Jump to heading

To create notifications declaratively, place a single <quiet-toast-item> in a template and call the toast's createFromTemplate() method. The toast item will be cloned and added to the stack.

Show notification
<div id="toast__declarative">
  <!-- Toast stack -->
  <quiet-toast></quiet-toast>

  <!-- The toast item must be in a <template>! -->
  <template>
    <quiet-toast-item variant="primary" duration="3000">
      <quiet-icon slot="icon" name="click"></quiet-icon>
      This was generated from a template.
    </quiet-toast-item>
  </template>

  <quiet-button>Show notification</quiet-button>
</div>

<script>
  const container = document.getElementById('toast__declarative');
  const toast = container.querySelector('quiet-toast');
  const template = container.querySelector('template');
  const button = container.querySelector('quiet-button');

  button.addEventListener('click', () => { 
    toast.createFromTemplate(template);
  });
</script>

Refer to the toast item docs to see more examples of creating notifications declaratively.

Variants Jump to heading

When calling create(), set the variant option to primary, constructive, destructive, or default to change the type of notification.

Default Primary Constructive Destructive
<div id="toast__variant">
  <quiet-toast></quiet-toast>

  <div style="display: flex; flex-wrap: wrap; gap: .5rem;">
    <quiet-button data-variant="default" data-icon="settings">Default</quiet-button>
    <quiet-button data-variant="primary" data-icon="info-circle">Primary</quiet-button>
    <quiet-button data-variant="constructive" data-icon="check">Constructive</quiet-button>
    <quiet-button data-variant="destructive" data-icon="alert-triangle">Destructive</quiet-button>
  </div>
</div>

<script>
  const container = document.getElementById('toast__variant');
  const toast = container.querySelector('quiet-toast');

  // Listen for button clicks
  container.addEventListener('click', event => {
    const button = event.target.closest('[data-variant]');
    const variant = button?.getAttribute('data-variant');
    const icon = button?.getAttribute('data-icon');
    if (!button) return;

    toast.create(`
      <quiet-icon slot="icon" name="${icon}"></quiet-icon>
      This is a ${variant} notification
    `, {
      allowHtml: true,
      variant
    });
  });
</script>

Changing the duration Jump to heading

When calling create(), set the duration option to change how long notifications show before disappearing. The value is in milliseconds. A value of 0 will keep the notification open until the user dismisses it.

Show notification
<quiet-toast id="toast__duration"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__duration');
  const button = toast.nextElementSibling;

  button.addEventListener('click', () => { 
    toast.create('You have 10 seconds to feed the cats', {
      duration: 10000
    });
  });
</script>

Removing the close button Jump to heading

Use the no-close-button attribute to hide the close button and the progress ring. This is only recommended when a duration is set or when you're using custom buttons to dismiss the notification.

Show notification
<quiet-toast id="toast__no-close"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__no-close');
  const button = toast.nextElementSibling;

  button.addEventListener('click', () => { 
    toast.create('This notification has no close button', {
      noCloseButton: true
    });
  });
</script>

Do not use this as a way to force the notification to stay open. You should provide a custom close button when you use this option. Remember that users can also press to close a notification.

Responding to events Jump to heading

The create() and createFromTemplate() methods return a reference to the generated toast item. You can use this to add a listener to respond when users click on the notification or dismiss it.

Show notification
<quiet-toast id="toast__click"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__click');
  const button = toast.nextElementSibling;

  button.addEventListener('click', async () => { 
    const toastItem = await toast.create('Click this and check the console');

    // Log to the console and remove the notification when clicked
    toastItem.addEventListener('click', () => {
      console.log('The cats appreciate your click');
      toastItem.remove();
    });

    // Log when the notification is dismissed
    toastItem.addEventListener('quiet-closed', () => {
      console.log('Closed');
    });
  });
</script>

Responding to custom buttons Jump to heading

To respond to custom buttons inside a toast item, obtain a reference to the notification and attach event listeners directly to the buttons you're interested in.

Show notification
<quiet-toast id="toast__buttons"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__buttons');
  const button = toast.nextElementSibling;

  button.addEventListener('click', async () => {
    // Create the notification
    const toastItem = await toast.create(`
      <quiet-icon slot="icon" name="cat"></quiet-icon>
      <p>The cats really want you to feed them now</p>
      <div style="display: flex; flex-wrap: wrap; gap: 0.5em;">
        <quiet-button class="complete" size="sm">Complete</quiet-button>
        <quiet-button class="later" size="sm">Remind me later</quiet-button>
      </div>
    `, {
      allowHtml: true,
      noCloseButton: true,
      variant: 'primary',
      duration: 0
    });

    // Obtain a reference to each button
    const complete = toastItem.querySelector('.complete');
    const later = toastItem.querySelector('.later');

    // When complete is clicked...
    complete.addEventListener('click', async () => {
      toastItem.remove();
      toast.create('OK, the cats are happy now!', { 
        variant: 'constructive',
        duration: 3000
      });
    });

    // When later is clicked...
    later.addEventListener('click', async () => {
      toastItem.remove();
      toast.create('The cats do not want to wait…', { 
        variant: 'destructive',
        duration: 3000
      });
    });
  });
</script>

Custom progress bars Jump to heading

You can add custom progress indicators using the readonly --progress custom property, which updates as the timer counts down.

Show notification
<quiet-toast id="toast__progress"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script>
  const toast = document.getElementById('toast__progress');
  const button = toast.nextElementSibling;

  button.addEventListener('click', async () => { 
    const toastItem = await toast.create(`
      <quiet-icon slot="icon" name="balloon"></quiet-icon>
      <p>This is fun, but the cats like the ring better.</p>
      <div class="custom-timer"></div>
    `, {
      allowHtml: true,
      variant: 'primary'
    });
  });
</script>

<style>
  #toast__progress {
    /** Hide the standard progress ring */
    quiet-toast-item::part(progress__track),
    quiet-toast-item::part(progress__indicator) {
      display: none;
    }

    .custom-timer {
      position: relative;
      height: 0.25em; 
      width: 100%; 
      border-radius: 9999px; 
      background-color: var(--quiet-neutral-fill-softer);
      box-shadow: var(--quiet-inset-shadow-soft);
      margin-block-start: -.5rem;
      margin-block-end: -.5rem;

      /** Custom progress bar */
      &::after {
        content: '';
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        width: var(--progress);
        background-color: var(--quiet-primary-fill-mid);
        border-radius: inherit;
        transition: 100ms width;
      }    
    }
  }
</style>

Changing the placement Jump to heading

Use the placement attribute to set the position of the toast stack. The most recent notification will always shows on top since users read from top to bottom.


Alert the cats
<div id="toast__placement">
  <quiet-toast></quiet-toast>

  <quiet-select label="Placement" value="top-end" style="max-width: 300px;">
    <option value="top-start">top-start</option>
    <option value="top-center">top-center</option>
    <option value="top-end">top-end</option>
    <option value="bottom-start">bottom-start</option>
    <option value="bottom-center">bottom-center</option>
    <option value="bottom-end">bottom-end</option>
  </quiet-select>
  <br>
  <quiet-button>Alert the cats</quiet-button>
</div>

<script>
  const container = document.getElementById('toast__placement');
  const toast = container.querySelector('quiet-toast');
  const button = container.querySelector('quiet-button');
  const placementSelect = container.querySelector('quiet-select');
  let count = 0;

  // Update the stack's position
  placementSelect.addEventListener('input', () => {
    toast.placement = placementSelect.value;
  });

  // Send a notification
  button.addEventListener('click', event => {
    const numTimes = ++count === 1 ? '1 time' : `${count} times`;

    toast.create(`
      <quiet-icon slot="icon" name="cat"></quiet-icon>
      Notified the cats ${numTimes}
    `, {
      allowHtml: true,
      variant: 'primary',
      duration: 0
    });
  });
</script>

It's possible, although not typically recommended, to have more than one <quiet-toast> element on the page at a time. If you need to do this, use a different placement for each and ensure they respond as expected on mobile devices.

Changing the animation Jump to heading

Toast uses a transition group internally to handle enter and exit animations. To customize the animation, set the transitionAnimation property using JavaScript. This value will be passed through to the transition group's property of the same name.

See changing the transition group's animation for more animations and examples.

Show notification
<quiet-toast id="toast__animation"></quiet-toast>
<quiet-button>Show notification</quiet-button>

<script type="module">
  import { allDefined } from '/dist/quiet.js';
  import { elevator } from 'https://cdn.jsdelivr.net/npm/@quietui/scurry@latest/dist/transition/elevator.js';  

  await allDefined();

  const toast = document.getElementById('toast__animation');
  const button = toast.nextElementSibling;

  // Set the new animation
  toast.transitionAnimation = elevator();

  button.addEventListener('click', () => { 
    toast.create(`
      <quiet-icon slot="icon" name="keyframes"></quiet-icon>
      This notification has a custom animation!
    `, {
      allowHtml: true,
      variant: 'primary'
    });
  });
</script>

API Jump to heading

Importing Jump to heading

The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.

CDN npm

To manually import <quiet-toast> from the CDN, use the following code.

import 'https://cdn.jsdelivr.net/npm/@quietui/quiet-browser@1.0.0/dist/components/toast/toast.js';

To manually import <quiet-toast> from npm, use the following code.

import '@quietui/quiet/dist/components/toast/toast.js';

Properties Jump to heading

Toast has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties

Property / Attribute Description Reflects Type Default
transitionAnimation A custom animation to use for enter/exit transitions. This gets passed through to the internal transition group. Works well with animations from @quietui/scurry. (Property only) QuietTransitionAnimation
undefined
placement The placement of the toast stack on the screen. 'top-start'
'top-center'
'top-end'
'bottom-start'
'bottom-center'
'bottom-end'
'top-end'

Methods Jump to heading

Toast supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods

Name Description Arguments
create() Creates a toast notification and adds it to the stack. Returns a reference to the created toast item. content: string, options: Partial<CreateOptions>
createFromTemplate() Creates a toast notification using an existing <quiet-toast-item> element. Useful if you want to create your own toast items declaratively. Returns a reference to the cloned toast item. template: HTMLTemplateElement
empty() Removes all elements from the toast stack and turns when the remove transition finishes.

Custom States Jump to heading

Toast has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states

Name Description CSS selector
visible Applied when the toast stack is visible. :state(visible)

Dependencies Jump to heading

Toast automatically imports the following elements. Sub-dependencies are also included in this list.

Search this website Toggle dark mode Get the code on GitHub Follow @quietui.org on Bluesky Follow @quiet_ui on X
    No results found