> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Toast – Design

> Toasts are temporary alerts that appear as a direct result of a user action.

export const LiveCode = ({children, customHeight, clickToLoad, example, fullWidth, fullHeight, hideCodeInLiveCode, screenshot, screenshotOnly, showCode: showCodeProp}) => {
  const SCREENSHOTS_BASE = "https://servicetitan.github.io/anvil2-docs-live-code/screenshots";
  const STACKBLITZ_BASE = "https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples";
  const [showCodeBlock, setShowCodeBlock] = useState(showCodeProp ?? false);
  const [isLocalOverride, setIsLocalOverride] = useState(false);
  useEffect(() => {
    const examplePath = `/images/live-code-screenshots-tmp/${example}.png`;
    fetch(examplePath, {
      method: "HEAD"
    }).then(r => {
      if (r.ok) setIsLocalOverride(true);
    }).catch(() => {});
  }, [example]);
  const screenshotBase = isLocalOverride ? "/images/live-code-screenshots-tmp" : SCREENSHOTS_BASE;
  if (screenshotOnly) {
    return <Frame className="flex flex-col">
        <div className="flex dark:hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#FFFFFF"
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>
        <div className="hidden dark:flex" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#141414"
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>
      </Frame>;
  }
  if (screenshot) {
    return <Frame className="flex flex-col -mb-2">
        <div className="flex dark:hidden bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>

        <div className="hidden dark:flex bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      background: "#141414",
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>

        <div className="flex justify-end items-center text-xs py-2 px-1 gap-4">
          {!showCodeProp ? <button className="inline-flex justify-end items-center text-gray-700 dark:text-gray-50 hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1 cursor-pointer" onClick={() => setShowCodeBlock(!showCodeBlock)} style={{
      appearance: "none"
    }}>
              <Icon icon="code" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
              <span>{showCodeBlock ? "Hide code" : "Show code"}</span>
            </button> : null}

          <a className="inline-flex justify-end items-center hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1" href={`${STACKBLITZ_BASE}/${example}?file=src/App.tsx`} target="_blank" rel="noreferrer">
            <Icon icon="bolt" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
            <span>StackBlitz demo</span>
          </a>
        </div>

        <div className="grid transition-[grid-template-rows] duration-300 ease-in-out overflow-auto overflow-y-hidden overflow-x-auto" style={showCodeBlock ? {
      gridTemplateRows: "1fr"
    } : {
      gridTemplateRows: "0fr"
    }}>
          <div style={{
      minHeight: 0,
      overflowX: "auto",
      overflowY: "hidden",
      marginBlockStart: "-1.25rem",
      marginBlockEnd: "-1.5rem"
    }}>
            {children}
          </div>
        </div>
      </Frame>;
  } else {
    return <div style={{
      display: "flex",
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px",
      resize: "vertical",
      overflow: "auto"
    }}>
        <iframe title={example} style={{
      flex: 1,
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px"
    }} src={`${STACKBLITZ_BASE}/${example}?embed=1&hideNavigation=1&hideExplorer=1&terminalHeight=0&file=src/App.tsx${clickToLoad ? "&ctl=1" : ""}${hideCodeInLiveCode ? "&view=preview" : ""}`} allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" />
      </div>;
  }
};

export const CodePreviewPlaceholder = ({double, fullWidth}) => {
  const single = <div style={{
    width: fullWidth ? "100%" : "50%",
    borderRadius: "1rem",
    display: "flex",
    padding: "1rem",
    flexDirection: "column",
    gap: "0.5rem",
    height: "10rem",
    marginBlockEnd: "1rem"
  }} className="border-width-default border-color-subdued">
      <div className="bg-strong border-radius-large" style={{
    width: "100%",
    flexGrow: "1"
  }} />
      <div className="bg-strong border-radius-large" style={{
    width: "100%",
    flexGrow: "1"
  }} />
    </div>;
  return double ? <div style={{
    display: "flex",
    gap: "1rem"
  }}>
      {single}
      {single}
    </div> : single;
};

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img noZoom src="https://mintcdn.com/servicetitan/H5FwKyiqhPVZ1UJQ/images/docs/web/components/shared/toast-main-image.png?fit=max&auto=format&n=H5FwKyiqhPVZ1UJQ&q=85&s=44599d3fe91f9599965341df10901932" width="846" height="212" data-path="images/docs/web/components/shared/toast-main-image.png" />
  </div>
