TABLE: Structured data display with consistent styling
VARIANTS: Striped | Bordered | Borderless | Hover | Clickable
Use tables to display tabular data with consistent formatting. Choose variants based on density and interaction needs.
Base table: Column headers with light background, bottom borders on rows. Default size with comfortable padding.
| Application ID | Student Name | Year Group | Status | Submitted |
|---|---|---|---|---|
| #2024-001 | Sarah Johnson | Year 7 | Submitted | 15 Mar 2024 |
| #2024-002 | Michael Chen | Year 7 | Draft | 14 Mar 2024 |
| #2024-003 | Emma Williams | Year 8 | Submitted | 13 Mar 2024 |
| #2024-004 | James Brown | Year 7 | Under Review | 12 Mar 2024 |
<table class="tw-table">...</table>
Striped rows: Alternating row backgrounds improve readability for wide tables or long lists.
| Campaign Name | Type | Status | Sent | Opened | Clicked |
|---|---|---|---|---|---|
| Spring Open Day Invitation | Completed | 1,245 | 892 (72%) | 456 (37%) | |
| Summer Term Newsletter | Active | 2,103 | 1,567 (75%) | 892 (42%) | |
| Admissions Reminder SMS | SMS | Completed | 456 | — | — |
| Parent Survey | Draft | — | — | — |
<table class="tw-table tw-table-striped">...</table>
Full borders: Borders on all cells. Use when clear cell separation is important.
| Field Name | Field Code | Type | Required |
|---|---|---|---|
| Student First Name | STUDENT_FNAME | Text | Yes |
| Student Last Name | STUDENT_LNAME | Text | Yes |
| Date of Birth | STUDENT_DOB | Date | Yes |
| Previous School | PREV_SCHOOL | Text | No |
<table class="tw-table tw-table-bordered">...</table>
No borders: Clean, minimal appearance. Use for simple data displays or inside cards.
| 10:23 AM | New application submitted by Sarah Johnson |
| 9:45 AM | Email campaign "Spring Newsletter" sent to 1,234 contacts |
| 9:12 AM | Application #2024-002 moved to "Under Review" |
| 8:30 AM | Workflow "Welcome Sequence" triggered for 3 new enquiries |
<table class="tw-table tw-table-borderless">...</table>
Hover state: Row highlights on mouse over. Use to indicate that rows are scannable or interactive.
| Family Name | Contact | Enquiry Date | Status | Actions |
|---|---|---|---|---|
| Johnson Family | sarah.johnson@email.com | 15 Mar 2024 | New | |
| Chen Family | m.chen@email.com | 14 Mar 2024 | Contacted | |
| Williams Family | emma.w@email.com | 13 Mar 2024 | Converted |
<table class="tw-table tw-table-hover">...</table>
Combine modifiers: Striped + Hover for interactive data tables with improved readability.
| Workflow Name | Trigger | Steps | Active | Actions |
|---|---|---|---|---|
| Welcome Sequence | New Enquiry | 3 emails | Active | |
| Application Reminder | Draft for 7 days | 1 email, 1 SMS | Active | |
| Event Follow-up | Event Attendance | 2 emails | Inactive |
<table class="tw-table tw-table-striped tw-table-hover">...</table>
Sizes: Small for dense data, default for general use, large for spacious layouts.
| Code | Status | Count |
|---|---|---|
| ENQUIRY | Active | 234 |
| APPLICATION | Active | 156 |
| INTERVIEW | Pending | 45 |
| Setting | Value | Description |
|---|---|---|
| Application Window | 1 Sep - 31 Oct | Main application submission period |
| Assessment Date | 15 November | Entrance assessment day |
<table class="tw-table tw-table-sm">...</table><table class="tw-table tw-table-lg">...</table>
Interactive rows: Add .table-row-clickable to <tr> for cursor pointer and hover state. Use .table-row-selected for selected state.
| Application ID | Student Name | Status | Date |
|---|---|---|---|
| #2024-001 | Sarah Johnson | Submitted | 15 Mar 2024 |
| #2024-002 | Michael Chen | Draft | 14 Mar 2024 |
| #2024-003 | Emma Williams | Submitted | 13 Mar 2024 |
<tr class="tw-table-row-clickable">...</tr><tr class="tw-table-row-clickable tw-table-row-selected">...</tr>
Horizontal scroll: Wrap table in .table-responsive for horizontal scroll on small screens. Negative margins break out of tw-card padding.
| Campaign | Channel | Sent | Delivered | Opened | Clicked | Converted | ROI |
|---|---|---|---|---|---|---|---|
| Spring Open Day | 1,245 | 1,232 (99%) | 892 (72%) | 456 (37%) | 89 (7%) | £12,450 | |
| Summer Newsletter | 2,103 | 2,089 (99%) | 1,567 (75%) | 892 (42%) | 156 (7%) | £22,890 |
<div class="tw-table-responsive"><table class="tw-table">...</table></div>
Cell utilities: .table-cell-fit for auto-width columns, .table-cell-actions for right-aligned action buttons.
| # | Title | Status | Date | Actions |
|---|---|---|---|---|
| 1 | Configure application form fields | Done | 15 Mar | |
| 2 | Set up email templates | In Progress | 14 Mar |
<th class="tw-table-cell-fit">#</th><th class="tw-table-cell-actions">Actions</th>
No data: Use .table-empty class for empty state messaging.
| Application ID | Student Name | Status | Date |
|---|---|---|---|
|
No applications yet Applications will appear here once families begin submitting. |
|||
<td colspan="4" class="tw-table-empty">...</td>
While data loads: keep the real <thead> and render
.tw-table-skeleton-row rows in the body — one .tw-table-skeleton-bar per cell,
sized with a width utility to echo the column's content shape (.tw-table-skeleton-circle for
avatar columns). Mark the skeleton body aria-hidden="true", set aria-busy="true"
on the wrapper, and announce loading with a tw:sr-only live region.
Loading applications…
| Student Name | Status | Form | Submitted | |
|---|---|---|---|---|
<tr class="tw-table-skeleton-row"><td><span class="tw-table-skeleton-bar tw:w-40"></span></td>…</tr>
CELL PATTERNS: 15 standard content types for table cells
COMPOSES: Avatar | Badge | Tag | Progress | Form Switch | Typography Tokens
Recommended HTML patterns for common cell content. Built entirely from existing design system components and Tailwind utilities — no additional CSS classes needed (except .table-cell-check and .table-cell-truncate).
| Type | Example | Composes |
|---|---|---|
| Plain Text | Year 7 Main Entry | — |
| Text + Subtext |
Jack Davies
jack.davies@email.com
|
Typography tokens |
| Identity |
JD
Jack Davies
jack.davies@email.com
|
.avatar .avatar-sm |
| Relationship |
Sarah Johnson
Mother
+2 linked contacts
|
.badge .badge-sm |
| Assigned |
JD
Jack Davies
|
.avatar .avatar-xs |
| Family |
Sarah Johnson
(Mother)
Siblings: Oscar Clarke,
Ruby Clarke
|
Typography + links |
| Badge / Status |
Active
Pending
Rejected
|
.badge .badge-*-subtle .badge-dot |
| Tag / Multi-Value |
Music
Sport
+3
|
.tag-group .tag .tag-sm |
| Numeric |
142
87
12%
|
tabular-nums, font-medium |
| Currency |
£1,250.00
£3,500.00
was £3,200.00
|
tabular-nums, font-medium |
| Progress |
75%
|
.progress .progress-bar |
| Date |
13 Feb 2026
09:30 AM
|
whitespace-nowrap |
| Timestamp |
13 Feb 2026
2 hours ago
|
Typography tokens |
| Boolean |
|
.form-switch or FA icons |
| Link / URL | .table-cell-truncate | |
| Icon + Text |
Academic Scholarship
|
FA icon + text |
| Thumbnail |
|
Tailwind sizing + rounded |
<td><div class="tw:flex tw:items-center tw:gap-3"><div class="tw-avatar tw-avatar-sm tw-avatar-blue">JD</div>...</div></td><td><span class="tw-badge tw-badge-success-subtle tw-badge-dot">Active</span></td><td class="tw:text-right tw:tabular-nums tw:font-medium">142</td><td class="tw-table-cell-truncate"><a href="#">...</a></td>
SORT: .table-sortable | .table-sort-icon | .table-sort-asc | .table-sort-desc
Add .table-sortable to <th> for a clickable header. Use .table-sort-asc or .table-sort-desc to indicate the active sort direction. The icon is always fa-arrow-up — CSS handles rotation for descending.
| Name | Year Group | Status | Submitted | |
|---|---|---|---|---|
| Alice Brown | alice.brown@email.com | Year 9 | Active | 10 Feb 2026 |
| Charlie Evans | charlie.e@email.com | Year 8 | Pending | 8 Feb 2026 |
| David Foster | d.foster@email.com | Year 7 | Active | 5 Feb 2026 |
<th class="tw-table-sortable">Name <i class="fa-solid fa-arrow-up tw-table-sort-icon"></i></th><th class="tw-table-sortable tw-table-sort-asc">Name <i class="fa-solid fa-arrow-up tw-table-sort-icon"></i></th><th class="tw-table-sortable tw-table-sort-desc">Name <i class="fa-solid fa-arrow-up tw-table-sort-icon"></i></th>
SELECT: .table-cell-check + .form-check-input + .table-row-selected
Use .table-cell-check on <th> and <td> for narrow checkbox columns. Combine with .table-row-selected to highlight checked rows.
| Student Name | Year Group | Status | Submitted | |
|---|---|---|---|---|
|
SJ
Sarah Johnson
sarah.j@email.com
|
Year 7 | Active | 15 Feb 2026 | |
|
MC
Michael Chen
m.chen@email.com
|
Year 7 | Pending | 14 Feb 2026 | |
|
EW
Emma Williams
emma.w@email.com
|
Year 8 | Active | 13 Feb 2026 | |
|
JB
James Brown
j.brown@email.com
|
Year 7 | Rejected | 12 Feb 2026 |
<th class="tw-table-cell-check"><input type="checkbox" class="tw-form-check-input"></th><td class="tw-table-cell-check"><input type="checkbox" class="tw-form-check-input"></td><tr class="tw-table-row-selected">...</tr>
Expandable rows: a summary row reveals the .tw-table-row-detail row beneath it
via the table-expand controller. The toggle is a real button with aria-expanded +
aria-controls; clicking the row also works, but links inside cells stay clickable.
| Expand | Applicant | Year group | Status |
|---|---|---|---|
| Amelia Osei | Year 7 | Submitted | |
| Sibling at this school (Year 9) · SEND support requested · Distance 1.2 miles · Faith reference received | |||
| Daniel Okoro | Year 7 | In review | |
| First preference · Distance 3.8 miles · Awaiting primary school reference | |||
<tbody data-controller="table-expand"><tr class="tw-table-row-expandable" data-action="click->table-expand#toggle">…<button aria-expanded="false" aria-controls="tx-detail-1"><i class="fa-solid fa-chevron-right tw-table-expand-icon"></i></button>…</tr><tr class="tw-table-row-detail" id="tx-detail-1" hidden>…</tr></tbody>
Animated disclosure: wrap the detail cell's content in a
.tw-collapsible-content (inside a tw:overflow-hidden div) and the same
table-expand controller animates the open instead of snapping — it detects the wrapper and
toggles .tw-show rather than the row's hidden attribute. Do not
also set hidden here: a hidden row has no height to animate from.
Added 2026-08-12, because both screens in the product that expand table rows animate.
| Staff member | Area | Credits | Expand |
|---|---|---|---|
| Olga Petrova | Communications | 720 | |
|
|||
<tr class="tw-table-row-detail"><td colspan="4" class="tw:p-0"><div class="tw-collapsible-content" id="tx-anim-1"><div class="tw:overflow-hidden">…</div></div></td></tr>
TINTED HEADER: .tw-table-tinted-header — one class on the <table>
The product's blue header treatment, as a single class on the table instead of
tw:bg-table-header tw:text-primary-700 repeated on every <th>
(30 per-cell copies across 10 files before this was promoted). Use it where the header needs to
read as a band — reference tables, printable summaries, tables sitting directly on a page ground.
A table already inside a .tw-card toolbar usually does not need it.
| Intake | Applications | Offers made | Places accepted |
|---|---|---|---|
| Year 7 — September 2027 | 486 | 210 | 178 |
| Sixth Form — September 2027 | 231 | 195 | 142 |
| In-year transfers — 2026/27 | 64 | 41 | 39 |
<table class="tw-table tw-table-tinted-header">…</table>
A row that needs attention: a red tint plus a left accent on the first cell —
two carriers, so the row still reads as flagged when the tint is invisible (projector, print,
colour-vision deficiency). It survives .tw-table-hover, deepening rather than
disappearing on hover. Colour is never the only carrier: pair it with a badge or
wording in the row that says what is wrong — a red row nobody can explain is noise.
Reserve it for genuine blockers, a handful of rows at most; tint everything and nothing stands out.
| Student | Intake | Outstanding | Status |
|---|---|---|---|
| Amelia Hughes | Year 7 | None | Enrolled |
| Daniel Okoro | Year 7 | Proof of address, birth certificate | Blocked — 14 days overdue |
| Priya Raman | Sixth Form | Reference | Chasing |
| Tom Bradley | Sixth Form | Signed acceptance | Blocked — offer expires Friday |
<tr class="tw-table-row-danger"><td>Daniel Okoro</td>…<td><span class="tw-badge tw-badge-danger-subtle">Blocked — 14 days overdue</span></td></tr>