# Table

**`sonic-table`** lays out tabular data with **`sonic-tr`** · **`sonic-th`** · **`sonic-td`** children, optionally grouped in **`sonic-thead`** · **`sonic-tbody`** · **`sonic-tfoot`**. It scrolls horizontally when columns overflow; set **`minWidth`** on wide cells to keep them readable. Render fetched rows with **`sonic-list`**.

## Basic example

**`bordered`** adds an outer frame and row dividers. **`sonic-tbody`** stripes and highlights its rows on hover.

<sonic-code>
  <template>
    <sonic-table bordered>
      <sonic-thead>
        <sonic-tr>
          <sonic-th>Flight</sonic-th>
          <sonic-th>Destination</sonic-th>
          <sonic-th>Status</sonic-th>
        </sonic-tr>
      </sonic-thead>
      <sonic-tbody>
        <sonic-tr>
          <sonic-td>CN 001</sonic-td>
          <sonic-td>New York JFK</sonic-td>
          <sonic-td>Boarding</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td>CN 014</sonic-td>
          <sonic-td>London LHR</sonic-td>
          <sonic-td>On time</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td>CN 102</sonic-td>
          <sonic-td>Rio de Janeiro GIG</sonic-td>
          <sonic-td>Delayed</sonic-td>
        </sonic-tr>
      </sonic-tbody>
    </sonic-table>
  </template>
</sonic-code>

## List, fetch and max height

Put a **`sonic-list`** with `displayContents` inside **`sonic-tbody`** and render one **`sonic-tr`** per item; the list sets `even` · `odd` · `last` on each row. **`maxHeight`** caps the scroll container so the body scrolls vertically.

<sonic-code>
  <template>
    <sonic-table maxHeight="10rem">
      <sonic-thead>
        <sonic-tr>
          <sonic-th>Time</sonic-th>
          <sonic-th>Flight</sonic-th>
          <sonic-th>Destination</sonic-th>
          <sonic-th>Gate</sonic-th>
        </sonic-tr>
      </sonic-thead>
      <sonic-tbody>
        <sonic-list fetch serviceURL="/docs-mock-api" dataProvider="flights" key="flights" displayContents>
          <template>
            <sonic-tr>
              <sonic-td data-bind ::inner-html="$time"></sonic-td>
              <sonic-td data-bind ::inner-html="$code"></sonic-td>
              <sonic-td minWidth="10rem" data-bind ::inner-html="$city <b>$airport</b>"></sonic-td>
              <sonic-td data-bind ::inner-html="$gate"></sonic-td>
            </sonic-tr>
          </template>
        </sonic-list>
      </sonic-tbody>
    </sonic-table>
  </template>
</sonic-code>

## Size

With no **`size`**, the table uses `md`.

<sonic-code>
  <template>
    <div class="grid grid-cols-4 gap-3">
      <sonic-table size="2xs" bordered><sonic-tr><sonic-td>2xs</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="xs" bordered><sonic-tr><sonic-td>xs</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="sm" bordered><sonic-tr><sonic-td>sm</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="md" bordered><sonic-tr><sonic-td>md</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="lg" bordered><sonic-tr><sonic-td>lg</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="xl" bordered><sonic-tr><sonic-td>xl</sonic-td></sonic-tr></sonic-table>
      <sonic-table size="2xl" bordered><sonic-tr><sonic-td>2xl</sonic-td></sonic-tr></sonic-table>
    </div>
  </template>
</sonic-code>

## Type

**`type`** on **`sonic-tr`** · **`sonic-th`** · **`sonic-td`** sets a semantic text color.

<sonic-code>
  <template>
    <sonic-table bordered>
      <sonic-tr>
        <sonic-th type="info">Set on</sonic-th>
        <sonic-th type="info">sonic-th</sonic-th>
      </sonic-tr>
      <sonic-tr>
        <sonic-td type="danger">Set on</sonic-td>
        <sonic-td type="danger">sonic-td</sonic-td>
      </sonic-tr>
      <sonic-tr type="success">
        <sonic-td>Set on</sonic-td>
        <sonic-td>sonic-tr</sonic-td>
      </sonic-tr>
    </sonic-table>
  </template>
</sonic-code>

## Colspan and rowspan

<sonic-code>
  <template>
    <sonic-table bordered>
      <sonic-tbody>
        <sonic-tr>
          <sonic-td colspan="2" class="bg-info text-neutral-0">colspan: 2</sonic-td>
          <sonic-td>cell</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td>cell</sonic-td>
          <sonic-td>cell</sonic-td>
          <sonic-td rowspan="2" class="bg-success text-neutral-0">rowspan: 2</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td>cell</sonic-td>
          <sonic-td>cell</sonic-td>
        </sonic-tr>
      </sonic-tbody>
    </sonic-table>
  </template>
</sonic-code>

## Alignment and width

**`align`** sets horizontal alignment. **`width`** · **`minWidth`** · **`maxWidth`** set the cell dimensions. **`vAlign`** exists on **`sonic-td`** only.

