Components
Table
Table is used to display structured information in a neat and organized manner. Tables can make it easier for users to scan and compare information.
React
const Preview = () => { return ( <Table> <caption>Table caption</caption> <Table.Head> <Table.Row> <Table.HeaderCell>Header 1</Table.HeaderCell> <Table.HeaderCell>Header 2</Table.HeaderCell> <Table.HeaderCell>Header 3</Table.HeaderCell> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>Cell 1</Table.Cell> <Table.Cell>Cell 2</Table.Cell> <Table.Cell>Cell 3</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>Cell 4</Table.Cell> <Table.Cell>Cell 5</Table.Cell> <Table.Cell>Cell 6</Table.Cell> </Table.Row> </Table.Body> <Table.Foot> <Table.Row> <Table.HeaderCell>Footer 1</Table.HeaderCell> <Table.HeaderCell>Footer 2</Table.HeaderCell> <Table.HeaderCell>Footer 3</Table.HeaderCell> </Table.Row> </Table.Foot> </Table> ); }; render(<Preview />)
- zebra
- Description
Will give the table zebra striping
- Type
boolean- Default
false
- stickyHeader
- Description
Will make the table header sticky
- Type
boolean- Default
false
- border
- Description
Will give the table a rounded border
- Type
boolean- Default
false
- hover
- Description
Will give the table a hover effect on rows
- Type
boolean- Default
false
| Name | Type | Default | Description |
|---|---|---|---|
| zebra | boolean | false | Will give the table zebra striping |
| stickyHeader | boolean | false | Will make the table header sticky |
| border | boolean | false | Will give the table a rounded border |
| hover | boolean | false | Will give the table a hover effect on rows |
TableHeaderCell
- sort
- Description
If 'none' | 'ascending' | 'descending' | 'other' will add a button to the header cell and change aria-sort and icon
- Type
"none" | "ascending" | "descending" | "other"- Default
undefined
| Name | Type | Default | Description |
|---|---|---|---|
| sort | "none" | "ascending" | "descending" | "other" | undefined | If 'none' | 'ascending' | 'descending' | 'other' will add a button to the header cell and change aria-sort and icon |
Use
Example
Zebra Stripes
React
const ZebraEn = () => { return ( <Table zebra> <caption>Number of applications per month</caption> <Table.Head> <Table.Row> <Table.HeaderCell>Month</Table.HeaderCell> <Table.HeaderCell>2023</Table.HeaderCell> <Table.HeaderCell>2024</Table.HeaderCell> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.HeaderCell scope='row'>January</Table.HeaderCell> <Table.Cell>1 230</Table.Cell> <Table.Cell>1 450</Table.Cell> </Table.Row> <Table.Row> <Table.HeaderCell scope='row'>February</Table.HeaderCell> <Table.Cell>980</Table.Cell> <Table.Cell>1 120</Table.Cell> </Table.Row> <Table.Row> <Table.HeaderCell scope='row'>March</Table.HeaderCell> <Table.Cell>1 150</Table.Cell> <Table.Cell>1 300</Table.Cell> </Table.Row> </Table.Body> </Table> ); }; render(<ZebraEn />)
With border
React
const Border = () => { return ( <Table border> <Table.Head> <Table.Row> <Table.HeaderCell>Header 1</Table.HeaderCell> <Table.HeaderCell>Header 2</Table.HeaderCell> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>Cell 1</Table.Cell> <Table.Cell>Cell 2</Table.Cell> </Table.Row> </Table.Body> </Table> ); }; render(<Border />)
Sorting
You can use props on Table.HeaderCell to show that the table can be sorted by the contents of a column.
- Use the
sortprop to indicate the sort direction: "none"- no sorting"ascending"- ascending order"descending"- descending order- Use
onClickto handle what happens when the user clicks on the column header.
React
const SortableEn = () => { const dummyData = [ { id: 1, name: 'Lise Example', email: 'lise@example.com', phone: '22345678', }, { id: 2, name: 'Kari Example', email: 'kari@example.com', phone: '87654321', }, { id: 3, name: 'Ola Example', email: 'ola@example.com', phone: '32345678', }, { id: 4, name: 'Per Example', email: 'per@example.com', phone: '12345678', }, ]; const [sortField, setSortField] = useState< keyof (typeof dummyData)[0] | null >(null); const [sortDirection, setSortDirection] = useState<TableHeaderCellProps['sort']>(undefined); const handleSort = (field: keyof (typeof dummyData)[0]) => { if (sortField === field && sortDirection === 'descending') { setSortField(null); setSortDirection(undefined); } else { setSortField(field); setSortDirection( sortField === field && sortDirection === 'ascending' ? 'descending' : 'ascending', ); } }; const sortedData = [...dummyData].sort((a, b) => { if (sortField === null) return 0; if (a[sortField] < b[sortField]) return sortDirection === 'ascending' ? -1 : 1; if (a[sortField] > b[sortField]) return sortDirection === 'ascending' ? 1 : -1; return 0; }); return ( <Table> <Table.Head> <Table.Row> <Table.HeaderCell sort={sortField === 'name' ? sortDirection : 'none'} onClick={() => handleSort('name')} > Name </Table.HeaderCell> <Table.HeaderCell>Email</Table.HeaderCell> <Table.HeaderCell sort={sortField === 'phone' ? sortDirection : 'none'} onClick={() => handleSort('phone')} > Phone </Table.HeaderCell> </Table.Row> </Table.Head> <Table.Body> {sortedData.map((row) => ( <Table.Row key={row.id}> <Table.Cell>{row.name}</Table.Cell> <Table.Cell>{row.email}</Table.Cell> <Table.Cell>{row.phone}</Table.Cell> </Table.Row> ))} </Table.Body> </Table> ); }; render(<SortableEn />)
Fixed column width
You can use table-layout: fixed to prevent column widths from changing when the table content is updated.
This provides a smoother layout, and helps the browser draw the table faster.
This is especially useful in tables with pagination or other dynamically updated content, where stable column widths provide a better user experience.
React
const FixedTable = () => { const rows = Array.from({ length: 3 }, (_, i) => i + 1); return ( <Table style={{ tableLayout: 'fixed', }} > <Table.Head> <Table.Row> <Table.HeaderCell>Header 1</Table.HeaderCell> <Table.HeaderCell>Header 2</Table.HeaderCell> <Table.HeaderCell>Header 3</Table.HeaderCell> </Table.Row> </Table.Head> <Table.Body> {rows.map((row) => ( <Table.Row key={row}> <Table.Cell>{`Cell ${row}1`}</Table.Cell> <Table.Cell>{`Cell ${row}2`}</Table.Cell> <Table.Cell>{`Cell ${row}3`}</Table.Cell> </Table.Row> ))} </Table.Body> </Table> ); }; render(<FixedTable />)
HTML
It is recommended to read about <table> on MDN (mozilla.org) for a thorough review of HTML tables and their semantics.
The class name ds-table is applied to the <table> element.
Sorting
By placing <button> in a <th> with aria-sort="*" you create a visual button for sorting.
You connect the logic for sorting to the button yourself.
Note that we apply type="button" to avoid the button behaving like a submit button.
CSS variables and data attributes
| Name | Value |
|---|---|
| --dsc-table-background--hover | var(--ds-color-surface-hover) |
| --dsc-table-background--zebra | var(--ds-color-surface-tinted) |
| --dsc-table-background | transparent |
| --dsc-table-border-color | var(--ds-color-border-subtle) |
| --dsc-table-border-radius | var(--ds-border-radius-md) |
| --dsc-table-border-style | solid |
| --dsc-table-border-width | var(--ds-border-width-default) |
| --dsc-table-color | var(--ds-color-text-default) |
| --dsc-table-divider-border-color | var(--dsc-table-border-color) |
| --dsc-table-divider-border-style | solid |
| --dsc-table-divider-border-width | calc(var(--ds-border-width-default) + 1px) |
| --dsc-table-header-background--hover | var(--ds-color-surface-hover) |
| --dsc-table-header-background--sorted | var(--ds-color-surface-tinted) |
| --dsc-table-header-background--sticky | var(--ds-color-surface-default) |
| --dsc-table-header-background | transparent |
| --dsc-table-padding | var(--ds-size-2) var(--ds-size-3) |
| --dsc-table-sort-size | var(--ds-size-6) |
| Name | Value |
|---|---|
| data-border | |
| data-sticky-header | |
| data-zebra | |
| data-hover |