toast

Notification toaster with close actions and toast variants.

Use ng-toast on the container; direct article children are toast items. Application code owns toast creation and queueing. Set type or variant to success, info, warning, error, or loading; the directive mirrors the result to data-type for styling.

<div ng-toast>
  <article type="success">
    <article>
      <article>Saved</article>
      <article>Update published.</article>
    </article>
  </article>
</div>

Toast titles and descriptions are connected through aria-labelledby and aria-describedby. Authored relationships are preserved. Toast action and close buttons default to type="button", so they do not submit an enclosing form.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toast</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="canonical = { visible: false, status: 'Ready' }"
    data-example="toast-demo"
  >
    <main class="visual-example">
      <button
        type="button"
        variant="outline"
        ng-click="canonical.visible = true; canonical.status = 'Toast shown'"
      >
        Show Toast
      </button>
      <output class="output">{{ canonical.status }}</output>
    </main>

    <div ng-toast position="bottom-right" aria-label="Notifications">
      <article ng-if="canonical.visible" animate>
        <section>
          <h3>Event has been created</h3>
          <p>Sunday, December 03, 2023 at 9:00 AM</p>
        </section>
        <button
          variant="outline"
          size="sm"
          ng-click="canonical.visible = false; canonical.status = 'Undo selected'"
        >
          Undo
        </button>
      </article>
    </div>
  </body>
</html>

Reference workflows

The workflow page exercises description, all six positions, notification types, and the loading-to-success promise transition. Its controller is compiled from TypeScript; AngularCSS does not own the application queue or asynchronous state.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toast Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
    <script src="../../js/toast-demo.umd.js"></script>
  </head>
  <body
    ng-app="toastDemo"
    ng-controller="ToastDemoController as toast"
    ng-cloak
    data-example="toast-description toast-position toast-types"
  >
    <main class="toast-workflow-grid">
      <section
        class="toast-workflow-section"
        aria-labelledby="toast-description-title"
      >
        <h2 id="toast-description-title">With description</h2>
        <button
          type="button"
          variant="outline"
          ng-click="toast.showDescription()"
        >
          Show Toast
        </button>
        <div class="toast-inline-preview">
          <div ng-toast aria-label="Description notifications">
            <article ng-if="toast.descriptionVisible" animate>
              <section>
                <h3>Event has been created</h3>
                <p>Monday, January 3rd at 6:00pm</p>
              </section>
              <button
                variant="ghost"
                size="icon-sm"
                aria-label="Dismiss description toast"
                ng-click="toast.dismissDescription()"
              >
                <span></span>
              </button>
            </article>
          </div>
        </div>
        <output class="output">{{ toast.descriptionStatus }}</output>
      </section>

      <section
        class="toast-workflow-section toast-workflow-wide"
        aria-labelledby="toast-position-title"
      >
        <h2 id="toast-position-title">Position</h2>
        <div class="toast-button-grid" aria-label="Toast positions">
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('top-left')"
          >
            Top Left
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('top-center')"
          >
            Top Center
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('top-right')"
          >
            Top Right
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('bottom-left')"
          >
            Bottom Left
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('bottom-center')"
          >
            Bottom Center
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPosition('bottom-right')"
          >
            Bottom Right
          </button>
        </div>
        <div class="toast-position-preview">
          <div
            ng-toast
            position="{{ toast.position }}"
            aria-label="Position notifications"
          >
            <article ng-if="toast.positionVisible" animate>
              <section>
                <h3>Event has been created</h3>
              </section>
              <button
                variant="ghost"
                size="icon-sm"
                aria-label="Dismiss position toast"
                ng-click="toast.dismissPosition()"
              >
                <span></span>
              </button>
            </article>
          </div>
        </div>
        <output class="output">Position: {{ toast.position }}</output>
      </section>

      <section
        class="toast-workflow-section toast-workflow-wide"
        aria-labelledby="toast-types-title"
      >
        <h2 id="toast-types-title">Types</h2>
        <div class="toast-button-grid" aria-label="Toast types">
          <button
            type="button"
            variant="outline"
            ng-click="toast.showType('default')"
          >
            Default
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showType('success')"
          >
            Success
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showType('info')"
          >
            Info
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showType('warning')"
          >
            Warning
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showType('error')"
          >
            Error
          </button>
          <button
            type="button"
            variant="outline"
            ng-click="toast.showPromise()"
          >
            Promise
          </button>
        </div>
        <div class="toast-inline-preview toast-types-preview">
          <div ng-toast aria-label="Type notifications">
            <article type="{{ toast.type }}" ng-if="toast.typeVisible" animate>
              <figure ng-if="toast.type === 'success'"></figure>
              <figure ng-if="toast.type === 'info'"></figure>
              <figure ng-if="toast.type === 'warning'"></figure>
              <figure ng-if="toast.type === 'error'"></figure>
              <figure ng-if="toast.type === 'loading'"></figure>
              <section>
                <h3>{{ toast.typeMessage }}</h3>
              </section>
              <button
                variant="ghost"
                size="icon-sm"
                aria-label="Dismiss type toast"
                ng-click="toast.dismissType()"
              >
                <span></span>
              </button>
            </article>
          </div>
        </div>
        <output class="output">Type: {{ toast.type }}</output>
      </section>
    </main>
  </body>
</html>

Installation

Install AngularCSS, load its stylesheet, and include the angular.css module in your AngularTS application. See Installation for the complete setup.

This component’s root directive is [ng-toast]. Importing the package registers it with the AngularCSS angular.css module; there is no per-component JavaScript registration step.

Anatomy

Directive selectors

  • ng-toast

Semantic structure

Use native elements for authored structure. Component classes are optional visual hooks when an HTML relationship is not specific enough.

API

Attributes and state

AttributeAccessPurpose
aria-atomicInput/outputWhether an assistive technology announces the entire updated region.
aria-describedbyInput/outputID of the element that supplies the accessible description.
aria-labelInput/outputAccessible name when visible text is insufficient.
aria-labelledbyInput/outputID of the element that supplies the accessible name.
aria-liveInput/outputAnnouncement priority for updates to a live region.
positionInput/outputViewport placement: top-left, top-center, top-right, bottom-left, bottom-center, or bottom-right.
roleInput/outputExplicit semantic role when native HTML does not provide one.
typeInput/outputToast state: default, error, info, loading, success, or warning.

Input attributes are read from authored HTML. Output attributes are maintained by AngularCSS for CSS and testing. Input/output attributes may be authored for a controlled initial state and are then synchronized by the directive.

CSS custom properties

This directive does not write component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

The directive exposes presentation and announcement state. The application decides when feedback appears, changes, or is removed.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use the appropriate live-region or status semantics for dynamic feedback. Decorative feedback must stay hidden from assistive technology.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target [ng-toast], semantic descendants, component classes, and generated state with ordinary CSS. Keep behavior and accessible state in the TypeScript directive; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.