# Chip

Chip is a flexible component that can be used for

* inline single- or multi-selection of items
* triggering filtering and selection components like
  [FilterPicker](../FilterPicker/FilterPicker.md)
* presenting grouped items that can be added or removed

```tsx
import type { ComponentProps } from "react";
import React from "react";
import { Chip } from "@jobber/components/Chip";
import { Avatar } from "@jobber/components/Avatar";
import { Icon } from "@jobber/components/Icon";

export function ChipWithAvatarExample(
  props: Partial<ComponentProps<typeof Chip>>,
) {
  return (
    <Chip label="Gavin Messina" {...props}>
      <Chip.Prefix>
        <Avatar
          size="small"
          imageUrl="https://images.unsplash.com/photo-1669475535925-a011d7c31d45?q=80&w=1886&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
        />
      </Chip.Prefix>
      <Chip.Suffix>
        <Icon name="cross" size="small" />
      </Chip.Suffix>
    </Chip>
  );
}
```

## Design & usage guidelines

See the
[Comparison story](/storybook/web/?path=/story/components-selections-chip-comparisons--all)
for a full overview of potential Chip variants.

### Variations

The base variation of Chip should be used in most cases. When a lighter-weight
approach is desired, use the subtle variation.

```tsx
import React from "react";
import { Chip } from "@jobber/components/Chip";
import { Flex } from "@jobber/components/Flex";

export function ChipVariationsExample() {
  return (
    <Flex template={["shrink", "shrink"]} direction="row" gap="small">
      <Chip label="Base" />
      <Chip label="Subtle" variation="subtle" />
    </Flex>
  );
}
```

### Selection

Chip allows users to make selections in scenarios where space is at a premium.
It has three high-level usages: single-select, multi-select, and add/dismiss
selection.

#### Single-select

If you need the user to make a selection of a single item from among several
items, and those items all have short (1–2 word) labels, single-select Chips
will allow the user to choose one of those items.

This preserves vertical space while allowing the user to clearly identify which
item they have selected.

Unlike [Radio](../RadioGroup/RadioGroup.md), the selected single-select Chip can be
de-selected by the user, leaving all selections blank.

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

export function ChipSingleSelectExample() {
  return (
    <Flex
      template={["shrink", "shrink", "shrink", "shrink"]}
      direction="row"
      gap="small"
    >
      <Chip label="Option 1" variation="subtle" />
      <Chip label="Option 2">
        <Chip.Suffix>
          <Icon name="checkmark" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 3" variation="subtle" />
      <Chip label="Option 4" variation="subtle" />
    </Flex>
  );
}
```

#### Multi-select

If you need the user to make a selection of one *or more* items from amongst
several items, and those items all have short (1–2 word) labels, a multi-select
Chips will allow the user to choose as many items from the group as they wish.

This preserves vertical space while allowing the user to clearly identify which
items they have selected. To signify to the user that multiple selections are
possible, a checkmark icon is present to reinforce the conceptual similarity to
a [Checkbox](../Checkbox/Checkbox.md).

Similar to Checkbox, a selected multi-select Chip can be de-selected by the
user, leaving all selections blank.

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

export function ChipMultiSelectExample() {
  return (
    <Flex
      template={["shrink", "shrink", "shrink", "shrink"]}
      direction="row"
      gap="small"
    >
      <Chip label="Option 1">
        <Chip.Suffix>
          <Icon name="checkmark" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 2">
        <Chip.Suffix>
          <Icon name="checkmark" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 3" variation="subtle" />
      <Chip label="Option 4">
        <Chip.Suffix>
          <Icon name="checkmark" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
    </Flex>
  );
}
```

#### Add/dismiss selection

When the user will be selecting one or more items by inputting their own Chip
options, use a dismissible Chip. Think of a case like team assignment, where the
user can add multiple users represented as Chips, and click on the dismiss
suffix of the Chip to remove a user.

The dismissible Chip allows them to remove previous selections from the Chips.
Use this option when the full list of possible selections is too great to
reasonably display in one group of Chip. For example, "all of my phone contacts"
would be far too many Chip options to present in one group, and would be
overwhelming for the user to interpret.

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

export function ChipAddDismissExample() {
  return (
    <Flex
      template={["shrink", "shrink", "shrink", "shrink", "shrink"]}
      direction="row"
      gap="small"
    >
      <Chip label="Add" variation="subtle">
        <Chip.Suffix>
          <Icon name="add" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 1">
        <Chip.Suffix>
          <Icon name="cross" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 2">
        <Chip.Suffix>
          <Icon name="cross" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 3">
        <Chip.Suffix>
          <Icon name="cross" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
      <Chip label="Option 4">
        <Chip.Suffix>
          <Icon name="cross" size="small" color="interactiveSubtle" />
        </Chip.Suffix>
      </Chip>
    </Flex>
  );
}
```

### Invalid

If something goes awry with a selection or you otherwise need to convey to the
user that something's gone wrong in relation to the Chip, you can use the
invalid state.

```tsx
import type { ComponentProps } from "react";
import React from "react";
import { Chip } from "@jobber/components/Chip";
import { Icon } from "@jobber/components/Icon";

