Data display
Table
Rows and columns for scannable, comparable data. Table is the static primitive; DataGrid wraps it with search, sorting, column visibility, paging and loading/empty states for operational lists.
Choosing the right one
If the user ever has to find a row, you want DataGrid. If they just read a short list, Table.
| Component | Use |
|---|---|
Table | Static, short lists: plan summaries, breakdowns inside a detail page. |
DataGrid | Operational lists: claims queues, member rosters, anything searched or paged. |
DescriptionList | One record's fields — a detail view is not a one-row table. |
Anatomy
Header, body and cells; status renders as Badge tones, amounts as tabular numbers.
| Claim | Member | Amount (MYR) | Status |
|---|---|---|---|
| CLM-48213 | Aisyah Rahman | 85.00 | Approved |
| CLM-48214 | Lim Wei Jie | 120.00 | Pending |
| CLM-48216 | Tan Mei Ling | 310.00 | Denied |
Sortable columns use SortableHead (adds aria-sort and the direction glyph); DataGrid wires it to TanStack sorting automatically.
Structure
| Property | Value |
|---|---|
| Header | 44px rows, 12px uppercase --muted-foreground |
| Body rows | 12px vertical padding, 14px text, --border dividers |
| Hover | --muted row wash |
| Numbers | tabular-nums, right-aligned when compared |
| Container | --radius-xl border wrapper, horizontal scroll |
Best practices
Do
- Use
DataGridthe moment users need search, sorting, column hiding or paging. - Right-align comparable numbers and keep them
tabular-nums. - Give every table a caption or a preceding heading naming the data set.
- Show 5 skeleton rows while loading and a helpful empty state — never a blank table.
- Put row actions in a trailing
DropdownMenu, not a strip of icon buttons.
Don't
- Reach for
Tablewhen the content is really a list of cards (mobile-heavy views). - Truncate identifiers users copy (claim numbers) — wrap or widen instead.
- Mix column alignments without reason — text left, numbers right.
- Nest tables or merge cells; restructure the data instead.
Accessibility & keyboard
- Semantic
<table>markup throughout — screen readers get real row/column navigation. - Sortable headers are buttons with
aria-sort; sort state never relies on the arrow glyph alone. - Row hover is an enhancement only — no information lives exclusively in hover.
- Keyboard (DataGrid): Tab reaches search, column menu, sortable headers and pager; Enter/Space activates.