Components · Extended
Data Tables
A sortable, multi-column table for dashboard and analytics surfaces — built from the same row height, separator, and hover tokens already confirmed on Lists & Tables, extended past that page's single-column row pattern because dashboard products need this and Instagram's own product doesn't have one to evidence.
Live
Sortable columns, numeric alignment, row selection
Click a column header to sort. Numeric columns align to the line-end (right in LTR, left in RTL — see RTL & Internationalization) while text columns align to the line-start.
| Engagement | Posts | Status | |||
|---|---|---|---|---|---|
| @julesframes | 284.1K | 6.2% | 412 | Active | |
| @noahshotit | 1.2M | 3.8% | 891 | Active | |
| @streetportraits | 58.9K | 9.1% | 203 | Active | |
| @mikaelastudio | 412K | 4.5% | 1204 | Paused | |
| @camila.city | 92.3K | 7.7% | 156 | Active |
Spec
Shared tokens with Lists & Tables, extended for columns
Row height, separator, and hover treatment are identical to the confirmed row-list pattern — only the header row and column-specific alignment are new.
Row height
44px minimum — same confirmed value as Lists & Tables
Header row
background: rgb(--ig-secondary-background), system-12 bold uppercase labels, sticky position optional
Separator
1px solid rgb(--ig-separator) between rows — same token as Lists & Tables
Hover
--ig-hover-overlay on row, same as every other row-based pattern in this system
Cell padding
var(--space-3) vertical, var(--space-4) horizontal
Text alignment
text-align: start for text/identity columns, text-align: end for numeric columns — both logical, RTL-safe
Sort icon
16px chevron, rotates 180deg between ascending/descending, --ig-stop-magenta when active
Status badge
var(--radius-pill), --ig-success/10% bg for positive states, --ig-secondary-background for neutral
.table { width: 100%; border-collapse: collapse; }
.table thead th {
background: rgb(var(--ig-secondary-background));
padding: var(--space-3) var(--space-4);
font-size: 12px;
font-weight: var(--fw-bold);
text-transform: uppercase;
letter-spacing: 0.04em;
text-align: start;
color: rgb(var(--ig-secondary-text));
}
.table tbody tr {
min-height: 44px;
border-top: 1px solid rgb(var(--ig-separator));
}
.table tbody tr:hover {
background: rgba(var(--ig-hover-overlay-rgb), var(--ig-hover-overlay-alpha));
}
.table td {
padding: var(--space-3) var(--space-4);
text-align: start;
}
.table td[data-numeric="true"] {
text-align: end;
font-variant-numeric: tabular-nums;
}States
Row and column states
Default row
44px minimum height, 1px separator above, text/numeric cells aligned per column type.
Hover row
--ig-hover-overlay applied to the full row — same treatment as Lists & Tables rows.
Selected row
Checkbox checked; row background takes a light --ig-primary-button tint to stay visible alongside the hover overlay.
Sorted column
Header label and chevron switch to --ig-stop-magenta; chevron rotation reflects ascending/descending.
Empty result set
Replace the table body with the standard Empty States pattern — centered icon, headline, body, optional CTA.
Loading
Replace row content with the shimmer skeleton pattern from Loading & Skeletons — same row height, no layout shift when data resolves.
Do
- Reuse Lists & Tables' row tokens — 44px row height, --ig-separator dividers, --ig-hover-overlay — keep tables visually consistent with the rest of the row-based system, not a separate design language.
- Right/end-align numeric columns — Use text-align: end (not a hardcoded 'right') and font-variant-numeric: tabular-nums so digits line up vertically for scanning.
- Show loading and empty states using existing patterns — Cross-reference Loading & Skeletons for the loading row treatment and Empty States for zero-result tables — don't invent table-specific versions of either.
- Keep sort state in the URL or app state, not just component state — A user should be able to share or refresh a sorted/paginated table view and land on the same view.
Don’t
- Don't use this pattern for simple content lists — Notifications, search results, and settings rows are Lists & Tables — single-column, no header, no sort. Reach for Data Tables only when columns are genuinely independent, sortable fields.
- Don't make every column sortable by default — Sort only columns where ordering is meaningful (followers, engagement) — sorting a status or avatar column rarely helps a user.
- Don't paginate AND infinite-scroll the same table — Pick one. Numbered pagination suits analytical tables where a user wants to jump to a specific page; infinite scroll suits content feeds — see Lists & Tables.