export function ChipInvalidExample(
  props: Partial<ComponentProps<typeof Chip>>,
) {
  return (
    <Chip label="Select team" invalid {...props}>
      <Chip.Prefix>
        <Icon name="alert" size="small" />
      </Chip.Prefix>
    </Chip>
  );
}
```

## Related components

* [Chips](../Chips/Chips.md) is a convenience wrapper that offers the
  single-select, multi-select, and add/dismiss functionality "out of the box"
* [FilterPicker](../FilterPicker/FilterPicker.md) is most commonly triggered by a Chip,
  but is a separate component
* [LegacySelect](../LegacySelect/LegacySelect.md) is a simpler single-select "dropdown"
  that presents as a form element and should be preferred in forms
* [RadioGroup](../RadioGroup/RadioGroup.md) should be used to allow the user to
  select "one-of-many" items (single-select) and the labels for the items are
  longer than 1 or 2 words.
* [Checkbox](../Checkbox/Checkbox.md) should be used to allow the user to select
  "one-or-more-of-many" items (multi-select) and the labels for the items are
  longer than 1 or 2 words.
* [InlineLabel](../InlineLabel/InlineLabel.md) should be used when you just need a
  rounded-rectangular element that displays metadata about an element

## Content guidelines

Chip headings and labels for single- or multi-select should be succinct -
ideally 1–2 words. If any of the options in the group may have longer labels,
consider Checkbox or Radio as necessary for your selection type.

In cases where a Chip displays name of its selections, such as when used to
trigger a FilterPicker or a date range selector, use the heading to identify the
"category" and the label to identify the selected items.

## Accessibility

Chips should convey to the user whether it is a "checkbox" or "radio" element
based on single or multi-select. The Chips in this group have the appropriate
roles and keyboard operation to allow the user to interact as though they are
dealing with a checkbox or radio button.

If Chips is set for add/dismiss selections, the dismiss button should notify the
user that they will "dismiss {label name}" upon press.

## Responsiveness

The Chips themselves will take up as much space as their container allows, and
the Chips will flow left to right. Chips may re-flow into new rows, or scroll
out of view in a single row, depending on your use case.

Chip can truncate if its' container is limited in space, but does not inherently
cap its own width and will default to "hug" its contents.


## Configuration

### Chip.Prefix

When `Chip.Prefix` is provided with an Icon or Avatar as its immediate child,
default markup and styles are automatically applied. If these styles and markup
are not desired, or if you would like to provide your own child, you should
provide your own wrapper element and layout.

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

export function ChipPrefixConfigExample() {
  return (
    <Box direction="column" gap="base">
      <Box direction="row" alignItems="center" gap="base">
        <Chip label="Select team">
          <Chip.Prefix>
            <Icon name="person" size="small" />
          </Chip.Prefix>
        </Chip>
        <Text>Default styling</Text>
      </Box>
      <Box direction="row" alignItems="center" gap="large">
        <Chip label="Select team">
          <Chip.Prefix>
            <div style={{ display: "flex", marginRight: 20 }}>
              <Icon name="person" size="small" />
            </div>
          </Chip.Prefix>
        </Chip>
        <Text>Custom wrapper around Icon to add larger margin</Text>
      </Box>
      <Box direction="row" alignItems="center" gap="base">
        <Chip label="Select team">
          <Chip.Prefix>
            <div style={{ display: "flex", marginRight: 15 }}>
              <StatusLabel status="success" label="Ready" />
            </div>
          </Chip.Prefix>
        </Chip>
        <Text>Custom wrapper around child</Text>
      </Box>
    </Box>
  );
}
```

## Component customization

### Base Chip Color Overrides

If you wish to modify the colors of the Base variant, you may do so with CSS
custom properties (variables).

For the resting background color: `--public-chip-base-bg-color`

For the hover/focused background color: `--public-chip-base-hover-bg-color`

For the text content and miscellaneous content such as the line separator
between the `label` and `heading`: `--public-chip-base-content-color`

## Developer notes

Chip is in the process of being applied to the more opinionated Chips
convenience wrapper, but by design does not carry the same level of "out of the
box" functionality as it is a more "atomic" element that can be used outside of
those more complex selection flows.


## Props

### Web

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `label` | `string` | Yes | — | The content of the chip. Will be displayed on the right if you include a heading. |
| `ariaLabel` | `string` | No | — | Accessible label, which can be different from the primary label. |
| `data-testid` | `string` | No | — |  |
| `disabled` | `boolean` | No | — | Disables both mouse and keyboard functionality, and updates the visual style of the Chip to appear disabled. |
| `heading` | `string` | No | — | Adds more prominent text to act as a heading. Will be displayed on the left with a | separator. |
| `invalid` | `boolean` | No | — | Changes Chip styling to inform the user of an issue. |
| `onClick` | `((ev: MouseEvent<HTMLButtonElement | HTMLDivElement, MouseEvent>) => void) & MouseEventHandler<ChipElement>` | No | — | Chip click callback using a standard event-first signature. |
| `onClickValue` | `(value: string | number, ev: MouseEvent<HTMLButtonElement | HTMLDivElement, MouseEvent>) => void` | No | — | Value-first click callback retained as an upgrade path for existing consumers. @deprecated Prefer `onClick` with a cl... |
| `onKeyDown` | `((ev: KeyboardEvent<HTMLButtonElement | HTMLDivElement>) => void) & KeyboardEventHandler<ChipElement>` | No | — | Callback. Called when you keydown on Chip. Ships the event, so you can get the key pushed. |
| `ref` | `Ref<HTMLButtonElement | HTMLDivElement>` | No | — | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (... |
| `role` | `string` | No | `button` | The accessible role the Chip is fulfilling. Defaults to 'button' |
| `tabIndex` | `number` | No | `0` | Used for accessibility purpopses, specifically using the tab key as navigation. |
| `testID` | `string` | No | — | The testing id for the chip if necessary. |
| `value` | `number | string` | No | — | Will be passed to onClick, when the user clicks on this Chip. |
| `variation` | `ChipVariations` | No | `base` | Button style variation. Does not affect functionality. |
