Temporary notification

A notification that appears at the bottom of the screen.

Props

message
string
The notification message text to display.
type
basic | success | failure | indeterminate | progress
The notification type which determines the visual style and icon.
Defaults to basic.
progress
number
Progress value from 0-100. Use -1 to hide the progress bar. Only applies when type is "progress".
Defaults to -1.
testId
string
Sets a data-testid attribute for automated testing.
actionText
string
Text for the optional action button. When provided, displays a clickable link button.
visible
boolean
Controls whether the notification is visible.
Defaults to true.
animationDirection
up | down
Direction the notification animates from when appearing or disappearing.
Defaults to down.
Examples

Show a notification

const save = async () => {
    // await api.save();

    TemporaryNotification.show("Your application has been saved.", {
      type: "success"
    });
  };
<GoabTemporaryNotificationCtrl />
      <GoabxButton type="secondary" onClick={save}>Save</GoabxButton>
async save(): Promise<void> {
    // await this.api.save();

    TemporaryNotification.show("Your application has been saved.", {
      type: "success"
    });
  }
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goabx-button type="secondary" (onClick)="save()">Save</goabx-button>
document.getElementById('save-btn').addEventListener('_click', () => {
  // await api.save();

  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification",
      data: {
        message: "Your application has been saved.",
        type: "success",
        uuid: crypto.randomUUID(),
        duration: "short"
      }
    }
  }));
});
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="save-btn" type="secondary">Save</goa-button>

Show a notification with an action

const comment = () => {
    const uuid = TemporaryNotification.show(
      "Edna Mode commented on your assigned case.",
      {
        actionText: "View",
        action: () => {
          TemporaryNotification.dismiss(uuid);
        }
      }
    );
  };
<GoabTemporaryNotificationCtrl />
      <GoabxButton onClick={comment}>Comment</GoabxButton>
comment(): void {
    const uuid = TemporaryNotification.show(
      "Edna Mode commented on your assigned case.",
      {
        actionText: "View",
        action: () => {
          TemporaryNotification.dismiss(uuid);
        }
      }
    );
  }
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goabx-button (onClick)="comment()">Comment</goabx-button>
const commentBtn = document.getElementById('comment-btn');
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification",
      data: { message, uuid, type: "basic", duration: "short", ...opts }
    }
  }));
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification:dismiss",
      data: uuid
    }
  }));
}

commentBtn.addEventListener('_click', () => {
  currentUuid = showNotification(
    "Edna Mode commented on your assigned case.",
    {
      actionText: "View",
      action: () => {
        dismissNotification(currentUuid);
      }
    }
  );
});
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="comment-btn">Comment</goa-button>

Show a user progress

const sendApi = (
    progressCallback: (progress: number) => void,
    isCancelledRef: { current: boolean }
  ) => {
    return new Promise((resolve, reject) => {
      let progress = 0;
      const interval = setInterval(() => {
        if (isCancelledRef.current) {
          clearInterval(interval);
          reject("cancelled");
          return;
        }

        progress += 5;
        progressCallback(progress);

        if (progress >= 100) {
          clearInterval(interval);
          resolve("success");
        }
      }, 200);
    });
  };

  const downloadReport = () => {
    const isCancelledRef = { current: false };

    const uuid = TemporaryNotification.show("Downloading report D-23459", {
      type: "progress",
      actionText: "Cancel",
      action: () => {
        isCancelledRef.current = true;
        TemporaryNotification.dismiss(uuid);
        console.log("Download cancelled");
      },
    });

    TemporaryNotification.setProgress(uuid, 0);

    const updateProgress = (progress: number) => {
      TemporaryNotification.setProgress(uuid, progress);

      if (progress >= 100) {
        setTimeout(() => {
          TemporaryNotification.show("Report downloaded", {
            type: "success",
            duration: "medium",
            actionText: "View",
            action: () => {
              console.log("View report clicked!");
            },
            cancelUUID: uuid,
          });
        }, 300);
      }
    };

    sendApi(updateProgress, isCancelledRef).catch((error) => {
      if (error !== "cancelled") {
        TemporaryNotification.dismiss(uuid);
      }
    });
  };
<GoabTemporaryNotificationCtrl />
      <GoabxButton type="tertiary" leadingIcon="download" onClick={downloadReport}>
        Download report
      </GoabxButton>
async downloadReportAPI(notificationUuid: string): Promise<Error | undefined> {
    // Perform your API call here with progress tracking
    // Update progress as download progresses (0-100)
    TemporaryNotification.setProgress(notificationUuid, 25);
    // ... continue API work ...
    TemporaryNotification.setProgress(notificationUuid, 50);
    // ... continue API work ...
    TemporaryNotification.setProgress(notificationUuid, 75);
    // ... complete API work ...
    TemporaryNotification.setProgress(notificationUuid, 100);
    return undefined;
  }

  async downloadReport(): Promise<void> {
    const uuid = TemporaryNotification.show("Downloading report D-23459", {
      type: "progress",
      actionText: "Cancel",
      action: () => {
        TemporaryNotification.dismiss(uuid);
      },
    });

    const err = await this.downloadReportAPI(uuid);

    if (err) {
      TemporaryNotification.show("Download failed", {
        type: "error",
        duration: "medium",
        cancelUUID: uuid,
      });
    } else {
      TemporaryNotification.show("Report downloaded", {
        type: "success",
        duration: "medium",
        actionText: "View",
        action: () => {
          console.log("View report clicked!");
        },
        cancelUUID: uuid,
      });
    }
  }
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goabx-button type="tertiary" leadingIcon="download" (onClick)="downloadReport()">
  Download report
