Item
A row with media, a title, a description and actions.
In Content first
See it live
npm run storybookWhen to use it
In Content first: Rows in the reading list, each with an action named in a word. Not where cards preview articles.
- 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 Content first decided and why. Each sample is the live story with that variant set.
defaultvariantUsed in Content firstWhat it is for
No border and no fill: the row sits on the surface around it.
In Content first
Rows in the reading list, separated by space, not lines.
outlinevariantNot used in Content firstWhat it is for
A border around each row.
In Content first
Borders would interrupt reading; space separates the rows.
mutedvariantNot used in Content firstWhat it is for
A soft fill behind the row.
In Content first
Every row in the reading list weighs the same; attention belongs to the text.
defaultsizeUsed in Content firstWhat it is for
Comfortable padding.
In Content first
Every row, at touch size: many readers are on phones.
smsizeNot used in Content firstWhat it is for
Tighter padding.
In Content first
Many readers are on phones, and rows are read, not scanned.
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
Space separates groups; lines would interrupt reading.
2So Item
- ✓uses default: Rows in the reading list, separated by space, not lines.
- –does not use outline: Borders would interrupt reading; space separates the rows.
3If it changed
No other answer follows from it.
spacing.values1The answer
Room around the text helps reading.
2So Item
- ✓uses default: Rows in the reading list, separated by space, not lines.
3If it changed
No other answer follows from it.
human.q11The answer
Attention belongs to the text.
2So Item
- –does not use muted: Every row in the reading list weighs the same; attention belongs to the text.
Button: large Field: horizontal Empty: default3If it changed
and 8 answers that follow from it: Surface, text, action and status, Only what floats, One, and 5 more.
accessibility.values1The answer
Readers are often on phones.
2So Item
- ✓uses default: Every row, at touch size: many readers are on phones.
- –does not use sm: Many readers are on phones, and rows are read, not scanned.
Button: default Button: compact3If it changed
and 1 answer that follow from it: Those and pressed.
tasks.q11The answer
People read from start to end.
2So Item
- –does not use sm: Many readers are on phones, and rows are read, not scanned.
3If it changed
and 23 answers that follow from it: Rarely, Attention on the content, Reading comfort, and 20 more.
Words
- Write to one person: "you", not "users".
- Short sentences with room to breathe.
- Explain why before asking for anything.
- Use: Read, Save for later, You, Next issue. Avoid: Click here, Submit, Users, Content.
The labels components use, from the voice tokens:
content.action.commit: Savecontent.action.cancel: Not nowcontent.action.destroy: Removecontent.action.retry: Try againcontent.action.empty-action: Browse guides
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.
Content first 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.8:0.5rem |
| Text size | component.item.font-sizetype.body.font-sizevar(--item-font-size) | font.size.18:1.125rem |
| Speed | component.item.durationmotion.duration.feedbackvar(--item-duration) | duration.moderate:200ms |
| Border focus Changes with theme on focus | component.item.border-focuscolor.border.focusvar(--item-border-focus) | Lightnavy.light.600:#1E3A5FDarknavy.dark.600:#8FA6C4 |
| Background hover Changes with theme on hover | component.item.background-hovercolor.surface.sunkenvar(--item-background-hover) | Lightstone.light.100:#F6F2EADarkstone.dark.100:#2E2A24 |
| Focus on focus | component.item.focusborder-width.focusvar(--item-focus) | border-width.2:2px |
| Focus ring focus Changes with theme on focus | component.item.focus-ring-focuscolor.border.focusvar(--item-focus-ring-focus) | Lightnavy.light.600:#1E3A5FDarknavy.dark.600:#8FA6C4 |
| Focus ring offset focus Changes with theme on focus | component.item.focus-ring-offset-focuscolor.surface.canvasvar(--item-focus-ring-offset-focus) | Lightstone.light.50:#FFFDF8Darkstone.dark.0:#14110D |
| 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) | Lightstone.light.200:#E4DDD0Darkstone.dark.100:#2E2A24 |
| Muted | ||
| Fill Changes with theme | component.item.muted.backgroundcolor.surface.sunkenvar(--item-muted-background) | Lightstone.light.100:#F6F2EADarkstone.dark.100:#2E2A24 |
| Default | ||
| Gap | component.item.default.gapspace.gap.groupvar(--item-default-gap) | space.32:2rem |
| Padding | component.item.default.paddingspace.inset.containervar(--item-default-padding) | space.24:1.5rem |
| Sm | ||
| Gap | component.item.sm.gapcomponent-spacing-map.x3var(--item-sm-gap) | space.20:1.25rem |
| Padding, left and right | component.item.sm.padding-xspace.inset.containervar(--item-sm-padding-x) | space.24:1.5rem |
| Padding, top and bottom | component.item.sm.padding-ycomponent-spacing-map.x3var(--item-sm-padding-y) | space.20:1.25rem |
| Icon | ||
| Size | component.item.icon.sizesize.control.defaultvar(--item-icon-size) | size.48:3rem |
| 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) | Lightstone.light.100:#F6F2EADarkstone.dark.100:#2E2A24 |
| Icon size | component.item.icon.icon-sizesize.iconvar(--item-icon-icon-size) | size.16:1rem |
| 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.18:1.125rem |
| Weight | component.item.title.font-weighttype.label.font-weightvar(--item-title-font-weight) | font.weight.600:600 |
| Description | ||
| Text size | component.item.description.font-sizetype.body.font-sizevar(--item-description-font-size) | font.size.18:1.125rem |
| 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) | Lightstone.light.600:#61594DDarkstone.dark.400:#A39A8B |
| Label 2 Changes with theme | component.item.description.label-2color.action.primaryvar(--item-description-label-2) | Lightnavy.light.600:#1E3A5FDarknavy.dark.600:#8FA6C4 |
| 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 | Lightstone.light.200 · #E4DDD0Darkstone.dark.100 · #2E2A24 |