Docs
Systhema Design (opens in new tab)
Unreleased

Chip

Small labels and filter chips with ChipTitle and ChipIcon.

On this page

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.

Chip
Design systemsNext.jsPayload
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>
  )
}

ImportLink to this section

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 tagsLink to this section

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

ComponentRenders
Chipa <span> by default, or the element in as
Chip.spana <span>
Chip.diva <div>
Chip.aa link through the LinkHelper, with hover colors
Static and linked
Chip.span
Chip.div
Chip.a (hover me)
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.

ExamplesLink to this section

With an iconLink to this section

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.

Chip icons
FeaturedSustainabilityVerified
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>
  )
}

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.

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

PropsLink to this section

ChipLink to this section

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

PropTypeDefaultDescription
asElementType'span'
classNamestring-
childrenReactNode-
…and all <span> attributes

ChipIconLink to this section

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

PropTypeDefaultDescription
asElementType'span'
classNamestring-
…and all <span> attributes

HTML and CSSLink to this section

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

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

ClassStyles
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…+ 3 more rules

Next.jsLink to this section

@systhemaui/next has its own Chip whose Chip.a renders next/link through the 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.

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.

PropTypeDefaultDescription
childrenReactNode-
classNamestring-
…and all InternalLinkProps props from next
…and all <a> attributes

AccessibilityLink to this section

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