</Frame>

## Anatomy

The Toast consists of four primary elements that work together to create temporary alerts that appear as a direct result of a user action.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-anatomy.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=cb5a2fc28ff1cb161d64e58525909700"
      alt="Toast
anatomy"
      width="924"
      height="372"
      data-path="images/docs/web/components/toast/design/toast-anatomy.png"
    />
  </div>
</Frame>

1. Title
2. Body content
3. Actions
4. Close button

## Options

The Toast supports the following configurations to accommodate various notification scenarios.

### Status

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-status-examples.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=2aaf186846ba911401f3b03caaffb3d8"
    alt="Toast status
examples"
    width="1300"
    height="940"
    data-path="images/docs/web/components/toast/design/toast-status-examples.png"
  />
</Frame>

| Type           | Description                                                                                                                   |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Informational  | Non-essential information as the result of a user action.                                                                     |
| Success        | Confirmation that a task was successfully completed.                                                                          |
| Warning        | Information to warn users of a potential issue as the result of an action. Often paired with an action to help users recover. |
| Critical/Error | Used to communicate an error or other failure. Often paired with an action to help users recover.                             |

### Content Area

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-content-area-examples.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=27fcc5505cec008a469952f95519f8db"
    alt="Toast content area
examples"
    width="1300"
    height="850"
    data-path="images/docs/web/components/toast/design/toast-content-area-examples.png"
  />
</Frame>

At minimum, a Toast consists of a title. Toasts also support body content, including a body message, actions, or progress bar.

### AI Mark

<LiveCode example="ai-mark-toast" fullWidth>
  ```tsx lines theme={null}
  import { toast, Flex, Grid, Button } from "@servicetitan/anvil2";

  function App() {
    const config = {
      title: "AI dispatch digest",
      message:
        "Today: 6 jobs—2 AC tune-ups, 2 drain calls, 1 heat-pump startup, and 1 panel inspection. Two are marked urgent.",
      duration: 8000,
      aiMark: true,
    };

    return (
      <div style={{ minHeight: "284px" }}>
        <Flex justifyContent="center">
          <Grid templateColumns="repeat(2, 12rem)" gap="2">
            <Button onClick={() => toast.info(config)} style={{ width: "100%" }}>
              Show info toast
            </Button>
            <Button
              onClick={() => toast.success(config)}
              style={{ width: "100%" }}
            >
              Show success toast
            </Button>
            <Button
              onClick={() => toast.warning(config)}
              style={{ width: "100%" }}
            >
              Show warning toast
            </Button>
            <Button
              onClick={() => toast.danger(config)}
              style={{ width: "100%" }}
            >
              Show danger toast
            </Button>
          </Grid>
        </Flex>
      </div>
    );
  }

  export default App;
  ```
</LiveCode>

Include an [AI Mark](/docs/web/components/ai-mark/code) in a Toast when the title should indicate AI-generated content.

## Usage Guidelines

Use the Toast when the user does not need to be interrupted and is being informed of an event with the option to take action.

### When to Use

Toast notifications are used when:

* The user does not need to be interrupted.
* The user is being informed of an event, with the option to take action.
* The results of an action are delayed.
* The notification could appear anywhere in the application.

See the notification pattern for additional guidance.

#### Status Variations

##### Informational

Communicates operational information to the user. These are commonly used to denote the start of an operation, and usually includes follow-up notifications.

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-status-info-example.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=29d3bef7e015463003d911726e94a8f9"
    alt="Toast Status Info
Example"
    width="1300"
    height="328"
    data-path="images/docs/web/components/toast/design/toast-status-info-example.png"
  />
</Frame>

##### Success

Communicates the success of an operation, e.g., user preferences were updated.

Avoid including the term "successfully" in success Toasts as it duplicates information.

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-status-success-example.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=8bcd001f7a6a7481f3f3cb0ecc4f42ad"
    alt="Toast Status Success
Example"
    width="1300"
    height="328"
    data-path="images/docs/web/components/toast/design/toast-status-success-example.png"
  />
</Frame>

##### Critical/Error

