---
title: "Chip"
description: "Small labels and filter chips with ChipTitle and ChipIcon."
url: https://docs.systhema.app/next/components/chip
version: unreleased (main)
docs_index: https://docs.systhema.app/next/llms.txt
---

`Chip` renders a small label: a category, a tag, a status. It is a `<span>` by default; as a link it gets a hover state, which makes it a tag or filter you can click. `ChipTitle` and `ChipIcon` lay out the text and an optional icon.

```tsx preview title="Chip"
import { Chip, ChipTitle } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Chip>
        <ChipTitle>Design systems</ChipTitle>
      </Chip>
      <Chip>
        <ChipTitle>Next.js</ChipTitle>
      </Chip>
      <Chip>
        <ChipTitle>Payload</ChipTitle>
      </Chip>
    </div>
  )
}
```

## Import

```tsx
import { Chip, ChipIcon, ChipTitle } from '@systhemaui/next'
```

In a React app without Next.js, import them from `@systhemaui/react`. There `Chip.a` renders a plain anchor.

## Variants and tags

There is one chip style, set by the `chip` tokens. The tag decides the behavior:

| Component   | Renders                                                                         |
| ----------- | ------------------------------------------------------------------------------- |
| `Chip`      | a `<span>` by default, or the element in `as`                                   |
| `Chip.span` | a `<span>`                                                                      |
| `Chip.div`  | a `<div>`                                                                       |
| `Chip.a`    | a link through the [`LinkHelper`](https://docs.systhema.app/next/components/utilities.md#linkhelper), with hover colors |

```tsx preview title="Static and linked"
import { Chip, ChipTitle } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Chip.span>
        <ChipTitle>Chip.span</ChipTitle>
      </Chip.span>
      <Chip.div>
        <ChipTitle>Chip.div</ChipTitle>
      </Chip.div>
      <Chip.a href="#variants-and-tags">
        <ChipTitle>Chip.a (hover me)</ChipTitle>
      </Chip.a>
    </div>
  )
}
```

The hover colors (`--color-chip-hover-*`) apply only when the chip is an `<a>`, so a static label never looks clickable.

## Examples

### With an icon

`ChipIcon` takes any content and sizes it with `--chip-icon-size`. `ChipIcon.svg` makes the SVG itself the icon. Unlike `ButtonIcon`, an empty `ChipIcon` draws nothing.

```tsx preview title="Chip icons"
import { Chip, ChipIcon, ChipTitle } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Chip>
        <ChipIcon.svg viewBox="0 -960 960 960" fill="currentColor">
          <path d="m233-120 65-281L80-590l288-25 112-265 112 265 288 25-218 189 65 281-247-149-247 149Z" />
        </ChipIcon.svg>
        <ChipTitle>Featured</ChipTitle>
      </Chip>
      <Chip>
        <ChipIcon>🌿</ChipIcon>
        <ChipTitle>Sustainability</ChipTitle>
      </Chip>
      <Chip>
        <ChipTitle>Verified</ChipTitle>
        <ChipIcon.svg viewBox="0 -960 960 960" fill="currentColor">
          <path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z" />
        </ChipIcon.svg>
      </Chip>
    </div>
  )
}
```

### Tag links

Linked chips make a tag list for a post or an archive. Group them in a list so screen readers announce how many there are.

```tsx preview title="Tag list"
import { Chip, ChipTitle } from '@systhemaui/next'

const tags = ['Tokens', 'Accessibility', 'Performance', 'Figma']

export default function Demo() {
  return (
    <ul className="flex flex-wrap gap-2" aria-label="Tags">
      {tags.map((tag) => (
        <li key={tag}>
          <Chip.a href={`#tag-${tag.toLowerCase()}`}>
            <ChipTitle>{tag}</ChipTitle>
          </Chip.a>
        </li>
      ))}
    </ul>
  )
}
```

## Props

### `Chip`

`Chip`, `Chip.span` and `Chip.div` take the props of the element they render. `ChipTitle` renders a `<span>`.

<!-- generated:props @systhemaui/react ChipProps -->

| Prop                         | Type          | Default  | Description |
| ---------------------------- | ------------- | -------- | ----------- |
| `as`                         | `ElementType` | `'span'` |             |
| `className`                  | `string`      | -        |             |
| `children`                   | `ReactNode`   | -        |             |
| …and all `<span>` attributes |               |          |             |

<!-- /generated -->

### `ChipIcon`

`ChipIcon` renders a `<span>` by default and always sets `aria-hidden="true"` (pass `aria-hidden={false}` to override).

<!-- generated:props @systhemaui/react ChipIconProps -->

| Prop                         | Type          | Default  | Description |
| ---------------------------- | ------------- | -------- | ----------- |
| `as`                         | `ElementType` | `'span'` |             |
| `className`                  | `string`      | -        |             |
| …and all `<span>` attributes |               |          |             |

<!-- /generated -->

## HTML and CSS

Without React, add the `chip` class. Use an `<a>` for a chip with hover colors:

```html
<span class="chip"><span class="chip-title">Design systems</span></span>

