Skip to main contentSkip to docs navigation

Compact, interactive element for tags, filters, and selections — rendered as a span, div, button, or link.

Examples

<Chip> renders a <span> by default, styled with the color prop for one of Chassis's context colors. It's a compact, composable building block for tags, filters, and selections — combine it with Icon, Avatar, or CloseButton as plain children.

Chip
JSX
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  return <Chip color="primary">Chip</Chip>
}

Colors

Set color to one of Chassis's context colors.

defaultalternateprimarysecondaryneutralsuccessdangerwarninginfoblackwhite
JSX
import { Chip } from '@chassis-ui/react'
import { COLORS } from '../../utils'

export const Example = () => {
  return (
    <>
      {COLORS.map((color) => (
        <Chip key={color} color={color}>
          {color}
        </Chip>
      ))}
    </>
  )
}

Color alone doesn't convey meaning to assistive technology. Pair a context color with visible text describing the chip's purpose.

Style variants

Outline

Set variant="outline" for a transparent background with a colored border and text — a lower-emphasis alternative to a solid chip in the same color.

defaultalternateprimarysecondaryneutralsuccessdangerwarninginfoblackwhite
JSX
import { Chip } from '@chassis-ui/react'
import { COLORS } from '../../utils'

export const Example = () => {
  return (
    <>
      {COLORS.map((color) => (
        <Chip key={color} color={color} variant="outline">
          {color}
        </Chip>
      ))}
    </>
  )
}

Smooth

Set variant="smooth" for a subdued, tinted background in the chip's color.

defaultalternateprimarysecondaryneutralsuccessdangerwarninginfoblackwhite
JSX
import { Chip } from '@chassis-ui/react'
import { COLORS } from '../../utils'

export const Example = () => {
  return (
    <>
      {COLORS.map((color) => (
        <Chip key={color} color={color} variant="smooth">
          {color}
        </Chip>
      ))}
    </>
  )
}

Icons

Nest an Icon at the start or end of a chip's content to add visual meaning. Wrap the text in its own <span> so chassis-css's :first-child/:last-child spacing applies correctly.

DefaultPrimary
JSX
import { Chip, Icon } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Chip color="default">
        <Icon name="info-circle-solid" aria-hidden="true" />
        <span>Default</span>
      </Chip>
      <Chip color="primary">
        <span>Primary</span>
        <Icon name="info-circle-solid" aria-hidden="true" />
      </Chip>
    </>
  )
}

Avatars

Nest an Avatar to represent a person or entity — pair it with CloseButton for a removable "selected person" chip. Pass component="span" to Avatar so it renders as a decorative image rather than an interactive button.

Profile pictureJane Doe
JSX
import { Avatar, Chip, CloseButton } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Chip color="default">
      <Avatar src="https://i.pravatar.cc/256" component="span" />
      Jane Doe
      <CloseButton label="Remove Jane Doe" />
    </Chip>
  )
}

Dismissible chips

Nest a CloseButton to add a removal action — Chip doesn't manage its own list state, so pair it with an onClick handler that removes the value from whatever collection is being rendered from.

ReactTypeScriptCSS
JSX
import { useState } from 'react'
import { Chip, CloseButton } from '@chassis-ui/react'

export const Example = () => {
  const [tags, setTags] = useState(['React', 'TypeScript', 'CSS'])

  return (
    <>
      {tags.map((tag) => (
        <Chip key={tag} color="primary">
          {tag}
          <CloseButton
            label={`Remove ${tag}`}
            onClick={() => setTags((current) => current.filter((value) => value !== tag))}
          />
        </Chip>
      ))}
    </>
  )
}

Sizes

Set size to "sm" or "lg" to adjust a chip's padding and font size; the default renders at md size.

SmallMediumLarge
JSX
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Chip color="primary" size="sm">
        Small
      </Chip>
      <Chip color="primary">Medium</Chip>
      <Chip color="primary" size="lg">
        Large
      </Chip>
    </>
  )
}

Pressed state

