# Icon

Icons are used to visually represent an idea or action. They can act as
wayfinding tools to orient users in the product, and identify common
interactions.

> **NOTICE:** Looking to add a new Icon to Atlantis? Read the [Adding an
> icon](../guides/adding-an-icon) guide before you get started.

## Design & usage guidelines

Icons should generally be paired with a label to help users understand the
meaning. If you want to use an Icon without a label, test with users to ensure
it's clear what the Icon represents.

In cases where a label may not be feasible space-wise, use a Tooltip to provide
contextual support.

```tsx
import React from "react";
import { Icon } from "@jobber/components/Icon";
import { Tooltip } from "@jobber/components/Tooltip";

export function IconTooltipExample() {
  return (
    <div
      style={{
        display: "flex",
        alignItems: "center",
        gap: "var(--space-large)",
      }}
    >
      <Tooltip message="Search">
        <Icon name="search" />
      </Tooltip>
      <Tooltip message="Support">
        <Icon name="help" />
      </Tooltip>
      <Tooltip message="Settings">
        <Icon name="cog" />
      </Tooltip>
    </div>
  );
}
```

### Status

Icons are commonly paired with status messages to help the user quickly
understand the state of the application.

```tsx
import React from "react";
import { Icon } from "@jobber/components/Icon";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function IconStatusExample() {
  return (
    <Content spacing="larger">
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
        }}
      >
        <Icon name="alert" color="critical" />
        <Content spacing="smallest">
          <Text variation="error">Something has gone wrong</Text>
        </Content>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
        }}
      >
        <Icon name="warning" color="warning" />
        <Content spacing="smallest">
          <Text variation="warn">Something could go wrong</Text>
        </Content>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
        }}
      >
        <Icon name="info" color="informative" />
        <Content spacing="smallest">
          <Text variation="info">Something is happening</Text>
        </Content>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
        }}
      >
        <Icon name="checkmark" />
        <Content spacing="smallest">
          <Text variation="success">Something succeeded</Text>
        </Content>
      </div>
    </Content>
  );
}
```

### Sizes

```tsx
import React from "react";
import { Icon } from "@jobber/components/Icon";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function IconSizesExample() {
  return (
    <Content spacing="larger">
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-large)",
        }}
      >
        <Icon name="search" size="small" />
        <Content spacing="smallest">
          <Text>Small</Text>
          <Text size="small" variation="subdued">
            When space is severely constrained
          </Text>
        </Content>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-base)",
        }}
      >
        <Icon name="search" />
        <Content spacing="smallest">
          <Text>Base</Text>
          <Text size="small" variation="subdued">
            For most icon usage
          </Text>
        </Content>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
        }}
      >
        <Icon name="search" size="large" />
        <Content spacing="smallest">
          <Text>Large</Text>
          <Text size="small" variation="subdued">
            When the icon is prominently featured in the interface
          </Text>
        </Content>
      </div>
    </Content>
  );
}
```

## Related components

* [Button](../Button/Button.md)
* [IconButton](../components/IconButton) (mobile-only)
* [Banner](../Banner/Banner.md)

## Accessibility

* Icons are a visual supplement, so they should not be used as the only means of
  conveying information
  * Ensure icons are paired with a label if they are used as a standalone
    element
  * When used in an icon-only Button, provide an aria-label and use a Tooltip

## Available icons

### Arrows

| Icon | `Name`             |
| :--- | :----------------- |
|      | `arrowDown`        |
|      | `arrowLeft`        |
|      | `arrowRight`       |
|      | `arrowUp`          |
|      | `longArrowDown`    |
|      | `longArrowLeft`    |
|      | `longArrowRight`   |
|      | `longArrowUp`      |
|      | `longArrowUpRight` |

### Calendar & scheduling

| Icon | `Name`                  |
| :--- | :---------------------- |
|      | `afterDate`             |
|      | `availability`          |
|      | `beforeDate`            |
|      | `calendar`              |
|      | `calendarCheck`         |
|      | `clearFilters`          |
|      | `event`                 |
|      | `onlineBooking`         |
|      | `orientationHorizontal` |
|      | `orientationVertical`   |
|      | `schedule`              |
|      | `task`                  |
|      | `timeline`              |
|      | `today`                 |
|      | `userConfirmed`         |
|      | `recurring`             |
|      | `sliderStart`           |
|      | `sliderCenter`          |

### Files

| Icon | `Name`      |
| :--- | :---------- |
|      | `addNote`   |
|      | `archive`   |
|      | `excel`     |
|      | `file`      |
|      | `note`      |
|      | `pdf`       |
|      | `video`     |
|      | `videoFile` |
|      | `word`      |
|      | `upload`    |
|      | `image`     |
|      | `paperclip` |

### Forms

