Table — <mv-table>
CSS-styled table (hover, stripes, density, sticky header/column, statuses) + optional <mv-table> for sorting and filtering.
| Category | Data display |
|---|---|
| Type | Web Component (<mv-table>) |
| Status | stable |
| Keywords | table, data-table, sort, filter |
When to use
- Tabular data must be compared across rows and columns with hover, stripes and status badges
- A long or wide dataset needs a sticky header or first column while scrolling
- Light client-side sorting and a search filter are enough, without pagination or selection
Avoid when
- Rows need selection, bulk actions, column visibility, value filters or pagination → use Data table instead
- Each item has rich mixed content rather than comparable columns → use Card instead
- Hundreds or thousands of rows would sit in the DOM at once; nothing is virtualized or paginated → use Data table instead
Install
node scripts/add.mjs table --out ./src/marvelousAI agent with the Marvelous UI MCP server: install_components({ slugs: ["table"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Files copied (dependencies included): tokens/tokens.css, core/base.css, core/element.js, components/table/table.css, components/table/table.js.
Usage
Canonical markup — start from it and customize with attributes, data-* and CSS variables:
<div style="display:grid;gap:.75rem;width:100%">
<input id="table-demo-filter" type="search" placeholder="Filter invoices…" aria-label="Filter" style="max-width:16rem;height:2.25rem;padding:0 .75rem;border:1px solid var(--mv-input);border-radius:var(--mv-radius-md);background:var(--mv-bg);color:inherit;font-size:.875rem">
<mv-table filter-input="#table-demo-filter">
<div class="mv-table-wrap">
<table class="mv-table" data-hover>
<thead>
<tr>
<th data-sort="text">Invoice</th>
<th data-sort="text">Customer</th>
<th>Status</th>
<th data-sort="date">Date</th>
<th data-sort="number" data-align="end">Amount</th>
</tr>
</thead>
<tbody>
<tr><td>INV-0042</td><td>Brightline Studio</td><td><span class="mv-table-status" data-status="success">Paid</span></td><td data-value="2026-09-18">Sep 18, 2026</td><td data-align="end" data-value="2450">$2,450.00</td></tr>
<tr><td>INV-0041</td><td>Nova Publishing</td><td><span class="mv-table-status" data-status="warning">Pending</span></td><td data-value="2026-09-12">Sep 12, 2026</td><td data-align="end" data-value="980">$980.00</td></tr>
<tr><td>INV-0040</td><td>Studio Kōan</td><td><span class="mv-table-status" data-status="danger">Overdue</span></td><td data-value="2026-08-29">Aug 29, 2026</td><td data-align="end" data-value="5120">$5,120.00</td></tr>
<tr><td>INV-0039</td><td>Opal Brewing Co.</td><td><span class="mv-table-status" data-status="success">Paid</span></td><td data-value="2026-08-21">Aug 21, 2026</td><td data-align="end" data-value="312.5">$312.50</td></tr>
</tbody>
<tfoot><tr><td colspan="4">Total</td><td data-align="end">$8,862.50</td></tr></tfoot>
</table>
</div>
</mv-table>
</div>API
Attributes
| Name | Type | Description |
|---|---|---|
data-hover / data-striped / data-bordered | boolean | On .mv-table. |
data-density | compact | Tighter cells. |
data-sticky / data-sticky-column | boolean | Sticky header / first column. |
data-align | end | center | Cell alignment. |
th[data-sort] | text | number | date | Sortable column (with <mv-table>). |
td[data-value] | string | Sort value when it differs from the displayed text. |
filter-input | selector | Search field wired to the filter. |
Methods
| Name | Description |
|---|---|
sort(index, direction, type) | Sorts the rows. |
filter(query) | Hides rows that don’t contain the query. |
Events
| Name | Description |
|---|---|
mv-sort | detail: { index, direction }. |
mv-filter | detail: { query, visible }. |
CSS classes
| Name | Description |
|---|---|
mv-table-wrap | Scrolling container with border and radius. |
mv-table | On <table>. |
mv-table-status | Status badge (data-status=success|warning|danger|info). |
mv-table-muted | Secondary text. |
Accessibility
aria-sort is updated on sortable headers, with native buttons inside the <th>. Keep a <caption> or aria-label on the table.