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

# Actionable Language

> Use clear, actionable language to deliver a seamless user experience.

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

Create concise, user-focused messaging that enhances clarity, builds trust, and ensures consistency across all touchpoints, helping users achieve their goals with ease.

### Titles, Headings, and Subheadings

Titles, headings, and subheadings are the first things users see when interacting with content. They need to be clear, concise, and immediately convey the purpose or action required.

**Do:**

* **Be clear and concise:** Titles and headings should immediately communicate the purpose or content. Use straightforward language that gets to the point.
* **Use action-oriented language:** Encourage users to take action by starting titles and headings with verbs when applicable.\
  *Example:* "Set Up Your Account" instead of "Account Setup."
* **Capitalize properly:** Use title case for titles, headings, and subheadings to maintain a professional and polished appearance.\
  *Example:* "Create a New Invoice."
* **Prioritize User Benefits:** Frame titles and headings around what the user gains or achieves.\
  *Example:* "Improve Efficiency with Automated Reports" instead of "Automated Reports."

**Don’t:**

* **Overload with information:** Avoid cramming too much detail into titles or headings.
* **Use jargon without explanation:** If trade-specific language is necessary, ensure it is understood by the target audience or provide a brief explanation.\
  *Avoid:* "Configure HVAC Load Calculations" unless your audience is familiar with these terms.

#### How to Use

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

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text el="h4" variant="headline" size="large">
          Manage Your Payments
        </Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Straightforward language that gets to the point, avoid "Payment Management Portal."

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

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text el="h4" variant="headline" size="large">
          Quickly and Easily Manage and Update All of Your Customer Information in
          One Place.
        </Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Overload with information. Keep it focused on the key message.

### Sentences

In-app copy should be easy to read and understand, guiding users through actions with minimal friction. The following guidelines ensure that sentences are clear, direct, and aligned with the overall user experience.

**Do:**

* **Use active voice:** Active voice makes sentences more direct and engaging. It clearly identifies who is doing what.
* **Keep it simple:** Aim for short, straightforward sentences that are easy to read and understand\
  *Example:* "Click ‘Submit’ to complete the process."
* **Be consistent:** Maintain a consistent tone and style that aligns with ServiceTitan’s voice—simple, bold, and authentic.\
  *Example:* "You’re in control" instead of "Take control of your settings."
* **Be directive and precise:** Guide users with clear instructions that leave no room for ambiguity.\
  *Example:* "Select a date range" instead of "You might want to select a date range."
* **Align with user goals:** Structure sentences around the user’s objectives, highlighting how the feature or action supports their needs.\
  *Example:* "Streamline your workflow by automating reminders."

**Don’t:**

* **Use complex sentence structures:** Avoid using multiple clauses or unnecessary words that could confuse the user.
* **Be vague:** Avoid vague or passive language that doesn’t clearly guide the user.\
  *Avoid:* "It might be beneficial to review your settings" instead of "Review your settings."
* **Overuse technical terms:** Even in a trade-focused context, too many technical terms can overwhelm users. Balance them with plain language.\
  *Avoid:* "Calibrate the thermostat settings according to ASHRAE standards" without providing context.

#### How to Use

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

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>
          Click <b>Submit</b> to complete the process.
        </Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Aim for short, straightforward sentences that are easy to read and understand.

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

  function App() {
    return (
      <Flex direction="column" gap="3">
        <Text>
          After you have filled in all the fields, and checked for accuracy, click
          the <b>Submit</b> button to save the form.
        </Text>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Avoid using multiple clauses or unnecessary words that could confuse the user.

### Error Messages

Error messages are critical touchpoints in the user experience. They should not only inform users about what went wrong but also guide them on how to fix the issue. Effective error messages are clear, concise, and constructive, helping users to quickly resolve problems and continue their journey without frustration.

#### How to Use

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

  function App() {
    return (
      <Flex direction="column" gap="4">
        <Alert
          title="Invalid email address"
          status="danger"
          onClose={console.log}
        >
          Please enter a valid email.
        </Alert>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Be clear about what went wrong and what the user can do to fix it.

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

  function App() {
    return (
      <Flex direction="column" gap="4">
        <Alert title="Error 404" status="danger" onClose={console.log} />
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Use generic error messages that don’t help the user understand or resolve the issue.

### Buttons and CTAs

Buttons and Calls to Action (CTAs) are the driving force behind user interactions within the product. They need to be clear, compelling, and direct, guiding users towards the next step in their journey. Well-crafted buttons and CTAs encourage engagement and make it easy for users to take action with confidence.

#### How to Use

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

  function App() {
    return (
      <Grid templateColumns="repeat(1, max-content)" gap="12">
        <Flex gap="4">
          <Button appearance="primary">Start free trial</Button>
        </Flex>
      </Grid>
    );
  }

  export default App;
  ```
</LiveCode>

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

Use strong, action-oriented verbs that clearly state what will happen next.

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

  function App() {
    return (
      <Grid templateColumns="repeat(1, max-content)" gap="12">
        <Flex gap="4">
          <Button appearance="primary">Learn more</Button>
        </Flex>
      </Grid>
    );
  }

  export default App;
  ```
</LiveCode>

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

Use vague terms like "Click Here" that don’t provide context.

### Tooltips

Tooltips provide users with additional information or guidance without overwhelming them. They should be brief and to the point, offering just enough context to support the user's next action. Effective tooltips enhance the user experience by providing timely and relevant information in a non-intrusive manner.

#### How to Use

<LiveCode example="actionablelanguage-tooltip-do" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Tooltip, Flex, Button } from "@servicetitan/anvil2";
  import Info from "@servicetitan/anvil2/assets/icons/material/round/info.svg";

  function App() {
    return (
      <Flex
        direction="column"
        gap="4"
        style={{ paddingBlockStart: "3.5rem", paddingInline: "3.5rem" }}
      >
        <Tooltip defaultOpen>
          <Tooltip.Trigger>
            <Button icon={Info}>Hover over me</Button>
          </Tooltip.Trigger>
          <Tooltip.Content>
            This will lock your settings until they’re manually changed.
          </Tooltip.Content>
        </Tooltip>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Keep them brief and to the point, offering just enough information to guide the user.

<LiveCode example="actionablelanguage-tooltip-dont" screenshot fullWidth>
  ```tsx lines theme={null}
  import { Tooltip, Flex, Button } from "@servicetitan/anvil2";
  import Info from "@servicetitan/anvil2/assets/icons/material/round/info.svg";

  function App() {
    return (
      <Flex
        direction="column"
        gap="4"
        style={{ paddingBlockStart: "7.5rem", paddingInline: "3.5rem" }}
      >
        <Tooltip defaultOpen>
          <Tooltip.Trigger>
            <Button icon={Info}>Hover over me</Button>
          </Tooltip.Trigger>
          <Tooltip.Content>
            This will lock your settings until they’re manually changed. If you
            need to unlock your settings, be sure to visit the Profile Settings
            page and click the lock to make changes.
          </Tooltip.Content>
        </Tooltip>
      </Flex>
    );
  }

  export default App;
  ```
</LiveCode>

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

Overload tooltips with too much information. They should support, not overwhelm.