| Icon | `Name`         |
| :--- | :------------- |
|      | `checkbox`     |
|      | `checklist`    |
|      | `edit`         |
|      | `editDisabled` |
|      | `radioButton`  |
|      | `star`         |
|      | `starHalf`     |
|      | `starFill`     |
|      | `text`         |
|      | `textBox`      |
|      | `textField`    |
|      | `toggle`       |
|      | `dropdown`     |
|      | `trash`        |

### Status and support

| Icon | `Name`    |
| :--- | :-------- |
|      | `alert`   |
|      | `warning` |
|      | `info`    |
|      | `help`    |
|      | `knot`    |

### Map

| Icon | `Name`       |
| :--- | :----------- |
|      | `address`    |
|      | `moveMarker` |
|      | `property`   |
|      | `directions` |
|      | `map`        |

### Messaging

| Icon | `Name`            |
| :--- | :---------------- |
|      | `chat`            |
|      | `compose`         |
|      | `conversation`    |
|      | `email`           |
|      | `emailInbound`    |
|      | `emailOutbound`   |
|      | `markSent`        |
|      | `marketing`       |
|      | `reminder`        |
|      | `sendMessage`     |
|      | `sms`             |
|      | `sms2`            |
|      | `smsInbound`      |
|      | `smsOutbound`     |
|      | `smsProgress`     |
|      | `webchat`         |
|      | `webchatProgress` |

### User

| Icon | `Name`                |
| :--- | :-------------------- |
|      | `clients`             |
|      | `person`              |
|      | `company`             |
|      | `franchiseIndividual` |
|      | `franchiseGroup`      |
|      | `user`                |
|      | `userSwitch`          |
|      | `userUnassigned`      |
|      | `vcard`               |

### Social media

| Icon | `Name`       |
| :--- | :----------- |
|      | `angieslist` |
|      | `facebook`   |
|      | `googlePlay` |
|      | `google`     |
|      | `instagram`  |
|      | `linkedIn`   |
|      | `twitter`    |
|      | `yelp`       |
|      | `youtube`    |
|      | `embed`      |

### Transaction

| Icon | `Name`               |
| :--- | :------------------- |
|      | `bank`               |
|      | `payment`            |
|      | `percent`            |
|      | `wallet`             |
|      | `money`              |
|      | `transfer`           |
|      | `jobberCardReader`   |
|      | `contactlessPayment` |
|      | `cheque`             |
|      | `cash`               |

### Work

| Icon | `Name`         |
| :--- | :------------- |
|      | `break`        |
|      | `chemical`     |
|      | `clockIn`      |
|      | `clockOut`     |
|      | `expense`      |
|      | `office`       |
|      | `supplies`     |
|      | `timer`        |
|      | `work`         |
|      | `runningTimer` |

### Request

| Icon | `Name`    |
| :--- | :-------- |
|      | `request` |

### Quote

| Icon | `Name`  |
| :--- | :------ |
|      | `quote` |

### Job

| Icon | `Name`       |
| :--- | :----------- |
|      | `job`        |
|      | `jobOnHold`  |
|      | `moveVisits` |
|      | `visit`      |

### Invoice

| Icon | `Name`         |
| :--- | :------------- |
|      | `badInvoice`   |
|      | `invoice`      |
|      | `invoiceLater` |
|      | `invoiceSlash` |
|      | `paidInvoice`  |
|      | `sendInvoice`  |

### Fleet management

| Icon | `Name`    |
| :--- | :-------- |
|      | `truck`   |
|      | `speed`   |
|      | `wheel`   |
|      | `battery` |
|      | `fuel`    |
|      | `engine`  |

### System actions

| Icon | `Name`           |
| :--- | :--------------- |
|      | `add`            |
|      | `addTag`         |
|      | `automate`       |
|      | `batch`          |
|      | `condition`      |
|      | `copy`           |
|      | `customize`      |
|      | `download`       |
|      | `drag`           |
|      | `dragHorizontal` |
|      | `embed`          |
|      | `export`         |
|      | `filter`         |
|      | `future`         |
|      | `history`        |
|      | `import`         |
|      | `merge`          |
|      | `redo`           |
|      | `search`         |
|      | `sort`           |
|      | `sync`           |
|      | `syncAlert`      |
|      | `tag`            |
|      | `updateStatus`   |

### Other

