Skip to main content

Data table

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

In Dense data

See it live​

Start Storybook to see it live: npm run storybook

When to use it​

In Dense data: Analysts scan hundreds of alerts, filter by status and asset group, sort by risk and act on many rows at once.

  • 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 Dense data uses it​

A number in a table
Use type.data
Not type.body
Mono digits line up in columns, so values compare at a glance.
A selected row or item
Use color.surface.selected
Not color.action.primary as a fill
A light tint shows selection without hiding the data.
Table row height
Use size.row (compact)
Not The comfortable row
Compact rows show more records without scrolling.
An action on one row or item
Use Icon button, ghost, compact
Not Button secondary in every row
Rows repeat dozens of times; a quiet icon keeps the table readable.

Words​

  • Lead with the object, then the state: "Alert 2041 contained."
  • Use numbers, not words for numbers.
  • One verb per button. No "please", no exclamation marks.
  • Use: Investigate, Filter, Assign, Escalated, Resolved. Avoid: Oops, Awesome, Please, Simply.

The labels components use, from the voice tokens:

  • content.action.commit: Save
  • content.action.cancel: Cancel
  • content.action.destroy: Delete
  • content.action.retry: Retry
  • content.action.empty-action: Change filters

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

Dense data 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.4:0.25rem
Table row heightcomponent.table.row-heightsize.rowvar(--table-row-height)size.32:2rem
Table row border
Changes with theme
component.table.row-bordercolor.border.defaultvar(--table-row-border)Lightslate.light.200:#DDE2EADarkslate.dark.100:#262D38
Data table
Gapcomponent.data-table.gapspace.gap.tightvar(--data-table-gap)space.4:0.25rem
Label hover
Changes with theme
on hover
component.data-table.label-hovercolor.text.primaryvar(--data-table-label-hover)Lightslate.light.900:#161B23Darkslate.dark.900:#F7F8FA
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.8:0.5rem
Cornercomponent.data-table.radiusradius.badgevar(--data-table-radius)radius.0:0rem
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)Lightslate.light.100:#EEF1F5Darkslate.dark.100:#262D38
Text
Changes with theme
component.data-table.labelcolor.text.mutedvar(--data-table-label)Lightslate.light.600:#535D6DDarkslate.dark.400:#969FAD
From the system
Edge
Changes with theme
color.border.default
straight from the system, through --border
Lightslate.light.200 · #DDE2EADarkslate.dark.100 · #262D38