Skip to main content

Chip

Available from version 0.5.0

Chip generates a compact element that can represent an input, attribute, or action.

Basics

import { Chip } from 'tailwind-joy/components';

Chips comes with medium size, neutral color, and soft variant set by default.

This is a chip
import { Chip } from 'tailwind-joy/components';

export function ChipBasics() {
return (
<div>
<Chip>This is a chip</Chip>
</div>
);
}

Customization

Decorators

Use the startDecorator and/or endDecorator props to add supporting icons to the chip.

Today is sunny
Tomorrow is cloudy
import { MdCloud, MdLightMode } from 'react-icons/md';
import { Box, Chip } from 'tailwind-joy/components';
import { iconClass } from 'tailwind-joy/utils';

export function ChipDecorators() {
return (
<Box className="flex items-center gap-2">
<Chip startDecorator={<MdLightMode className={iconClass()} />}>
Today is sunny
</Chip>
<Chip startDecorator={<MdCloud className={iconClass()} />}>
Tomorrow is cloudy
</Chip>
</Box>
);
}

Delete button

To add a delete action inside a chip, use the complementary ChipDelete component.

The onDelete callback is fired on ChipDelete either when:

  • Backspace, Enter or Delete is pressed.
  • The ChipDelete is clicked.
Delete
Delete
Delete
import { Box, Chip, ChipDelete } from 'tailwind-joy/components';

export function ChipDeleteButton() {
return (
<Box className="flex items-center gap-2">
<Chip
size="sm"
variant="outlined"
color="danger"
endDecorator={<ChipDelete onDelete={() => alert('Delete')} />}
>
Delete
</Chip>
<Chip
color="danger"
endDecorator={<ChipDelete onDelete={() => alert('Delete')} />}
>
Delete
</Chip>
<Chip
size="lg"
variant="solid"
color="danger"
endDecorator={<ChipDelete onDelete={() => alert('Delete')} />}
>
Delete
</Chip>
</Box>
);
}

Clickable

To make chips clickable, pass a function to the onClick prop.

Octocat
Octocat
import { MdCheck } from 'react-icons/md';
import { Box, Chip } from 'tailwind-joy/components';
import { iconClass } from 'tailwind-joy/utils';

export function ChipClickable() {
return (
<Box className="flex items-center gap-2">
<Chip
size="lg"
variant="outlined"
startDecorator={
<div className="-ml-[9px] flex h-[22px] w-[22px] items-center justify-center overflow-hidden rounded-full">
<img
src="/img/avatar/octocat-avatar.png"
className="h-full w-full object-cover"
alt="Octocat"
/>
</div>
}
endDecorator={<MdCheck className={iconClass()} />}
onClick={() => alert('You clicked the Tailwind Joy Chip!')}
>
Octocat
</Chip>
</Box>
);
}

Clickable and deletable

Use both the onClick prop and the complementary ChipDelete component to make a chip support two actions.

Clear
import { MdDeleteForever } from 'react-icons/md';
import { Box, Chip, ChipDelete } from 'tailwind-joy/components';
import { iconClass } from 'tailwind-joy/utils';

export function ChipClickableAndDeletable() {
return (
<Box className="flex items-center gap-2">
<Chip
variant="outlined"
color="danger"
onClick={() => alert('You clicked the chip!')}
endDecorator={
<ChipDelete
variant="plain"
color="danger"
onClick={() => alert('You clicked the delete button!')}
>
<MdDeleteForever className={iconClass()} />
</ChipDelete>
}
>
Clear
</Chip>
</Box>
);
}

With radio

Common to filtering UIs, wrap the Radio component with the Chip to use them together. Use radios when you want to enable single selection.

Best Movie

import { useState } from 'react';
import { MdCheck } from 'react-icons/md';
import {
Box,
Chip,
Radio,
RadioGroup,
Typography,
} from 'tailwind-joy/components';
import { iconClass } from 'tailwind-joy/utils';
import { twMerge } from 'tailwind-merge';

export function ChipWithRadio() {
const [selected, setSelected] = useState('');

return (
<Box className="flex items-center gap-2">
<div>
<Typography level="title-lg" className="mb-4">
Best Movie
</Typography>
<RadioGroup
name="best-movie"
orientation="horizontal"
className="flex-wrap gap-2"
>
{[
'Star trek',
'Batman',
'Spider man',
'Eternals',
'Shang chi',
'Jungle cruise',
'No time to die',
'Thor',
'The hulk',
].map((name) => {
const checked = selected === name;

return (
<Chip
key={name}
variant="plain"
color={checked ? 'primary' : 'neutral'}
startDecorator={
checked && (
<MdCheck
className={twMerge(
iconClass(),
'pointer-events-none z-[1]',
)}
/>
)
}
>
<Radio
variant="outlined"
color={checked ? 'primary' : 'neutral'}
disableIcon
overlay
label={name}
value={name}
checked={checked}
onChange={(event) => {
if (event.target.checked) {
setSelected(name);
}
}}
/>
</Chip>
);
})}
</RadioGroup>
</div>
</Box>
);
}

With checkbox

Similar to the above, wrap the Checkbox component with the Chip to use them together. Use checkboxes when you want to enable multiple selection.

Favorite Movies

import { useState } from 'react';
import { MdCheck } from 'react-icons/md';
import { Box, Checkbox, Chip, Typography } from 'tailwind-joy/components';
import { iconClass } from 'tailwind-joy/utils';
import { twMerge } from 'tailwind-merge';

export function ChipWithCheckbox() {
const [selected, setSelected] = useState<string[]>([]);

return (
<Box className="flex items-center gap-2">
<div>
<Typography level="title-lg" className="mb-4">
Favorite Movies
</Typography>
<Box role="group" className="flex flex-wrap gap-2">
{[
'Star trek',
'Batman',
'Spider man',
'Eternals',
'Shang chi',
'Jungle cruise',
'No time to die',
'Thor',
'The hulk',
].map((name) => {
const checked = selected.includes(name);

return (
<Chip
key={name}
variant="plain"
color={checked ? 'primary' : 'neutral'}
startDecorator={
checked && (
<MdCheck
className={twMerge(
iconClass(),
'pointer-events-none z-[1]',
)}
/>
)
}
>
<Checkbox
variant="outlined"
color={checked ? 'primary' : 'neutral'}
disableIcon
overlay
label={name}
checked={checked}
onChange={(event) => {
setSelected((names) =>
!event.target.checked
? names.filter((n) => n !== name)
: [...names, name],
);
}}
/>
</Chip>
);
})}
</Box>
</div>
</Box>
);
}

Anatomy

The Chip component is composed of a single root <div> element that wraps around its contents:

<div class="tj-chip-root ...">
<!-- action button is nested here when clickable -->
<span class="tj-chip-label ...">
<!-- Chip contents -->
</span>
<!-- start decorator is nested here when present -->
<!-- end decorator is nested here when present -->
</div>

API

See the documentation below for a complete reference to all of the props available to the components mentioned here.