| Icon | `Name`              |
| :--- | :------------------ |
|      | `apps`              |
|      | `at`                |
|      | `camera`            |
|      | `checkmark`         |
|      | `checkmarkCircle`   |
|      | `circle`            |
|      | `cog`               |
|      | `dashboard`         |
|      | `desktop`           |
|      | `website`           |
|      | `eye`               |
|      | `eyeCrossed`        |
|      | `flash`             |
|      | `flashAuto`         |
|      | `flashOff`          |
|      | `gift`              |
|      | `grid`              |
|      | `happyFace`         |
|      | `headset`           |
|      | `home`              |
|      | `link`              |
|      | `loadingCheck`      |
|      | `lock`              |
|      | `logout`            |
|      | `measurement`       |
|      | `menu`              |
|      | `microphone`        |
|      | `microphoneMuted`   |
|      | `mobile`            |
|      | `more`              |
|      | `number`            |
|      | `numpad`            |
|      | `offline`           |
|      | `phone`             |
|      | `phoneCall`         |
|      | `phoneDisconnected` |
|      | `phoneEnd`          |
|      | `phoneIncoming`     |
|      | `phoneOutgoing`     |
|      | `pinned`            |
|      | `presentation`      |
|      | `priceTag`          |
|      | `quickbooks`        |
|      | `reports`           |
|      | `shape`             |
|      | `sidebar`           |
|      | `signature`         |
|      | `sneaker`           |
|      | `soundwave`         |
|      | `sparkles`          |
|      | `speaker`           |
|      | `sprout`            |
|      | `starburst`         |
|      | `sun`               |
|      | `tableColumns`      |
|      | `thumbsDown`        |
|      | `thumbsUp`          |
|      | `unPinned`          |
|      | `xero`              |

### Legacy

| Icon | `Name`   |
| :--- | :------- |
|      | `apple`  |
|      | `cross`  |
|      | `list`   |
|      | `minus`  |
|      | `minus2` |
|      | `plus`   |
|      | `plus2`  |


## Validating icon names at runtime

When icon names arrive as runtime data (API responses, configuration, user
input), validate them before rendering with the exports from
`@jobber/components` (also available from `@jobber/design`):

* `iconNames`: a readonly array of every valid icon name
* `isIconName(value)`: a type guard that narrows a value to `IconNames`

```tsx
import { Icon, isIconName } from "@jobber/components";

function StatusIcon({ iconName }: { readonly iconName: string }) {
  if (!isIconName(iconName)) return null;

  return <Icon name={iconName} />;
}
```

## Component customization

### UNSAFE\_ props (advanced usage)

General information for using `UNSAFE_` props can be found
[here](../customizing-components/customizing-components.md).

**Note**: Use of `UNSAFE_` props is **at your own risk** and should be
considered a **last resort**. Future Icon updates may lead to unintended
breakages.

Icon has two elements that can be targeted with classes or styles:

* `svg`: The container element of the icon
* `path`: The actual shape and color of the icon

#### UNSAFE\_className (web)

Use `UNSAFE_className` to apply custom classes to the Icon. This can be useful
for applying styles via CSS Modules.

```tsx
// Icon.tsx
UNSAFE_className={{
  svg: styles.iconContainer,
  path: styles.iconPath,
}}

// Icon.module.css
.iconContainer {
  padding: var(--space-small);
  border-radius: var(--radius-large);
  background-color: var(--color-purple);
}

.iconPath {
  fill: var(--color-orange);
}
```

Using `UNSAFE_className` for modifying the icon's dimensions (width, height) may
not work as expected. For size modifications, use `UNSAFE_style.svg` instead.

#### UNSAFE\_style (web)

The `UNSAFE_style` prop provides granular control over the icon's appearance
through inline styles, allowing you to modify the dimensions and colors
independently.

```tsx
<Icon
  name="arrowDown"
  UNSAFE_style={{
    svg: {
      width: "48px",
      height: "48px",
      backgroundColor: "var(--color-purple)",
      padding: "var(--space-small)",
      borderRadius: "var(--radius-large)",
    },
    path: {
      fill: "orange",
    },
  }}
/>
```

##### Key styling notes:

* To modify icon dimensions, use `UNSAFE_style.svg` with both `width` and
  `height`
* To override an icon's color, use `fill` in the `path` styles, instead of
  `color`
* Container styling (background, padding, border) should be applied to the `svg`
  styles

Remember that the standard `size` prop is the recommended way to control icon
dimensions. Only use `UNSAFE_style.svg` for custom sizing when absolutely
necessary.


## Props

### Web

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `name` | `IconNames` | Yes | — | The icon to show. |
| `color` | `"disabled" | "icon" | "task" | "text" | "warning" | "success" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
| `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
| `size` | `"base" | "large" | "small"` | No | `base` | Changes the size to small or large. |
| `testID` | `string` | No | — | Used to locate this view in end-to-end tests |
| `UNSAFE_className` | `{ svg?: string; path?: string; }` | No | — | **Use at your own risk:** Custom classnames for specific elements. This should only be used as a **last resort**. Usi... |
| `UNSAFE_style` | `{ svg?: CSSProperties; path?: CSSProperties; }` | No | — | **Use at your own risk:** Custom style for specific elements. This should only be used as a **last resort**. Using th... |
