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

# Icon - Web

> Icons act as visual aids to help users complete tasks.

> [!NOTE]
>
> For development, import `Icon` from
> `@servicetitan/anvil2`. For design, find it in the
> [Anvil2 file](https://www.figma.com/design/xaNQsvRKczoxu7pj0M6QT8/Anvil2-v3).

![](https://mintcdn.com/servicetitan/H5FwKyiqhPVZ1UJQ/images/docs/web/components/shared/preview-of-icon-component.png?fit=max\&auto=format\&n=H5FwKyiqhPVZ1UJQ\&q=85\&s=8a150a020ecf5e8204d5631388d5d40b)

## Anatomy

The Icon consists of two primary elements that work together to act as visual aids.

![Anatomy of an
icon](https://mintcdn.com/servicetitan/CekIMDXcDEhGoN_I/images/docs/web/components/icon/design/anatomy-of-an-icon.png?fit=max\&auto=format\&n=CekIMDXcDEhGoN_I\&q=85\&s=8df79371b6a430d914bcf9fd289f3b20)

1. Icon
2. Bounding area

## Options

The Icon supports multiple sizes, SVG support, and color configurations to accommodate various visual aid scenarios.

### Sizes

icon-size

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-size?file=src/App.tsx)

```tsx lines theme={null}
import { Icon, Text } from "@servicetitan/anvil2";
import Close from "@servicetitan/anvil2/assets/icons/material/round/close.svg";

function App() {
  return (
    <div
      style={{
        display: "grid",
        gap: "1rem",
        fontFamily: "monospace",
        gridTemplateColumns: "60px 60px 60px 60px",
        justifyItems: "center",
        alignItems: "center",
      }}
    >
      <Icon svg={Close} size="small" />
      <Icon svg={Close} size="medium" />
      <Icon svg={Close} size="large" />
      <Icon svg={Close} size="xlarge" />
      <Text>small</Text>
      <Text>medium</Text>
      <Text>large</Text>
      <Text>xlarge</Text>
    </div>
  );
}

export default App;
```

| Size | Height | When to use |
| - | - | - |
| Small | 12px | For high dense pages. Not recommended for interactive Icons. |
| Medium | 16px | Used within Buttons. |
| Large | 24px | For supplementing information on the page, such as status. |
| Extra Large | 32px | For low density, expressive pages. |

### SVG support

Icon accepts SVGs. This typically involves using Anvil's provided icon library but also supports custom SVGs.

### Color

Icons inherit a color provided to them. When providing a color, use a token value.

icon-inherit

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-inherit?file=src/App.tsx)

```tsx lines theme={null}
import { Icon, Text } from "@servicetitan/anvil2";
import { core } from "@servicetitan/anvil2/token";
import Warning from "@servicetitan/anvil2/assets/icons/material/round/warning.svg";

function App() {
  return (
    <div
      style={{
        display: "grid",
        gap: "1rem",
        fontFamily: "monospace",
        gridTemplateColumns: "140px 140px 140px",
        justifyItems: "center",
        textAlign: "center",
      }}
    >
      <span>
        <Icon svg={Warning} size="large" />
      </span>
      <span style={{ color: core.semantic.BackgroundColorDanger.value }}>
        <Icon svg={Warning} size="large" inherit />
      </span>
      <span style={{ color: "#FF0000" }}>
        <Icon svg={Warning} size="large" inherit />
      </span>
      <Text>no color added</Text>
      <Text>token value (recommended)</Text>
      <Text>raw hex value (not recommended)</Text>
    </div>
  );
}

export default App;
```

## Behavior

The Icon responds to different size and color requirements while maintaining consistent visual representation.

## Usage Guidelines

| Standard | Requirement |
| - | - |
| DoEnhance understanding of a concept | Icons enhance the understanding of a concept. They also work well in places where space is a premium. |
| DoProvide a label for Icons | Provide a label for an Icon as a text label next to it, or as a Tooltip; a text label is generally preferred since most icons don't have an obvious meaning; see [Provide a label for Icons](#provide-a-label-for-icons). |
| Don'tUse icons for their own sake | Avoid using Icons for the sake of having icons. Most icons have ambiguous meaning and result in confusion and an overwhelming visual design. |
| Don'tInconsistent icon usage | Consistent icon usage of status and actions brings familiarity — use the standard a product has adopted; see [Consistent icon usage](#consistent-icon-usage). |

### How to Use

#### Provide a label for Icons

An Icon's label takes two forms: as a text label next to an icon, or as a [Tooltip](https://anvil.servicetitan.com/docs/components/tooltip/web.md). A text label is generally preferred as most icons do not have an obvious meaning.

icon-label-obvious-text-do

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-label-obvious-text-do?file=src/App.tsx)

