Patterns
Data table
A table is rarely just a table — it ships with pagination, and it needs an answer for the moment the data is still loading and the moment there's nothing to show. Design all three states up front so the list never looks broken.
Loaded
Table with Pagination beneath it.
| Name | Role | Status |
|---|---|---|
| Ava Chen | Engineer | Active |
| Liam Park | Designer | Pending |
| Noah Reyes | Product | Invited |
Loading
Hold the table's shape with skeleton rows — never collapse the layout or show a bare spinner where structured content will land.
| Name | Role | Status |
|---|---|---|
Empty
When there's no data, say so plainly and offer the next action — don't show an empty grid.
| Name | Role | Status |
|---|
No team members yet
Invite someone to get started — they'll show up here.
Rules of thumb
- Always design loading and empty alongside the loaded state — they're not edge cases, they're the first thing a new user sees.
- Skeletons mirror the real row shape so there's no layout shift when data arrives.
- Pagination sits directly below the table; the current page is marked with
aria-currentand the disabled edge controls stay visible, not removed. - Every table needs a composition-settings control — column visibility, default sort column and direction, and default page size, persisted per user. New obligation in v1.6: it applies to tables you have already shipped, not just new ones.
Page-level empty / loading / error patterns are guidance, not yet tokenized — see Known gaps.