</goabx-button>
const downloadBtn = document.getElementById("download-btn");
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification",
      data: { message, uuid, type: "basic", ...opts }
    }
  }));
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification:dismiss",
      data: uuid
    }
  }));
}

function setProgress(uuid, progress) {
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification:progress",
      data: { uuid, progress }
    }
  }));
}

async function downloadReportAPI(notificationUuid) {
  setProgress(notificationUuid, 25);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 50);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 75);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 100);
}

async function downloadReport() {
  currentUuid = showNotification("Downloading report D-23459", {
    type: "progress",
    actionText: "Cancel",
    action: () => {
      dismissNotification(currentUuid);
    },
  });

  try {
    await downloadReportAPI(currentUuid);
    showNotification("Report downloaded", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View report clicked!");
      },
      cancelUUID: currentUuid,
    });
  } catch (err) {
    showNotification("Download failed", {
      type: "failure",
      duration: "medium",
      cancelUUID: currentUuid,
    });
  }
}

downloadBtn.addEventListener("_click", downloadReport);
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="download-btn" type="tertiary" leadingicon="download">
  Download report
</goa-button>

Show a user progress when the time is unknown

const searchCMS = async (): Promise<Error | undefined> => {
    // Perform your API call here
    await new Promise((resolve) => setTimeout(resolve, 3000));
    return undefined;
  };

  const search = async () => {
    const uuid = TemporaryNotification.show("Searching case management system...", {
      type: "indeterminate",
      actionText: "Cancel",
      action: () => {
        TemporaryNotification.dismiss(uuid);
      },
    });

    const err = await searchCMS();
    if (err) {
      TemporaryNotification.show("Could not connect to case history", {
        type: "failure",
        duration: "medium",
        cancelUUID: uuid,
      });
    } else {
      TemporaryNotification.show("Search complete - 47 records found", {
        type: "success",
        duration: "medium",
        actionText: "View",
        action: () => {
          console.log("View search results clicked!");
        },
        cancelUUID: uuid,
      });
    }
  };
<GoabTemporaryNotificationCtrl />
      <GoabxButton type="secondary" leadingIcon="search" onClick={search}>
        Search case history
      </GoabxButton>
async searchCMS(): Promise<Error | undefined> {
    // Perform your API call here
    await new Promise((resolve) => setTimeout(resolve, 3000));
    return undefined;
  }

  async search(): Promise<void> {
    const uuid = TemporaryNotification.show("Searching case management system...", {
      type: "indeterminate",
      actionText: "Cancel",
      action: () => {
        TemporaryNotification.dismiss(uuid);
      },
    });

    const err = await this.searchCMS();
    if (err) {
      TemporaryNotification.show("Could not connect to case history", {
        type: "failure",
        duration: "medium",
        cancelUUID: uuid,
      });
    } else {
      TemporaryNotification.show("Search complete - 47 records found", {
        type: "success",
        duration: "medium",
        actionText: "View",
        action: () => {
          console.log("View search results clicked!");
        },
        cancelUUID: uuid,
      });
    }
  }
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goabx-button type="secondary" leadingIcon="search" (onClick)="search()">
  Search case history
</goabx-button>
const searchBtn = document.getElementById("search-btn");
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification",
      data: { message, uuid, type: "basic", ...opts }
    }
  }));
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(new CustomEvent("msg", {
    composed: true,
    bubbles: true,
    detail: {
      action: "goa:temp-notification:dismiss",
      data: uuid
    }
  }));
}

async function searchCMS() {
  await new Promise((resolve) => setTimeout(resolve, 3000));
}

async function search() {
  currentUuid = showNotification("Searching case management system...", {
    type: "indeterminate",
    actionText: "Cancel",
    action: () => {
      dismissNotification(currentUuid);
    },
  });

  try {
    await searchCMS();
    showNotification("Search complete - 47 records found", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View search results clicked!");
      },
      cancelUUID: currentUuid,
    });
  } catch (err) {
    showNotification("Could not connect to case history", {
      type: "failure",
      duration: "medium",
      cancelUUID: currentUuid,
    });
  }
}

searchBtn.addEventListener("_click", search);
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="search-btn" type="secondary" leadingicon="search">
  Search case history
</goa-button>

No usage guidelines have been documented for this component yet.

All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

No accessibility-specific guidelines have been documented for this component yet.