Critical Toasts are used when an operation was unable to be performed or has failed. Page-specific and form errors should utilize the Alert notification. When applicable, users should be able to take action on an operation.

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-status-error-example.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=1ccd05bd283a50f06ef88dd4afe4420c"
    alt="Toast Status Error
Example"
    width="1300"
    height="328"
    data-path="images/docs/web/components/toast/design/toast-status-error-example.png"
  />
</Frame>

##### Warning

Warnings are distinct from errors and represent issues that do not need an immediate resolution, but still need to be addressed. Unintended consequences in an operation and fallback choices are common examples. In general, users should be able to take action on a warning.

<Frame>
  <img
    src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-status-warning-example.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=a9db407c22426d48344ce2d36e959faa"
    alt="Toast Status Warning
Example"
    width="1300"
    height="328"
    data-path="images/docs/web/components/toast/design/toast-status-warning-example.png"
  />
</Frame>

### Alternatives

#### Toast vs Alert

Alerts are used to communicate information about either part of a page or a whole page. Alerts can be used to summarize information, such as a summary of errors.

Toasts are brief pieces of information and usually appear as the result of user action.

#### Toast vs Announcement

Announcements are used to convey app-wide messages, such as a new release being available, application maintenance, or sandbox information.

Toasts are short pieces of information usually prompted by user action.

## Behavior

The Toast responds to timing requirements and positioning constraints while maintaining consistent notification appearance.

### How to Use

#### Positioning

Toasts are positioned in the top-right of the screen on top of application UI. Toasts do not cover any part of the global navigation.

#### Timing

By default, Toasts are persistent until dismissed by a user. An optional timeout is available. The recommended duration is 8 seconds, but this can be customized.

Toasts are always persistent in the following cases:

* When there are any actions within the Toast.
* When a Toast contains a Progress Bar.
* When a Toast is in an error state.

Avoid adding a timeout when a Toast contains information that users may need to copy or remember.

#### Progress Bar

When the time to complete a task can be calculated, pair a Toast with a [Progress Bar](/docs/web/components/progress-bar/design).

## Content

Content within the Toast should be brief, scannable, and actionable.

### Titles should be brief and scannable and as specific as possible.

Use sentence case. Don't use periods and exclamation points, and avoid articles: a, an, the.

### Write titles as verbs

Titles should have a clear verb + noun question or statement.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-do-example-that-has-title-that-says-unable-to-create-geofence-and-body-text-that-says-we-werent-able-to-create-the-geofence-please-try-again.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=13412db9543f8261f15b4672621b8919"
      alt="Toast &#x22;Do&#x22; example that has title that says &#x22;Unable to create geofence&#x22;
and body text that says &#x22;We weren't able to create the geofence. Please try
again.&#x22;"
      width="900"
      height="348"
      data-path="images/docs/web/components/toast/design/toast-do-example-that-has-title-that-says-unable-to-create-geofence-and-body-text-that-says-we-werent-able-to-create-the-geofence-please-try-again.png"
    />
  </div>
</Frame>

<Check>**Do**</Check>

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-dont-example-that-has-a-title-that-says-request-failed-and-body-text-that-says-something-went-wrong-please-try-again.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=286cbb50bde39c463982f1f73ee81049"
      alt="Toast &#x22;Don't&#x22; example that has a title that says &#x22;Request failed&#x22; and body
text that says &#x22;Something went wrong. Please try
again.&#x22;"
      width="900"
      height="352"
      data-path="images/docs/web/components/toast/design/toast-dont-example-that-has-a-title-that-says-request-failed-and-body-text-that-says-something-went-wrong-please-try-again.png"
    />
  </div>
</Frame>

<Danger>**Don't**</Danger>

### Messages that can be communicated in a single header don't require body text.

Body text should only provide information that is not included in the header. Do not repeat information that's already in the header.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-do-example-with-only-a-title-that-says-geofence-created-successfully.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=3ec92b9f5f31ae2021f3020eb90eed94"
      alt="Toast &#x22;Do&#x22; example with only a title that says &#x22;Geofence created
successfully&#x22;"
      width="900"
      height="364"
      data-path="images/docs/web/components/toast/design/toast-do-example-with-only-a-title-that-says-geofence-created-successfully.png"
    />
  </div>
</Frame>