<sonic-code>
  <template>
    <sonic-table bordered>
      <sonic-thead>
        <sonic-tr>
          <sonic-th width="8rem">align</sonic-th>
          <sonic-th maxWidth="8rem">maxWidth 8rem</sonic-th>
          <sonic-th>vAlign</sonic-th>
        </sonic-tr>
      </sonic-thead>
      <sonic-tbody>
        <sonic-tr>
          <sonic-td align="left">left</sonic-td>
          <sonic-td maxWidth="8rem">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sonic-td>
          <sonic-td vAlign="top">top</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td align="center">center</sonic-td>
          <sonic-td maxWidth="8rem">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sonic-td>
          <sonic-td vAlign="middle">middle</sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td align="right">right</sonic-td>
          <sonic-td maxWidth="8rem">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</sonic-td>
          <sonic-td vAlign="bottom">bottom</sonic-td>
        </sonic-tr>
      </sonic-tbody>
    </sonic-table>
  </template>
</sonic-code>

## Sticky header and caption

**`sonic-th`** cells stick to the top of the scroll container. To stick the header to the page instead, set **`noCustomScroll`** (which removes the scroll container) and position **`sonic-thead`** yourself. **`sonic-caption`** adds a caption.

<sonic-code>
  <template>
    <sonic-table bordered noCustomScroll>
      <sonic-thead class="sticky top-16">
        <sonic-tr>
          <sonic-th minWidth="12rem">Product</sonic-th>
          <sonic-th align="center">Quantity</sonic-th>
          <sonic-th align="right">Price</sonic-th>
          <sonic-th></sonic-th>
        </sonic-tr>
      </sonic-thead>
      <sonic-tbody>
        <sonic-tr>
          <sonic-td>Desk lamp</sonic-td>
          <sonic-td align="center">2</sonic-td>
          <sonic-td align="right">40 €</sonic-td>
          <sonic-td align="right">
            <sonic-button shape="circle" variant="outline" size="sm" aria-label="Edit">
              <sonic-icon library="iconoir" name="edit-pencil" size="lg"></sonic-icon>
            </sonic-button>
          </sonic-td>
        </sonic-tr>
        <sonic-tr type="warning">
          <sonic-td>Notebook</sonic-td>
          <sonic-td align="center">0</sonic-td>
          <sonic-td align="right">8 €</sonic-td>
          <sonic-td align="right">
            <sonic-button shape="circle" variant="outline" size="sm" aria-label="Edit">
              <sonic-icon library="iconoir" name="edit-pencil" size="lg"></sonic-icon>
            </sonic-button>
          </sonic-td>
        </sonic-tr>
        <sonic-tr>
          <sonic-td>Headphones</sonic-td>
          <sonic-td align="center">1</sonic-td>
          <sonic-td align="right" type="danger">120 €</sonic-td>
          <sonic-td align="right">
            <sonic-button shape="circle" variant="outline" size="sm" aria-label="Edit">
              <sonic-icon library="iconoir" name="edit-pencil" size="lg"></sonic-icon>
            </sonic-button>
          </sonic-td>
        </sonic-tr>
      </sonic-tbody>
      <sonic-caption>Cart contents</sonic-caption>
    </sonic-table>
  </template>
</sonic-code>

## API reference

### `sonic-table`

| Attribute | Values | Description |
|----------|---------|-------------|
| `size` | `2xs` … `2xl` · `inherit` (default `md`) | Font size |
| `bordered` | boolean | Outer border and row dividers |
| `maxHeight` | CSS length | Max height of the scroll container |
| `noCustomScroll` | boolean | Remove the scroll container and its custom scrollbar |

| Slot | Description |
|------|-------------|
| *(default)* | Sections, rows and caption |

### `sonic-thead` · `sonic-tbody` · `sonic-tfoot` · `sonic-caption`

No attributes. Default slot only. `sonic-tbody` stripes and highlights its rows.

### `sonic-tr`

| Attribute | Values | Description |
|----------|---------|-------------|
| `type` | `default` · `primary` · `info` · `success` · `warning` · `danger` · `neutral` | Text color |
| `even` · `odd` | boolean | Striping background; set by `sonic-list` |
| `last` | boolean | No bottom border; set by `sonic-list` |

| Slot | Description |
|------|-------------|
| *(default)* | `sonic-th` or `sonic-td` cells |

### `sonic-th` · `sonic-td`

| Attribute | Values | Description |
|----------|---------|-------------|
| `type` | same as `sonic-tr` | Text color |
| `align` | `left` · `center` · `right` | Horizontal alignment |
| `vAlign` | CSS `vertical-align` | Vertical alignment (`sonic-td` only) |
| `colSpan` · `rowSpan` | number | Column and row span |
| `width` · `minWidth` · `maxWidth` | CSS length | Cell dimensions |
| `noBorder` | boolean | No bottom border (`sonic-th` only) |

| Slot | Description |
|------|-------------|
| *(default)* | Cell content |