Set pressed to mark a toggle-style chip as active — e.g. a filter pill that stays highlighted while selected. It applies the .active class and sets aria-pressed, so assistive technology announces the toggle state. Chip doesn't toggle itself; flip pressed from an onClick handler. A chip that isn't a button gets the class alone: a static chip, and a chip that is a link (href, or an <a> as component or the asChild element), which has no pressed state to announce. Give a link chip role="button" if it acts as a toggle, and it takes aria-pressed too.

JSX
import { useState } from 'react'
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  const [pressed, setPressed] = useState(false)

  return (
    <Chip component="button" color="primary" pressed={pressed} onClick={() => setPressed(!pressed)}>
      In stock
    </Chip>
  )
}

Root element

Set component to render <Chip> as a different element — "div" for a non-interactive block, "button" for a toggle control, or any custom component. href implies component="a" automatically.

Span
Div
Link
JSX
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Chip color="primary">Span</Chip>
      <Chip component="div" color="primary">
        Div
      </Chip>
      <Chip component="button" color="primary">
        Button
      </Chip>
      <Chip href="#" role="button" color="primary">
        Link
      </Chip>
    </>
  )
}

A chip rendered as <a> for something other than navigation — a toggle filter, for example — needs an explicit role="button"; Chassis doesn't add it automatically, since not every component="a" usage is a non-navigation action.

Disabled state

Set disabled to make a chip non-interactive. A <button> chip uses the real disabled attribute, which blocks keyboard and pointer interaction on its own.

JSX
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Chip component="button" color="primary" disabled>
      Button
    </Chip>
  )
}

<span>, <div>, and <a> have no disabled attribute, so a disabled non-button chip gets the .disabled class instead, which sets pointer-events: none. A disabled <a> chip additionally gets aria-disabled="true" and tabindex="-1", and blocks its own click handler and navigation.

JSX
import { Chip } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Chip href="#" role="button" color="secondary" disabled>
      Link
    </Chip>
  )
}

Scope

No automatic role="button" on non-navigation links. Rendering <Chip> with component="a" for a toggle action rather than navigation (see Root element) still needs an explicit role="button" — Chassis can't distinguish the two cases from href alone.

No built-in list management. Unlike ChipInput, Chip renders a single chip with no concept of a value collection — creation, removal, and keyboard navigation across a set of chips are the consumer's responsibility (or use ChipInput, which composes Chip internally for exactly that use case).

API

Chip

PropTypeDefault
asChild?boolean—
Render the single child element in place of this component's own element, with this component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log in</Link></Button>. The alternative to component for React Server Components — an element can be passed from the server to this package's client components, a component reference (component={Link}) can't.
className?string—
A string of all className you want applied to the component.
color?ContextColor—
Sets the color of the component to one of Chassis context colors.
component?ElementType—
Component used for the root node. Either a string to use a HTML element or a component. Defaults to span, or a when href is set.
disabled?boolean—
Toggle the disabled state for the component. Applied as the native disabled attribute when component is button, or the .disabled class for every other element (a bare <span>/ <a> has no real disabled attribute).
href?string—
Renders the chip as a link to this URL. Defaults component to a.
onClick?MouseEventHandler<HTMLElement>—
Fires on click. Typed for every element component can actually render, rather than narrowed to whichever element C happens to be.
pressed?boolean—
Marks the chip as pressed for toggle-style usage (e.g. a filter chip). Applies the .active class and sets aria-pressed so assistive technology announces the toggle state. A chip with no onClick or component="button" is not a button and gets the class alone: a static chip, and a link (href, or an <a> as component or the asChild element), which has no pressed state to announce unless you give it role="button".
ref?any—
size?"sm" | "lg"—
Size the component sm or lg.
type?"button" | "submit" | "reset"—
Specifies the type of button. Only applies when component is button. Different browsers may use different default types for the <button> element, so always specify it explicitly.
variant?ContextStyle—
Set the chip style variant. solid/basic render the default look with no extra class.