> ## 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.

# Confirmation Messages

> Confirmation messages are crucial touchpoints that verify user actions and provide an opportunity to ensure the user's intention before proceeding.

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>;
  }
};

They should be clear, concise, and respectful of the user's workflow, minimizing disruption while maximizing clarity.

### Guiding principles for confirmation messages

**Be selective with confirmation prompts**

* **Purpose:** Use confirmation messages only when the action is significant, irreversible, or could lead to data loss. Avoid overusing them, as this can interrupt the user experience and lead to "confirmation fatigue," where users dismiss messages without fully engaging.
* **Efficiency:** Prioritize the user's time by only presenting confirmations when absolutely necessary. This shows respect for their workflow and confidence in their decisions.
* **Example:**
  * **Do:** Use a confirmation prompt when a user is about to delete an account or data that cannot be recovered.
  * **Don’t:** Prompt for confirmation when saving settings that can easily be changed back.

**Ensure clarity and simplicity**

* **Directness:** The confirmation message should directly state what the user is confirming, using a simple and straightforward verb+noun structure. Avoid unnecessary words or jargon.
* **Tone:** Use a tone that is confident and reassuring, aligned with ServiceTitan's brand voice. The language should be simple, bold, and authentic, resonating with the direct communication style of the trades professionals who use the product.

**Communicate consequences clearly**

* **Transparency:** Clearly explain what will happen as a result of the action, especially if it is irreversible. Users should understand the implications without needing to read lengthy explanations.
* **Brevity:** Keep the explanation short, focusing on the most critical information that the user needs to know to make an informed decision.

**Align CTA labels with action**

* **Consistency:** The primary CTA (Call to Action) should mirror the action described in the confirmation message. This ensures that even if a user only reads the title and the CTA, they will understand the action they are confirming.
* **Verb-noun structure:** Use a clear verb+noun structure for CTA labels to reinforce the action, e.g., "Delete Job" instead of just "Delete."

**Minimize Disruption**

* **User Flow:** Confirmation messages should be as non-intrusive as possible. Design them to fit seamlessly into the user journey, providing necessary checks without breaking the flow.
* **Visual Design:** Ensure that the confirmation message is visually aligned with the rest of the UI, using clear buttons and intuitive layouts that guide the user naturally.

**Examples**

#### Ensure clarity and simplicity

<LiveCode example="confirmationmessages-simple-do" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Text, Flex } from "@servicetitan/anvil2";

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>Delete this job?</Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

<LiveCode example="confirmationmessages-simple-dont" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Text, Flex } from "@servicetitan/anvil2";

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>Are you sure you want to delete this job?</Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

#### Communicate consequences clearly

<LiveCode example="confirmationmessages-clear-do" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Text, Flex } from "@servicetitan/anvil2";

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>This action cannot be undone.</Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

<LiveCode example="confirmationmessages-clear-dont" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Text, Flex } from "@servicetitan/anvil2";

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>
          Are you sure you want to proceed? If you delete this, it will be gone
          forever, and there’s no way to recover it.
        </Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

#### Align CTA labels with action

<LiveCode example="confirmationmessages-button-do" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Dialog, Flex, Button } from "@servicetitan/anvil2";

  function App() {
    return (
      <div style={{ minWidth: "23rem", minHeight: "12rem" }}>
        <Dialog enableScrollChaining open>
          <Dialog.Header>Delete this job?</Dialog.Header>
          <Dialog.Content>This action cannot be undone.</Dialog.Content>
          <Dialog.Footer>
            <Flex justifyContent="flex-end">
              <Flex gap="3">
                <Dialog.CancelButton>Cancel</Dialog.CancelButton>
                <Button appearance="danger">Delete Job</Button>
              </Flex>
            </Flex>
          </Dialog.Footer>
        </Dialog>
      </div>
    );
  }

  export default App;
  ```
</LiveCode>

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

<LiveCode example="confirmationmessages-button-dont" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Dialog, Flex, Button } from "@servicetitan/anvil2";

  function App() {
    return (
      <div style={{ minWidth: "23rem", minHeight: "14rem" }}>
        <Dialog enableScrollChaining open>
          <Dialog.Header>Delete this job?</Dialog.Header>
          <Dialog.Content>
            Are you sure? If you delete this, it can not be recovered. This is
            permanent.
          </Dialog.Content>
          <Dialog.Footer>
            <Flex justifyContent="flex-end">
              <Flex gap="3">
                <Dialog.CancelButton>Cancel</Dialog.CancelButton>
                <Button appearance="danger">Yes, I&apos;m sure</Button>
              </Flex>
            </Flex>
          </Dialog.Footer>
        </Dialog>
      </div>
    );
  }

  export default App;
  ```
</LiveCode>

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

### Structure of a Confirmation Message

**Title: Action-oriented and direct**

* Use a clear verb+noun format (e.g., "Delete this job?").
* Keep it concise, typically one sentence in sentence case.
* Maintain a straightforward, confident tone.

**Context: Brief and relevant**

* Provide essential information in 1-2 sentences.
* Avoid repeating the title and focus on what the user needs to know.

**Consequence: Clear and unambiguous**

* State the impact of the action, especially if irreversible.
* Use simple, direct language (e.g., "This action cannot be undone.").

**Primary CTA: Reflect the action**

* Match the CTA label with the title (e.g., "Delete Job").
* Ensure the primary action is prominent, with a clear verb+noun structure.
