beta

Data table — <mv-data-table>

Full-featured data table around a .mv-table: column sorting, accent-insensitive search, value filters, a column visibility menu, row selection (indeterminate header checkbox, Shift + click for ranges) with a bulk-actions bar, pagination with rows per page, and an empty state.

CategoryBlocks
TypeWeb Component (<mv-data-table>)
Statusbeta
Also installscheckbox, menu, popover, pagination, table
Keywordsdata-table, datagrid, table, sort, filter, search, pagination, selection, bulk-actions, columns

When to use

Avoid when

Install

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

AI agent with the Marvelous UI MCP server: install_components({ slugs: ["data-table"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dismiss.js, core/dom.js, core/element.js, core/focus.js, core/motion.js, core/position.js, components/data-table/data-table.js, components/data-table/data-table.css, components/checkbox/checkbox.css, components/menu/menu.js, components/menu/menu.css, components/popover/popover.js, components/popover/popover.css, components/pagination/pagination.js, components/pagination/pagination.css, components/table/table.css, components/table/table.js.

Usage

Canonical markup — start from it and customize with attributes, data-* and CSS variables:

<div id="dt-demo" style="width:min(100%,64rem);margin-inline:auto">
<mv-data-table page-size="8" label="Recent orders">
  <div class="mv-data-table-toolbar">
    <div class="mv-input-group" data-size="sm">
      <label class="mv-input-group-addon" for="dt-demo-q"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg><span class="mv-sr-only">Search</span></label>
      <input id="dt-demo-q" class="mv-input" type="search" placeholder="Search orders or customers…" data-dt-search autocomplete="off">
    </div>
    <select class="mv-select" data-size="sm" data-dt-filter="status" aria-label="Filter by status">
      <option value="">All statuses</option>
      <option value="paid">Paid</option>
      <option value="pending">Pending</option>
      <option value="shipped">Shipped</option>
      <option value="refunded">Refunded</option>
      <option value="failed">Failed</option>
    </select>
    <div class="mv-data-table-toolbar-end">
      <mv-menu data-dt-columns placement="bottom-end">
        <button class="mv-button" data-variant="outline" data-size="sm" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/><path d="M9 4v16M15 4v16" opacity=".5"/></svg>Columns</button>
        <div data-content style="--mv-menu-width:12rem"></div>
      </mv-menu>
      <button class="mv-button" data-size="sm" type="button" data-dt-demo-export><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v12m-5-5 5 5 5-5M5 21h14"/></svg><span data-dt-label>Export</span></button>
    </div>
  </div>
  <div class="mv-table-wrap">
    <table class="mv-table">
      <thead>
        <tr>
          <th scope="col" data-dt-select></th>
          <th scope="col" data-key="id" data-sort="text">Order</th>
          <th scope="col" data-key="client" data-sort="text">Customer</th>
          <th scope="col" data-key="status" data-sort="text">Status</th>
          <th scope="col" data-key="channel" data-sort="text">Channel</th>
          <th scope="col" data-key="date" data-sort="date">Date</th>
          <th scope="col" data-key="items" data-sort="number" data-align="end">Items</th>
          <th scope="col" data-key="amount" data-sort="number" data-align="end">Amount</th>
          <th scope="col"><span class="mv-sr-only">Actions</span></th>
        </tr>
      </thead>
      <tbody>
        <tr data-id="ORD-4821">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4821</span></td>
          <td data-value="Camila Rossi"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:200" aria-hidden="true"><span class="mv-avatar-fallback">CR</span></span><div><b>Camila Rossi</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-22" class="mv-table-muted"><time datetime="2026-09-22">Sep 22, 2026</time></td>
          <td data-align="end" data-value="6">6</td>
          <td data-align="end" data-value="111.83"><b>$111.83</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4821" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4820">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4820</span></td>
          <td data-value="Isabel Moreno"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:280" aria-hidden="true"><span class="mv-avatar-fallback">IM</span></span><div><b>Isabel Moreno</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-22" class="mv-table-muted"><time datetime="2026-09-22">Sep 22, 2026</time></td>
          <td data-align="end" data-value="3">3</td>
          <td data-align="end" data-value="351.32"><b>$351.32</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4820" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4819">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4819</span></td>
          <td data-value="Kwame Boateng"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:160" aria-hidden="true"><span class="mv-avatar-fallback">KB</span></span><div><b>Kwame Boateng</b><small>[email protected]</small></div></div></td>
          <td data-value="refunded"><span class="mv-badge" data-variant="secondary" data-size="sm">Refunded</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-21" class="mv-table-muted"><time datetime="2026-09-21">Sep 21, 2026</time></td>
          <td data-align="end" data-value="1">1</td>
          <td data-align="end" data-value="151.54"><b>$151.54</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4819" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4818">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4818</span></td>
          <td data-value="Sofia Nguyen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:320" aria-hidden="true"><span class="mv-avatar-fallback">SN</span></span><div><b>Sofia Nguyen</b><small>[email protected]</small></div></div></td>
          <td data-value="pending"><span class="mv-badge" data-variant="warning" data-size="sm">Pending</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-20" class="mv-table-muted"><time datetime="2026-09-20">Sep 20, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="167.69"><b>$167.69</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4818" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4817">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4817</span></td>
          <td data-value="Tom Grant"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:240" aria-hidden="true"><span class="mv-avatar-fallback">TG</span></span><div><b>Tom Grant</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-20" class="mv-table-muted"><time datetime="2026-09-20">Sep 20, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="369.71"><b>$369.71</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4817" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4816">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4816</span></td>
          <td data-value="Lena Fischer"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:20" aria-hidden="true"><span class="mv-avatar-fallback">LF</span></span><div><b>Lena Fischer</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-19" class="mv-table-muted"><time datetime="2026-09-19">Sep 19, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="264.74"><b>$264.74</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4816" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4815">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4815</span></td>
          <td data-value="Hugo Larsen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:110" aria-hidden="true"><span class="mv-avatar-fallback">HL</span></span><div><b>Hugo Larsen</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Mobile app</td>
          <td data-value="2026-09-18" class="mv-table-muted"><time datetime="2026-09-18">Sep 18, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="100.83"><b>$100.83</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4815" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4814">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4814</span></td>
          <td data-value="Chloe Martin"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:350" aria-hidden="true"><span class="mv-avatar-fallback">CM</span></span><div><b>Chloe Martin</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Mobile app</td>
          <td data-value="2026-09-17" class="mv-table-muted"><time datetime="2026-09-17">Sep 17, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="373.11"><b>$373.11</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4814" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4813">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4813</span></td>
          <td data-value="Mehdi Haddad"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:60" aria-hidden="true"><span class="mv-avatar-fallback">MH</span></span><div><b>Mehdi Haddad</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Marketplace</td>
          <td data-value="2026-09-17" class="mv-table-muted"><time datetime="2026-09-17">Sep 17, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="373.29"><b>$373.29</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4813" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4812">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4812</span></td>
          <td data-value="Zoe Brooks"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:300" aria-hidden="true"><span class="mv-avatar-fallback">ZB</span></span><div><b>Zoe Brooks</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-16" class="mv-table-muted"><time datetime="2026-09-16">Sep 16, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="460.93"><b>$460.93</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4812" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4811">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4811</span></td>
          <td data-value="James Miller"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:190" aria-hidden="true"><span class="mv-avatar-fallback">JM</span></span><div><b>James Miller</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-15" class="mv-table-muted"><time datetime="2026-09-15">Sep 15, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="326.77"><b>$326.77</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4811" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4810">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4810</span></td>
          <td data-value="Emma Park"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:140" aria-hidden="true"><span class="mv-avatar-fallback">EP</span></span><div><b>Emma Park</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Marketplace</td>
          <td data-value="2026-09-14" class="mv-table-muted"><time datetime="2026-09-14">Sep 14, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="307.6"><b>$307.60</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4810" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4809">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4809</span></td>
          <td data-value="Noah Reyes"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:230" aria-hidden="true"><span class="mv-avatar-fallback">NR</span></span><div><b>Noah Reyes</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Mobile app</td>
          <td data-value="2026-09-14" class="mv-table-muted"><time datetime="2026-09-14">Sep 14, 2026</time></td>
          <td data-align="end" data-value="6">6</td>
          <td data-align="end" data-value="512.1"><b>$512.10</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4809" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4808">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4808</span></td>
          <td data-value="Maya Das"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:10" aria-hidden="true"><span class="mv-avatar-fallback">MD</span></span><div><b>Maya Das</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Marketplace</td>
          <td data-value="2026-09-13" class="mv-table-muted"><time datetime="2026-09-13">Sep 13, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="204.75"><b>$204.75</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4808" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4807">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4807</span></td>
          <td data-value="Yusuf Celik"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:260" aria-hidden="true"><span class="mv-avatar-fallback">YC</span></span><div><b>Yusuf Celik</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-12" class="mv-table-muted"><time datetime="2026-09-12">Sep 12, 2026</time></td>
          <td data-align="end" data-value="1">1</td>
          <td data-align="end" data-value="197.1"><b>$197.10</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4807" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4806">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4806</span></td>
          <td data-value="Mehdi Haddad"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:60" aria-hidden="true"><span class="mv-avatar-fallback">MH</span></span><div><b>Mehdi Haddad</b><small>[email protected]</small></div></div></td>
          <td data-value="pending"><span class="mv-badge" data-variant="warning" data-size="sm">Pending</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-11" class="mv-table-muted"><time datetime="2026-09-11">Sep 11, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="488.94"><b>$488.94</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4806" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4805">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4805</span></td>
          <td data-value="Hugo Larsen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:110" aria-hidden="true"><span class="mv-avatar-fallback">HL</span></span><div><b>Hugo Larsen</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Marketplace</td>
          <td data-value="2026-09-11" class="mv-table-muted"><time datetime="2026-09-11">Sep 11, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="433.63"><b>$433.63</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4805" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4804">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4804</span></td>
          <td data-value="Lena Fischer"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:20" aria-hidden="true"><span class="mv-avatar-fallback">LF</span></span><div><b>Lena Fischer</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-10" class="mv-table-muted"><time datetime="2026-09-10">Sep 10, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="387.7"><b>$387.70</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4804" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4803">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4803</span></td>
          <td data-value="Isabel Moreno"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:280" aria-hidden="true"><span class="mv-avatar-fallback">IM</span></span><div><b>Isabel Moreno</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-09" class="mv-table-muted"><time datetime="2026-09-09">Sep 9, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="605.59"><b>$605.59</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4803" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4802">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4802</span></td>
          <td data-value="Camila Rossi"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:200" aria-hidden="true"><span class="mv-avatar-fallback">CR</span></span><div><b>Camila Rossi</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-08" class="mv-table-muted"><time datetime="2026-09-08">Sep 8, 2026</time></td>
          <td data-align="end" data-value="5">5</td>
          <td data-align="end" data-value="210.58"><b>$210.58</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4802" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4801">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4801</span></td>
          <td data-value="Tom Grant"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:240" aria-hidden="true"><span class="mv-avatar-fallback">TG</span></span><div><b>Tom Grant</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-08" class="mv-table-muted"><time datetime="2026-09-08">Sep 8, 2026</time></td>
          <td data-align="end" data-value="3">3</td>
          <td data-align="end" data-value="569.74"><b>$569.74</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4801" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4800">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4800</span></td>
          <td data-value="Chloe Martin"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:350" aria-hidden="true"><span class="mv-avatar-fallback">CM</span></span><div><b>Chloe Martin</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Online store</td>
          <td data-value="2026-09-07" class="mv-table-muted"><time datetime="2026-09-07">Sep 7, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="397.99"><b>$397.99</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4800" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4799">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4799</span></td>
          <td data-value="Sofia Nguyen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:320" aria-hidden="true"><span class="mv-avatar-fallback">SN</span></span><div><b>Sofia Nguyen</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-06" class="mv-table-muted"><time datetime="2026-09-06">Sep 6, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="98.45"><b>$98.45</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4799" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4798">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4798</span></td>
          <td data-value="Hugo Larsen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:110" aria-hidden="true"><span class="mv-avatar-fallback">HL</span></span><div><b>Hugo Larsen</b><small>[email protected]</small></div></div></td>
          <td data-value="refunded"><span class="mv-badge" data-variant="secondary" data-size="sm">Refunded</span></td>
          <td class="mv-table-muted">London store</td>
          <td data-value="2026-09-05" class="mv-table-muted"><time datetime="2026-09-05">Sep 5, 2026</time></td>
          <td data-align="end" data-value="2">2</td>
          <td data-align="end" data-value="326.83"><b>$326.83</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4798" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4797">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4797</span></td>
          <td data-value="Hugo Larsen"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:110" aria-hidden="true"><span class="mv-avatar-fallback">HL</span></span><div><b>Hugo Larsen</b><small>[email protected]</small></div></div></td>
          <td data-value="shipped"><span class="mv-badge" data-variant="info" data-size="sm">Shipped</span></td>
          <td class="mv-table-muted">Marketplace</td>
          <td data-value="2026-09-05" class="mv-table-muted"><time datetime="2026-09-05">Sep 5, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="567.46"><b>$567.46</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4797" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4796">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4796</span></td>
          <td data-value="Emma Park"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:140" aria-hidden="true"><span class="mv-avatar-fallback">EP</span></span><div><b>Emma Park</b><small>[email protected]</small></div></div></td>
          <td data-value="pending"><span class="mv-badge" data-variant="warning" data-size="sm">Pending</span></td>
          <td class="mv-table-muted">Mobile app</td>
          <td data-value="2026-09-04" class="mv-table-muted"><time datetime="2026-09-04">Sep 4, 2026</time></td>
          <td data-align="end" data-value="4">4</td>
          <td data-align="end" data-value="241.16"><b>$241.16</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4796" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
        <tr data-id="ORD-4795">
          <td></td>
          <td><span class="mv-data-table-mono">ORD-4795</span></td>
          <td data-value="Kwame Boateng"><div class="mv-data-table-person"><span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:160" aria-hidden="true"><span class="mv-avatar-fallback">KB</span></span><div><b>Kwame Boateng</b><small>[email protected]</small></div></div></td>
          <td data-value="paid"><span class="mv-badge" data-variant="success" data-size="sm">Paid</span></td>
          <td class="mv-table-muted">Mobile app</td>
          <td data-value="2026-09-03" class="mv-table-muted"><time datetime="2026-09-03">Sep 3, 2026</time></td>
          <td data-align="end" data-value="6">6</td>
          <td data-align="end" data-value="112.11"><b>$112.11</b></td>
          <td data-align="end"><button class="mv-button" data-variant="ghost" data-size="icon" type="button" aria-label="Actions for ORD-4795" data-dt-demo-row><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button></td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="mv-data-table-footer">
    <span data-dt-selection aria-live="polite"></span>
    <label>Rows per page
      <select class="mv-select" data-size="sm" data-dt-page-size>
        <option>5</option><option>8</option><option>10</option><option>20</option>
      </select>
    </label>
    <span data-dt-page-info></span>
    <mv-pagination data-size="sm" hide-labels siblings="0" data-dt-always label="Orders pagination"></mv-pagination>
  </div>
  <div class="mv-data-table-bulk" role="toolbar" aria-label="Bulk actions" hidden>
    <span data-dt-bulk-count></span>
    <button class="mv-button" data-variant="ghost" data-size="sm" type="button" data-dt-action="ship"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h11v10H3zM14 10h4l3 3v3h-7"/><circle cx="7" cy="18" r="1.8"/><circle cx="17.5" cy="18" r="1.8"/></svg><span data-dt-label>Mark as shipped</span></button>
    <button class="mv-button" data-variant="ghost" data-size="sm" type="button" data-dt-action="export"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v12m-5-5 5 5 5-5M5 21h14"/></svg><span data-dt-label>Export</span></button>
    <button class="mv-button" data-variant="ghost" data-size="sm" type="button" data-dt-action="delete" style="color:var(--mv-danger)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span data-dt-label>Delete</span></button>
    <button class="mv-button" data-variant="ghost" data-size="icon" type="button" data-dt-clear aria-label="Clear selection"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
  </div>
</mv-data-table>
<p id="dt-demo-log" role="status" style="margin:.75rem 0 0;min-height:1.25rem;color:var(--mv-fg-muted);font-size:.75rem;text-align:center"></p>
</div>
<script type="module">
  const root = document.getElementById("dt-demo");
  const table = root?.querySelector("mv-data-table");
  const log = root?.querySelector("#dt-demo-log");
  table?.addEventListener("mv-action", (e) => {
    const { action, rows } = e.detail;
    const n = rows.length;
    const s = n > 1 ? "s" : "";
    if (action === "delete") {
      table.removeRows(rows);
      log.textContent = `${n} order${s} deleted.`;
    } else if (action === "ship") {
      for (const row of rows) {
        const cell = row.cells[3];
        cell.dataset.value = "shipped";
        cell.innerHTML = '<span class="mv-badge" data-variant="info" data-size="sm">Shipped</span>';
      }
      table.clearSelection();
      log.textContent = `${n} order${s} marked as shipped.`;
    } else if (action === "export") {
      log.textContent = `CSV export of ${n} order${s} ready (demo).`;
    }
  });
  root?.querySelector("[data-dt-demo-export]")?.addEventListener("click", () => { log.textContent = "Export of all orders ready (demo)."; });
  root?.addEventListener("click", (e) => {
    const b = e.target.closest("[data-dt-demo-row]");
    if (b) log.textContent = `Actions menu: ${b.closest("tr").dataset.id}`;
  });
</script>

API

Attributes

NameTypeDefaultDescription
page-sizenumber10Rows per page (kept in sync with select[data-dt-page-size]).
labelstringAccessible name for the table (aria-label) if it has none.
data-selectingbooleanSet while at least one row is selected.

Properties

NameTypeDescription
selectedRowsHTMLTableRowElement[]Selected rows (across all pages).

Methods

NameDescription
sortBy(key, direction?)Sorts by data-key ('ascending' | 'descending'); null clears the sort.
setColumnVisible(key, visible)Shows or hides a column.
clearSelection()Clears the selection.
resetFilters()Clears the search and filters.
removeRows(rows)Removes rows (e.g. after a bulk delete).
render()Re-renders after cells change.

Events

NameDescription
mv-actionA [data-dt-action] button was clicked. detail: { action, rows }.
mv-sortSort changed. detail: { key, direction }.
mv-columnsColumn visibility changed. detail: { key, visible }.
mv-renderAfter each render. detail: { total, page, pages }.

Content structure

NameDescription
table.mv-tablePlain HTML table: th[data-key] names the column, th[data-sort=text|number|date] makes it sortable, th[data-dt-select] adds the checkbox column; td[data-value] provides the raw value for sorting and filtering.
[data-dt-search]Search field (matches row text, ignoring accents and case).
select[data-dt-filter="key"]Exact-match filter on a column value (empty option = all).
mv-menu[data-dt-columns]Menu whose [data-content] panel is filled with column checkboxes (th[data-dt-hideable=false] opts out).
[data-dt-selection] / [data-dt-page-info]Auto-filled text: “n of N rows selected”, “1–8 of 27”.
select[data-dt-page-size]Rows-per-page picker.
mv-paginationControlled pagination (hidden when there is only one page, unless data-dt-always).
.mv-data-table-bulkFloating bulk-actions bar, shown as soon as a row is checked; [data-dt-bulk-count], [data-dt-action], [data-dt-clear].

CSS classes

NameDescription
mv-data-table-toolbar / -toolbar-end / -footerBars above and below the table.
[data-dt-label]Button label visually hidden in narrow containers (still the accessible name).
mv-data-table-person / -monoAvatar + name + email cells, monospace IDs.

Accessibility

Sorting uses real buttons in the headers with aria-sort; checkboxes are named after their row (“Select ORD-4821”) and the header checkbox supports the indeterminate state; rows carry aria-selected; the result count is announced (role=status) after a search or filter; the actions bar is a named role=toolbar; the column menu uses menuitemcheckbox items and stays open; pagination is keyboard navigable.