```tsx lines theme={null}
import { Button } from "@servicetitan/anvil2";
import Edit from "@servicetitan/anvil2/assets/icons/material/round/edit.svg";

function App() {
  return (
    <Button icon={Edit} appearance="ghost">
      Edit
    </Button>
  );
}

export default App;
```

> [!TIP]
>
> **Do**

icon-label-obvious-tooltip-do

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-label-obvious-tooltip-do?file=src/App.tsx)

```tsx lines theme={null}
import { Button, Tooltip } from "@servicetitan/anvil2";
import Edit from "@servicetitan/anvil2/assets/icons/material/round/edit.svg";

function App() {
  return (
    <Tooltip open>
      <Tooltip.Trigger>
        <Button icon={Edit} appearance="ghost" />
      </Tooltip.Trigger>
      <Tooltip.Content>Edit</Tooltip.Content>
    </Tooltip>
  );
}

export default App;
```

> [!TIP]
>
> **Do**

icon-label-nonobvious-text-do

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-label-nonobvious-text-do?file=src/App.tsx)

```tsx lines theme={null}
import { Button } from "@servicetitan/anvil2";
import AddCircle from "@servicetitan/anvil2/assets/icons/material/round/add_circle.svg";

function App() {
  return (
    <Button icon={AddCircle} appearance="ghost">
      Add Widget
    </Button>
  );
}

export default App;
```

> [!TIP]
>
> **Do**

Labels can clarify what the icon is trying to represent.

icon-label-nonobvious-tooltip-caution

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-label-nonobvious-tooltip-caution?file=src/App.tsx)

```tsx lines theme={null}
import { Button, Tooltip } from "@servicetitan/anvil2";
import AddCircle from "@servicetitan/anvil2/assets/icons/material/round/add_circle.svg";

function App() {
  return (
    <Tooltip open>
      <Tooltip.Trigger>
        <Button icon={AddCircle} appearance="ghost" />
      </Tooltip.Trigger>
      <Tooltip.Content>Add Widget</Tooltip.Content>
    </Tooltip>
  );
}

export default App;
```

> [!WARNING]
>
> **Caution**

More ambiguous actions are less discoverable when only providing a Tooltip.

#### Provide information without action

Icon provides indication for users and can be focused or hovered to convey more details. In these use cases, add `tabIndex={0}` to make icon focusable and use Tooltip with it.

icon-tabindex-do

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-tabindex-do?file=src/App.tsx)

```tsx lines theme={null}
import { Icon, Tooltip } from "@servicetitan/anvil2";
import Warning from "@servicetitan/anvil2/assets/icons/material/round/warning.svg";

function App() {
  return (
    <Tooltip>
      <Tooltip.Trigger>
        <Icon svg={Warning} tabIndex={0} />
      </Tooltip.Trigger>
      <Tooltip.Content>Hello, I&apos;m a tooltip</Tooltip.Content>
    </Tooltip>
  );
}

export default App;
```

#### Consistent icon usage

Consistent icon usage of status and actions brings familiarity. Use the standard that a product has adopted.

icon-consistent-dont

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-consistent-dont?file=src/App.tsx)

```tsx lines theme={null}
import { Button } from "@servicetitan/anvil2";
import Add from "@servicetitan/anvil2/assets/icons/material/round/add.svg";
import AddCircle from "@servicetitan/anvil2/assets/icons/material/round/add_circle.svg";

function App() {
  return (
    <span>
      <Button icon={Add} appearance="ghost">
        Add Object
      </Button>
      <Button icon={AddCircle} appearance="ghost">
        Add Thing
      </Button>
    </span>
  );
}

export default App;
```

