Item
A row of media, text and actions for lists, settings and pickers, with a grouped surface and a hover highlight that glides between rows.
pnpm dlx shadcn@latest add https://hextaui.com/r/item.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopy and paste the following code into your project.
components/ui/item.tsx lib/motion.ts Update the import paths to match your project setup.
Give icon media a tone for colored tiles like iOS Settings, or leave it unset for a neutral tile. An item becomes interactive when it renders as a link, button or label through render. Only then does it get hover, press and focus styles, so static rows never pretend to be clickable.
variant="grouped" puts items on one surface. Separators are drawn for you and inset to the text, the first and last rows own the outer corners, and the separators next to a hovered or focused row fade out.
Interactive items in a group share one highlight that glides to the row under the pointer and takes on its corners. It only follows a mouse or pen, never touch, and turn it off with highlight={false}. Image media corners are concentric with the row.
Render an item as a <label> around a Checkbox and the whole row toggles it. A checked control, or aria-selected, aria-checked or aria-pressed on the item, marks the row selected.
default has no surface, outline draws a hairline and muted sits on a soft fill.
size scales padding, gap, corner radius and media together. A group tightens its gap to match.
The default <ItemMedia /> only centers its content, so an Avatar or AvatarGroup drops straight in.
A grouped list of people. Separators start where the text starts, whatever sits in the media slot, so they line up under the names.
<ItemActions /> holds buttons at the end of the row. Keep the item itself static when it holds buttons, so there's never a button inside a link.
<ItemHeader /> and <ItemFooter /> take a full row above and below the content.
In a default group, place an <ItemSeparator /> between items yourself.
Titles clamp to one line and descriptions to two. Unbroken strings wrap instead of widening the row.
Padding, separator insets and the chevron follow the reading direction.
| Key | Action |
|---|---|
| Tab | Moves to the next interactive item, in source order like any link or button. |
| Enter | Follows a link item or presses a button item. |
| Space | Presses a button item or toggles a label item. |
- A group is a list when its items are plain rows. Items rendered as links or buttons keep their own role, and the group drops the list role so the markup stays valid. Render the group as
<ul>and items as<li>wrapping links if you want both. <ItemMedia variant="icon" />and the chevron are hidden from screen readers. Give images real alt text when they carry meaning.- The highlight is decoration. Keyboard focus shows the focus ring, and the highlight never moves focus or changes the tab order.
Every part renders a <div> by default and accepts render and its element's attributes.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "muted" | "default" |
size | "default" | "sm" | "xs" | "default" |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="item" | Target items in CSS. |
data-variant | The current variant. |
data-size | The current size. |
data-interactive | Present when the item renders as a link, button or label. |
data-highlighted | Present while the group highlight is on it. |
--item-radius | Corner radius. Media corners derive from it. Set by size. |
--item-px / --item-py / --item-gap | Padding and gap. Set by size. |
--item-media-size | Size of icon and image media. Set by size. |
--item-inset | Where a grouped separator starts. Measured to line up with ItemContent, whatever the media is. |
| Prop | Type | Default |
|---|---|---|
variantgrouped puts items on one surface with automatic separators. | "default" | "grouped" | "default" |
highlightShow one highlight that glides between interactive items on hover. | boolean | true |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="item-group" | Target groups in CSS. |
data-variant | The current variant. |
data-highlight | Present when the hover highlight is on. |
--item-group-radius | Corner radius of a grouped surface. The first and last items follow it. |
data-slot="item-highlight" | The highlight element, with data-visible and data-pressed. |
| Prop | Type | Default |
|---|---|---|
varianticon puts the icon on a tile and hides it from screen readers. image crops to a square. Both have corners concentric with the item. | "default" | "icon" | "image" | "default" |
toneWith the icon variant, fills the tile with a solid color and turns the icon white, like iOS Settings. Leave it unset for a neutral tile. | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "sky" | "blue" | "indigo" | "purple" | "pink" | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="item-media" | Target media in CSS. |
data-variant | The current variant. |
data-tone | The tile color, when tone is set on an icon. |
--item-media-tone | The tile color. Set it to any color for a custom tone. |
| Attribute | Description |
|---|---|
data-slot="item-content" | Grows to fill the row. A second content block hugs its text. |
| Attribute | Description |
|---|---|
data-slot="item-title" | Clamped to one line. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <p> |
| Attribute | Description |
|---|---|
data-slot="item-description" | Clamped to two lines. |
| Attribute | Description |
|---|---|
data-slot="item-actions" | Target the actions in CSS. |
| Attribute | Description |
|---|---|
data-slot="item-header" | A full-width row above the content. |
data-slot="item-footer" | A full-width row below the content. |
A trailing chevron that nudges toward the reading direction when its item is hovered. Accepts every Tabler icon prop.
| Attribute | Description |
|---|---|
data-slot="item-chevron" | Target the chevron in CSS. |
| Attribute | Description |
|---|---|
data-slot="item-separator" | A hairline with role="separator". |
- MotionThe easing curves, durations and reduced-motion check every component animates with, plus hooks for size morphs and sliding highlights.
- AvatarUser photos with an initials fallback, status badges and stacked groups that collapse into a count.
- BadgeStatus labels with colored dots, removable tags that slide closed and counts that roll to their new value.
- CardA surface for grouping content, with three variants, edge-to-edge media, concentric radii and whole-card links.
- ChartRecharts charts with themed colors, a tooltip and legend that read labels from one config, and keyboard navigation with a visible focus ring.
- Data tableA table for real data, with sorting, search, row selection, pinned columns, a sticky header and pagination.