<Check>**Do**</Check>

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-dont-example-with-a-title-that-says-geofence-created-successfully-and-body-text-that-says-the-geofence-has-been-created-successfully.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=c4617e564981e203c3119858eeffb702"
      alt="Toast &#x22;Don't&#x22; example with a title that says &#x22;Geofence created
successfully&#x22; and body text that says &#x22;The geofence has been created
successfully&#x22;"
      width="900"
      height="364"
      data-path="images/docs/web/components/toast/design/toast-dont-example-with-a-title-that-says-geofence-created-successfully-and-body-text-that-says-the-geofence-has-been-created-successfully.png"
    />
  </div>
</Frame>

<Danger>**Don't**</Danger>

### Make body content concise, informative, and actionable

Use imperative verbs when telling users what they need to know or do. Avoid permissive language like "you can".

Whenever possible, include an in-line action for a user to take so that they can readily address the issue explained in the message.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-do-example-with-title-that-says-some-drivers-havent-been-mapped-and-body-text-that-says-all-drivers-must-be-mapped-to-a-technician-before-you-can-move-to-the-next-step.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=3ce33f1499f549e986cb6897c8ef1989"
      alt="Toast &#x22;Do&#x22; example with title that says &#x22;Some drivers haven't been mapped&#x22;
and body text that says &#x22;All drivers must be mapped to a technician before
you can move to the next
step.&#x22;"
      width="900"
      height="404"
      data-path="images/docs/web/components/toast/design/toast-do-example-with-title-that-says-some-drivers-havent-been-mapped-and-body-text-that-says-all-drivers-must-be-mapped-to-a-technician-before-you-can-move-to-the-next-step.png"
    />
  </div>
</Frame>

<Check>**Do**</Check>

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-dont-example-that-has-a-title-that-says-request-failed-and-body-text-that-says-something-went-wrong-please-try-creating-again.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=e231bef4acb36b3e587c4957b1f40025"
      alt="Toast &#x22;Don't&#x22; example that has a title that says &#x22;Request failed&#x22; and body
text that says &#x22;Something went wrong. Please try creating
again.&#x22;"
      width="900"
      height="404"
      data-path="images/docs/web/components/toast/design/toast-dont-example-that-has-a-title-that-says-request-failed-and-body-text-that-says-something-went-wrong-please-try-creating-again.png"
    />
  </div>
</Frame>

<Danger>**Don't**</Danger>

### Buttons should be clear, predictable, and action-oriented

Users should be able to predict what will happen when they click a button.

Lead with a strong verb that encourages action. Use a verb/noun pair on actions in most cases. Common actions like Save, Close, or Cancel do not require an accompanying noun.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-do-example-that-has-title-that-says-submission-error-and-body-text-that-says-an-issue-was-encountered-process-the-request-please-try-again-or-view-the-results-for-more-details-and-two-buttons-th.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=2fd3b99665c93842891a1ca65a19e569"
      alt="Toast &#x22;Do&#x22; example that has title that says &#x22;Submission error&#x22; and body
text that says &#x22;An issue was encountered process the request. Please try
again or view the results for more details.&#x22; and two buttons. The first
button says &#x22;Try Again&#x22; and the second button says &#x22;View
Results&#x22;"
      width="900"
      height="506"
      data-path="images/docs/web/components/toast/design/toast-do-example-that-has-title-that-says-submission-error-and-body-text-that-says-an-issue-was-encountered-process-the-request-please-try-again-or-view-the-results-for-more-details-and-two-buttons-th.png"
    />
  </div>
</Frame>

<Check>**Do**</Check>

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/toast/design/toast-dont-example-with-a-title-that-says-submission-error-with-no-body-text-and-two-buttons-the-first-button-says-results-and-the-second-button-says-view.png?fit=max&auto=format&n=ar8TJanaRSxOpbCO&q=85&s=73e5d60bfe0f3ece0d686103defda20b"
      alt="Toast &#x22;Don't&#x22; example with a title that says &#x22;Submission error&#x22; with no
body text and two buttons. The first button says &#x22;Results&#x22; and the second
button says
&#x22;View&#x22;"
      width="900"
      height="506"
      data-path="images/docs/web/components/toast/design/toast-dont-example-with-a-title-that-says-submission-error-with-no-body-text-and-two-buttons-the-first-button-says-results-and-the-second-button-says-view.png"
    />
  </div>
</Frame>

<Danger>**Don't**</Danger>