> [!CAUTION]
>
> **Don't**

#### Use semantic token colors for Icons

When using color for Icons, use a semantic token value. This ensures an icon is both themeable and internally consistent with other UI's color usage.

#### Avoid custom icon resizing

Icons have a consistent set of dimensions. Resizing breaks the internal consistency and creates awkward vector scaling.

## Content

Content within the Icon should be clear and recognizable, helping users understand the concept being represented.

## Keyboard Interaction

Users can navigate the Icon using standard keyboard controls.

### Accessibility

#### Non-interactive Icons

Pair Icons with a text label when possible.

When using an Icon without text, provide an `aria-label` to the Icon directly, describing what the icon is.

For more guidance on icon accessibility, see [accessible icon usage best practices](https://anvil.servicetitan.com/docs/accessibility/media-and-animation.md#alt-tags-vs-decorative-images).

## Code

**Implementation**

icon-playground

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/icon-playground?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Icon } from "@servicetitan/anvil2";
import Warning from "@servicetitan/anvil2/assets/icons/material/round/warning.svg";

function App() {
  return <Icon svg={Warning} size="large" />;
}

export default App;
```

## Common Examples

```tsx theme={null}
import { Icon } from "@servicetitan/anvil2";
import EditIcon from "@servicetitan/anvil2/assets/icons/material/round/Edit.svg";

function ExampleComponent() {
  return <Icon svg={EditIcon} color="var(--color-green-300)" size="large" />;
}
```

### SVGR Config

Anvil2 icons are pure SVGs, and require a special loader to properly handle imports and rendering – SVGR. Any project using the `@servicetitan/startup` package version `23.5.0` or later will already have this configured. To use Anvil2 in a standalone app or other project, the SVGR plugin needs to be configured to properly render Anvil2 icons.

Use the examples below for common build tools. For other build tools, check out the [SVGR docs](https://react-svgr.com/docs/getting-started/) (or the specific build tool docs) for how to update the config object, and be sure to disable the `removeViewbox` option in the `svgoConfig` (see the examples for more details).

#### Webpack SVGR Config

```javascript theme={null}
{
  loader: "@svgr/webpack",
  options: {
    svgoConfig: {
      plugins: [
        {
          name: "preset-default",
          params: {
            overrides: {
              removeViewBox: false,
            },
          },
        },
      ],
    },
  },
}
```

*Learn more about [Webpack loaders](https://webpack.js.org/concepts/loaders).*

#### Vite SVGR Config

```javascript theme={null}
import svgr from "vite-plugin-svgr";

export default {
  plugins: [
    svgr({
      svgrOptions: {
        svgoConfig: {
          plugins: [
            {
              name: "preset-default",
              params: {
                overrides: {
                  removeViewBox: false,
                },
              },
            },
          ],
        },
      },
    }),
  ],
};
```

## React Accessibility

#### Non-interactive Icons

Icons that lack interaction and have no accompanying text only need an `aria-label` to describe what the Icon is. If paired with text, no additional elements are needed.

**Decorative icon paired with a text label**

`<div><Icon svg={Warning} size="large" /> <BodyText>Label Text</BodyText> </div>`

**Standalone icon with no text label**

`<Icon svg={Warning} size="large" aria-label="Warning" />`

#### Interactive Icons

Icon can be used to provide indication for users which can be focused or hovered to convey more details. In these use cases, add `tabIndex={0}` to make icon focusable and use Tooltip with it.

For more guidance on icon accessibility, see [accessible icon usage best practices](https://anvil.servicetitan.com/docs/accessibility/media-and-animation.md#alt-tags-vs-decorative-images).

**Icon Props**

```tsx theme={null}
<Icon
  svg={EditIcon}
  color="var(--color-green-300)"
  size="large"
  inherit={false}
  aria-label="Edit"
/>
```

## `Icon` Props

In addition to the props listed below, the `Icon` component can accept any valid HTML `span` props.

**svg** `Svg` *required*

Assets passed in using SVGR.

**color** `string`

Accepts valid CSS color values, including CSS variables.

**inherit** `boolean` (default: false)

Allows the icon SVG to inherit its color.

**size** `"small" | "medium" | "large" | "xlarge"` (default: medium)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.