Table — <mv-table>

CSS-styled table (hover, stripes, density, sticky header/column, statuses) + optional <mv-table> for sorting and filtering.

CategoryData display
TypeWeb Component (<mv-table>)
Statusstable
Keywordstable, data-table, sort, filter

When to use

Avoid when

Install

node scripts/add.mjs table --out ./src/marvelous

AI 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

NameTypeDescription
data-hover / data-striped / data-borderedbooleanOn .mv-table.
data-densitycompactTighter cells.
data-sticky / data-sticky-columnbooleanSticky header / first column.
data-alignend | centerCell alignment.
th[data-sort]text | number | dateSortable column (with <mv-table>).
td[data-value]stringSort value when it differs from the displayed text.
filter-inputselectorSearch field wired to the filter.

Methods

NameDescription
sort(index, direction, type)Sorts the rows.
filter(query)Hides rows that don’t contain the query.

Events

NameDescription
mv-sortdetail: { index, direction }.
mv-filterdetail: { query, visible }.

CSS classes

NameDescription
mv-table-wrapScrolling container with border and radius.
mv-tableOn <table>.
mv-table-statusStatus badge (data-status=success|warning|danger|info).
mv-table-mutedSecondary text.

Accessibility

aria-sort is updated on sortable headers, with native buttons inside the <th>. Keep a <caption> or aria-label on the table.