Table

Styled data tables with optional striping and hover effects.

Default

Preview
Name Email Status
Jane Doe jane@example.com Active
John Smith john@example.com Pending
Bob Wilson bob@example.com Inactive
<div class="nano-table-wrapper">
  <table class="nano-table nano-table--striped nano-table--hoverable">
    <thead class="nano-table__head">
      <tr>
        <th scope="col" class="nano-table__header">Name</th>
        <th scope="col" class="nano-table__header">Email</th>
        <th scope="col" class="nano-table__header">Status</th>
      </tr>
    </thead>
    <tbody class="nano-table__body">
      <tr class="nano-table__row">
        <td class="nano-table__cell">Jane Doe</td>
        <td class="nano-table__cell">jane@example.com</td>
        <td class="nano-table__cell">
          <span class="nano-badge nano-badge--success">Active</span>
        </td>
      </tr>
    </tbody>
  </table>
</div>

Variants

  • nano-table--striped – alternating row backgrounds
  • nano-table--hoverable – highlight rows on hover

Sortable columns

Wrap a table with data-controller="nanoui-data-table" and mark sortable headers with --sortable + data-nanoui-data-table-target="header". The controller toggles aria-sort on click and (by default) sorts rows client-side. Set data-nanoui-data-table-server-value="true" to let the controller only dispatch a nanoui-data-table:sort event and leave actual sorting to the server (Turbo Frame, fetch, etc.).

Per-header options:

  • data-sort-key — the field name used in the dispatched event
  • data-sort-typestring (default), number, or date
  • data-sort-value on cells — explicit sort value when the displayed text isn’t directly comparable
Preview
Alice Anderson $49.00 Apr 15
Carol Carver $149.00 Apr 10
Bob Baker $349.00 Apr 12
<div class="nano-table-wrapper" data-controller="nanoui-data-table">
  <table class="nano-table">
    <thead class="nano-table__head">
      <tr>
        <th class="nano-table__header nano-table__header--sortable"
            data-nanoui-data-table-target="header"
            data-sort-key="amount"
            data-sort-type="number"
            data-action="click->nanoui-data-table#sort">
          <button type="button" class="nano-table__sort">Amount</button>
        </th>
      </tr>
    </thead>
    <tbody class="nano-table__body" data-nanoui-data-table-target="body">
      <tr class="nano-table__row" data-nanoui-data-table-target="row">
        <td class="nano-table__cell" data-sort-value="49">$49.00</td>
      </tr>
    </tbody>
  </table>
</div>

Pagination

Pair the table with .nano-table-pagination below. Pagination is a presentation-only component — you can wire it to Turbo, a fetch-and-replace handler, or server-rendered links.

Preview
<nav class="nano-table-pagination" aria-label="Table pagination">
  <span class="nano-table-pagination__info">
    Showing <strong>1–10</strong> of <strong>42</strong>
  </span>
  <span class="nano-table-pagination__controls">
    <a class="nano-table-pagination__button" aria-current="page" href="?page=1">1</a>
    <a class="nano-table-pagination__button" href="?page=2">2</a>
    <span class="nano-table-pagination__ellipsis">…</span>
    <a class="nano-table-pagination__button" href="?page=5">5</a>
  </span>
</nav>

Data table Stimulus API

  • Controller: nanoui-data-table
  • Targets: header, body, row
  • Values: server (Boolean, default false) — when true, skip client-side sorting and only dispatch the event
  • Events: nanoui-data-table:sort with { key, direction } in detail