Item
A row with media, a title, a description and actions.
In Brand expressive
See it live
npm run storybookWhen to use it
In Brand expressive: A short list with media and a few actions. Not for products and features; card does that.
- Use it when: Lists of things such as people, files or settings, each with a few actions.
- Not when: Records people compare cell by cell (a table).
Instead:
Variants
What each variant is for in any design system, then what Brand expressive decided and why. Each sample is the live story with that variant set.
defaultvariantUsed in Brand expressiveWhat it is for
No border and no fill: the row sits on the surface around it.
In Brand expressive
Rows inside a card, which already gives the frame.
outlinevariantUsed in Brand expressiveWhat it is for
A border around each row.
In Brand expressive
Rows on a color block, with a border so each holds its edge on vivid color.
mutedvariantNot used in Brand expressiveWhat it is for
A soft fill behind the row.
In Brand expressive
A quiet fill reads as bland on a loud page; color blocks already mark each section.
defaultsizeUsed in Brand expressiveWhat it is for
Comfortable padding.
In Brand expressive
Every row, at touch size: phones first.
smsizeNot used in Brand expressiveWhat it is for
Tighter padding.
In Brand expressive
Phones first: no compact rows.
Why it works this way
Item looks the way it does because of 5 answers about this product. Each card is one answer, in three steps: the answer, what it decided for Item, and what would move if it changed.
elevation.definition1The answer
Cards hold each offer.
2So Item
- ✓uses default: Rows inside a card, which already gives the frame.
3If it changed
No other answer follows from it.
color.values1The answer
Vivid color is the brand.
2So Item
- ✓uses outline: Rows on a color block, with a border so each holds its edge on vivid color.
Toggle: default Toggle: outline3If it changed
and 2 answers that follow from it: Two-tone, Brand color.
brand.q21The answer
The brand is loud everywhere.
2So Item
- –does not use muted: A quiet fill reads as bland on a loud page; color blocks already mark each section.
3If it changed
and 22 answers that follow from it: Core and expressive display, Fine steps, so pages can set their own rhythm, A ratio, line heights in proportion, and 19 more.
outcomes.q21The answer
A bland page is the costly mistake.
2So Item
- –does not use muted: A quiet fill reads as bland on a loud page; color blocks already mark each section.
Button: secondary Button: danger Alert: destructive3If it changed
and 1 answer that follow from it: One per moment.
accessibility.values1The answer
Visitors come from social posts on phones.
2So Item
- ✓uses default: Every row, at touch size: phones first.
- –does not use sm: Phones first: no compact rows.
Button: default Button: compact Button: icon Field: horizontal Input group: inline-end Toggle: default Toggle: sm3If it changed
and 1 answer that follow from it: Those and pressed.
Words
- Headlines are short and bold. Three to six words.
- Verbs that move: Join, Try, Go.
- Playful in headlines, plain in errors.
- Use: Join, Drop, Go, Love. Avoid: Synergy, Leverage, Kindly.
The labels components use, from the voice tokens:
content.action.commit: Gocontent.action.cancel: Not nowcontent.action.destroy: Removecontent.action.retry: Try againcontent.action.empty-action: Explore the drop
See Voice and tone for the whole voice.
Use it in code
npx open-ds add item
The component reads only component keys and semantic tokens, so it follows the brand and mode on <html>.
Tokens it reads
Item reads 32 tokens of its own, each an alias of a semantic token. Each row is one part: its own token, the semantic it aliases, and the value it ends at. Change a semantic and every component that reads it follows; override one of Item's tokens to change Item alone.
Brand expressive decides what changes when you switch theme. Here a switch changes colors only, so the marked rows differ between light and dark; everything else holds steady.
| Part | Its token and the semantic it aliases | Value |
|---|---|---|
| Item | ||
| Corner | component.item.radiusradius.controlvar(--item-radius) | radius.999:9999px |
| Text size | component.item.font-sizetype.body.font-sizevar(--item-font-size) | font.size.17:1.0625rem |
| Speed | component.item.durationmotion.duration.feedbackvar(--item-duration) | duration.fast:120ms |
| Border focus Changes with theme on focus | component.item.border-focuscolor.border.focusvar(--item-border-focus) | Lightpink.light.600:#D61F7ADarkpink.dark.600:#F59ACA |
| Background hover Changes with theme on hover | component.item.background-hovercolor.surface.sunkenvar(--item-background-hover) | Lighttaupe.light.100:#FCEFE6Darktaupe.dark.100:#33241F |
| Focus on focus | component.item.focusborder-width.focusvar(--item-focus) | border-width.3:3px |
| Focus ring focus Changes with theme on focus | component.item.focus-ring-focuscolor.border.focusvar(--item-focus-ring-focus) | Lightpink.light.600:#D61F7ADarkpink.dark.600:#F59ACA |
| Focus ring offset focus Changes with theme on focus | component.item.focus-ring-offset-focuscolor.surface.canvasvar(--item-focus-ring-offset-focus) | Lighttaupe.light.50:#FFF8F3Darktaupe.dark.0:#120B09 |
| Gap | component.item.gapspace.gap.defaultvar(--item-gap) | space.16:1rem |
| Outline | ||
| Border Changes with theme | component.item.outline.bordercolor.border.defaultvar(--item-outline-border) | Lighttaupe.light.200:#F2DCCFDarktaupe.dark.100:#33241F |
| Muted | ||
| Fill Changes with theme | component.item.muted.backgroundcolor.surface.sunkenvar(--item-muted-background) | Lighttaupe.light.100:#FCEFE6Darktaupe.dark.100:#33241F |
| Default | ||
| Gap | component.item.default.gapspace.gap.groupvar(--item-default-gap) | space.40:2.5rem |
| Padding | component.item.default.paddingspace.inset.containervar(--item-default-padding) | space.32:2rem |
| Sm | ||
| Gap | component.item.sm.gapcomponent-spacing-map.x3var(--item-sm-gap) | space.24:1.5rem |
| Padding, left and right | component.item.sm.padding-xspace.inset.containervar(--item-sm-padding-x) | space.32:2rem |
| Padding, top and bottom | component.item.sm.padding-ycomponent-spacing-map.x3var(--item-sm-padding-y) | space.24:1.5rem |
| Icon | ||
| Size | component.item.icon.sizesize.control.defaultvar(--item-icon-size) | size.52:3.25rem |
| Corner | component.item.icon.radiusradius.badgevar(--item-icon-radius) | radius.999:9999px |
| Fill Changes with theme | component.item.icon.backgroundcolor.surface.sunkenvar(--item-icon-background) | Lighttaupe.light.100:#FCEFE6Darktaupe.dark.100:#33241F |
| Icon size | component.item.icon.icon-sizesize.iconvar(--item-icon-icon-size) | size.20:1.25rem |
| Image | ||
| Corner | component.item.image.radiusradius.badgevar(--item-image-radius) | radius.999:9999px |
| Content | ||
| Gap | component.item.content.gapspace.gap.tightvar(--item-content-gap) | space.8:0.5rem |
| Title | ||
| Gap | component.item.title.gapspace.gap.defaultvar(--item-title-gap) | space.16:1rem |
| Text size | component.item.title.font-sizetype.body.font-sizevar(--item-title-font-size) | font.size.17:1.0625rem |
| Weight | component.item.title.font-weighttype.label.font-weightvar(--item-title-font-weight) | font.weight.700:700 |
| Description | ||
| Text size | component.item.description.font-sizetype.body.font-sizevar(--item-description-font-size) | font.size.17:1.0625rem |
| Weight | component.item.description.font-weighttype.body.font-weightvar(--item-description-font-weight) | font.weight.400:400 |
| Text Changes with theme | component.item.description.labelcolor.text.mutedvar(--item-description-label) | Lighttaupe.light.600:#6B544ADarktaupe.dark.400:#B5988A |
| Label 2 Changes with theme | component.item.description.label-2color.action.primaryvar(--item-description-label-2) | Lightpink.light.600:#D61F7ADarkpink.dark.600:#F59ACA |
| Actions | ||
| Gap | component.item.actions.gapspace.gap.defaultvar(--item-actions-gap) | space.16:1rem |
| Header | ||
| Gap | component.item.header.gapspace.gap.defaultvar(--item-header-gap) | space.16:1rem |
| Footer | ||
| Gap | component.item.footer.gapspace.gap.defaultvar(--item-footer-gap) | space.16:1rem |
| From the system | ||
| Edge Changes with theme | color.border.default straight from the system, through --border | Lighttaupe.light.200 · #F2DCCFDarktaupe.dark.100 · #33241F |