Skip to main content

Data table

Many records in one view, with search, filters, sorting, column choice, selection and paging.

Left out of Brand expressive Brand expressive avoids tools people use for hours. Data table is for acting on many records in bulk; here people browse and explore the story. Use instead: Card

See it live​

Start Storybook to see it live: npm run storybook

When to use it​

  • Use it when: People find, compare and act on many records, often in bulk.
  • Not when: A handful of rows (a plain table), or items people browse rather than compare (cards).

Instead:

  • Table: A few rows, no tools.
  • Card: Items to browse, not compare.

How Brand expressive uses it​

A number in a table
Use type.body
Not A mono font
Tables are rare and never compared column by column, so mono digits add nothing. The brand font keeps the voice.
A selected row or item
Use color.surface.selected (brand tint)
Not Grey
Selection carries the brand.
Table row height
Use size.row (comfortable)
Not A compact row
Tables are rare and short, so there is no need to fit many rows. Comfortable rows keep the brand's airy rhythm.
An action on one row or item
Use Button ghost with a word
Not An icon alone
Visitors come rarely, so they never learn an icon. A word says what will happen.

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: Go
  • content.action.cancel: Not now
  • content.action.destroy: Remove
  • content.action.retry: Try again
  • content.action.empty-action: Explore the drop

See Voice and tone for the whole voice.

Accessibility and keyboard​

KeyboardWhat happensNot
undefinedEvery tool and row action is reachable by keyboard.undefined

Test before you ship:

  • It stays a real table with headers; sorting and selection are announced. undefined

Use it in code​

npx open-ds add data-table

The component reads only component keys and semantic tokens, so it follows the brand and mode on <html>.

Tokens it reads​

Data table reads 12 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 Data table's tokens to change Data table alone.

Changes with theme

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.

PartIts token and the semantic it aliasesValue
Shared
Card radiuscomponent.card.radiusradius.containervar(--card-radius)radius.24:1.5rem
Table row heightcomponent.table.row-heightsize.rowvar(--table-row-height)size.52:3.25rem
Table row border
Changes with theme
component.table.row-bordercolor.border.defaultvar(--table-row-border)Lighttaupe.light.200:#F2DCCFDarktaupe.dark.100:#33241F
Data table
Gapcomponent.data-table.gapspace.gap.tightvar(--data-table-gap)space.8:0.5rem
Label hover
Changes with theme
on hover
component.data-table.label-hovercolor.text.primaryvar(--data-table-label-hover)Lighttaupe.light.900:#1F1411Darktaupe.dark.900:#FFF8F3
Paddingcomponent.data-table.paddingcomponent-spacing-map.x2var(--data-table-padding)space.8:0.5rem
Gap 2component.data-table.gap-2space.gap.defaultvar(--data-table-gap-2)space.16:1rem
Cornercomponent.data-table.radiusradius.badgevar(--data-table-radius)radius.999:9999px
Padding, left and rightcomponent.data-table.padding-xcomponent-spacing-map.x2var(--data-table-padding-x)space.8:0.5rem
Padding, top and bottomcomponent.data-table.padding-ycomponent-spacing-map.x1var(--data-table-padding-y)space.4:0.25rem
Background hover
Changes with theme
on hover
component.data-table.background-hovercolor.surface.sunkenvar(--data-table-background-hover)Lighttaupe.light.100:#FCEFE6Darktaupe.dark.100:#33241F
Text
Changes with theme
component.data-table.labelcolor.text.mutedvar(--data-table-label)Lighttaupe.light.600:#6B544ADarktaupe.dark.400:#B5988A
From the system
Edge
Changes with theme
color.border.default
straight from the system, through --border
Lighttaupe.light.200 · #F2DCCFDarktaupe.dark.100 · #33241F