<a class="chip" href="/tag/tokens">
  <span class="chip-icon" aria-hidden="true">🌿</span>
  <span class="chip-title">Tokens</span>
</a>
```

Padding, radius, border, shadow, font and colors all come from the `chip` tokens (`--chip-padding-x`, `--chip-border-radius`, `--color-chip-normal-background` and so on).

<!-- generated:utilities chip -->

| Class  | Styles                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chip` | `& { --tw-shadow-color: var(--color-chip-normal-shadow); --tw-shadow: var(--tw-shadow-color); vertical-align: bottom; position: relative; display: inline-flex; align-items: center; justify-content: center; border-style: solid; border-radius: var(--chip-border-radius); border-width: var(--chip-border-width); box-shadow: var(--chip-shadow-x) var(--chip-shadow-y) var(--chip-shadow-blur) var(--chip-shadow-spread) var(--tw-shadow-color, rgba(0, 0, 0, 0.25)); transition-property: c…`<br>+ 3 more rules |

<!-- /generated -->

## Next.js

`@systhemaui/next` has its own `Chip` whose `Chip.a` renders `next/link` through the [`LinkHelper`](https://docs.systhema.app/next/components/utilities.md#linkhelper): client-side navigation, prefetching and smooth same-page hashes. Its props are `NextLinkChipProps`, so `href` is required and `next/link` props such as `prefetch` are accepted. Passing `as="a"` to `Chip` also routes through the helper.

```tsx
import { Chip, ChipTitle } from '@systhemaui/next'

export function CategoryChip() {
  return (
    <Chip.a href="/blog/category/design" prefetch={false}>
      <ChipTitle>Design</ChipTitle>
    </Chip.a>
  )
}
```

The module is not marked `'use client'`, so `Chip.a`, `Chip.span` and `Chip.div` keep working when `Chip` is imported in a Server Component.

<!-- generated:props @systhemaui/next NextLinkChipProps -->

| Prop                                           | Type        | Default | Description |
| ---------------------------------------------- | ----------- | ------- | ----------- |
| `children`                                     | `ReactNode` | -       |             |
| `className`                                    | `string`    | -       |             |
| …and all `InternalLinkProps` props from `next` |             |         |             |
| …and all `<a>` attributes                      |             |         |             |

<!-- /generated -->

## Accessibility

- `ChipIcon` renders with `aria-hidden="true"`, so only the title is announced. A chip whose only content is an icon needs an `aria-label`.
- A chip that filters content should say what it does: a link to a filtered URL, or a `<button>` (`<Chip as="button" aria-pressed={active}>`) when it toggles a filter in place.

## Related

- [Chip block](https://docs.systhema.app/next/payload/blocks/chip.md)
- [Button](https://docs.systhema.app/next/components/button.md)
- [ArchiveSearchFilter](https://docs.systhema.app/next/components/archive-search-filter.md) (filter chips)
