<!--
Source: https://www.theui.dev/docs/table
Part of the theui-svelte documentation. Index: https://www.theui.dev/llms.txt
-->

# Table

A table you can build from data or write out by hand, with stripes, hover rows and border options.

## About

Pass `headers` and `data` and the `Table` builds the rows for you, or write `THead`, `TBody`, `TR`, `TH` and `TD` out by hand. The two styles mix freely, and the output is always wrapped in a horizontally scrollable container.

## Example

There are several ways to build a table. For example:

- Using data

- Using snippet

- Manually using the components

### Setup

At first import the relevant components of the table.

```html
<script>
  import { Table, THead, TBody, TR, TH, TD } from "theui-svelte";
</script>
```

### Example: Using Props

The `Table` component allows you to generate tables dynamically using data. This approach is useful when you have structured data and want to render it efficiently without manually defining each row and column. This method ensures your table remains dynamic and adaptable to different datasets.

Pass the `headers`, `data`, and `keys` as props to the `Table` component.

- `headers: string[]` - An array of column headers.

- `data: object[]` - An array of objects representing table rows.

- `keys: string[]` - An array of keys that map data fields to columns.

Cell values passed this way are rendered as plain text, so HTML inside them is not rendered. A key that is missing from a row renders an empty cell. To add custom markup, use the components as shown in the next example.

```html
<script>
  let headers = ["Heading 1", "Heading 2", "Heading 3", "Heading 4"];
  let data = [
    {item1: "Data 11", item2: "Data 12", item3: "Data 13", item4: "Data 14"},
    {item1: "Data 21", item2: "Data 22", item3: "Data 23", item4: "Data 24"},
    {item1: "Data 31", item2: "Data 23", item3: "Data 33", item4: "Data 43"},
  ];
  let keys = ["item1", "item2", "item3", "item4"];
</script>

<!-- Option 1 -->
<Table {headers} {data} {keys} />

<!-- Option 2 -->
<Table>
  <THead {headers} />
  <TBody {data} {keys} />
</Table>

<!-- Option 3 -->
<Table {headers}>
  <TBody>
    {#each data as d}
      <TR data={d} {keys} />
    {/each}
  </TBody>
</Table>
```

### Example: Using Components

Instead of props or dynamically looping through the data, the table content is written manually using the `THead`, `TBody`, `TR`, `TH` and `TD` components.

- `<THead>` - Contains the header row.

- `<TBody>` - Contains the table rows.

- `<TR>` - Represents a table row. Add `tableHeader={"{true}"}` to the header row so it gets the `trHeadClasses` styles. When a `TR` renders its cells from the `data` prop, `tableHeader` also makes it render `<th>` cells instead of `<td>`.

- `<TH>` - Represents a header cell.

- `<TD>` - Represents a table data containing the actual data.

```html
<Table>
  <THead>
    <TR tableHeader={true}>
      <TH>Heading 1</TH>
      <TH>Heading 2</TH>
      <TH>Heading 3</TH>
      <TH>Heading 4</TH>
    </TR>
  </THead>
  <TBody>
    <TR>
      <TD>Data 11</TD>
      <TD>Data 12</TD>
      <TD>Data 13</TD>
      <TD>Data 14</TD>
    </TR>
    ...
    ...
  </TBody>
</Table>
```

## Custom Header

If you need custom headers or anything other than text in the header just put your custom items in the `TH` component. For example:

```html
<Table>
  <THead>
    <TR>
      <TH class="items-center gap-2">
        Sort
        <Svg class="inline">
          <path d="M3.5 12.5a.5.5 0 0 ... 0 1h1a.5.5 0 0 0 0-1z"/>
        </Svg>
      </TH>
      <TH class="items-center gap-2">
        Sort
        <Svg class="inline">
          <path d="M3.5 2.5a.5.5 0 0 0-1 ... 1h1a.5.5 0 0 0 0-1z"/>
        </Svg>
      </TH>
    </TR>
  </THead>
</Table>
```

## Table Border

The `border` prop controls where borders appear in the table. By default, it is set to `"both"`. Setting it to `"x"` adds borders only between columns, while `"y"` applies borders only between rows. The default option, `"both"`, adds borders between both rows and columns, and `"none"` removes all borders. This prop allows you to customize the table's appearance based on your design preferences.

```html
<Table {headers} {data} {keys} border="x" />
<Table {headers} {data} {keys} border="y" />
<Table {headers} {data} {keys} border="none" />
```

## Table Spacing

The `space` prop adjusts the cell padding to control the overall table spacing, affecting how compact or spacious the table appears.

- `"compact"` - Reduces padding for a denser layout, making the table more space-efficient.

- `"default"` (Default value) - Uses the standard padding, providing a balanced look.

- `"comfortable"` - Increases padding for a more spacious and readable layout.

```html
<Table {headers} {data} {keys} space="compact" />
<Table {headers} {data} {keys} space="comfortable" />
```

## Stripe Rows

The `stripe` prop adds alternating background colors to table rows, improving readability and visual distinction between rows. By default, this feature is disabled (`undefined`), meaning all rows have the same background.

- `"even"` - Applies striping to even-numbered rows, making them visually distinct from odd rows.

- `"odd"` Applies striping to odd-numbered rows, enhancing readability by differentiating them from even rows.

- *Custom class names* - You can specify a class name instead of predefined values to apply custom styling. This allows full control over the appearance of striped rows, making it easy to match your design needs.

```html
<!-- Striped even rows -->
<Table {headers} {data} {keys} stripe="even" />
<!-- Striped odd rows -->
<Table {headers} {data} {keys} stripe="odd" />
<!-- Striped even rows with custom classes -->
<Table {headers} {data} {keys} stripe="even:bg-green-100 dark:even:bg-green-900" />
<!-- Striped odd rows with custom classes -->
<Table {headers} {data} {keys} stripe="odd:bg-green-100 dark:odd:bg-green-900" />
```

## Hoverable Rows

The `hover` prop enables a visual highlight effect when users hover over table rows. By default, this feature is disabled (undefined), meaning no hover effect is applied.

- `true` - When set to `true`, the row background color changes on hover, improving user experience and readability.

- *Custom class names* - Instead of using the default hover effect, you can pass a custom class to define your own hover styles, allowing for more design flexibility.

Use the `animationSpeed` prop to control how fast the hover color changes. Available values are `"none"`, `"slower"`, `"slow"`, `"normal"` (default), `"fast"` and `"faster"`.

```html
<!-- Hoverable rows -->
<Table {headers} {data} {keys} hover={true} />
<!-- Hoverable rows with custom classes -->
<Table {headers} {data} {keys} hover="hover:bg-red-100" />
<!-- Slower hover transition -->
<Table {headers} {data} {keys} hover={true} animationSpeed="slower" />
```

## Customization

You can use the following props to customize the table's appearance, allowing you to style the table and its elements as needed.

- `borderColor` - the border color for the table. The default is `"border-gray-200/80 dark:border-gray-800/80"`, which reads in both light and dark mode. Override it with any Tailwind border color class.

- `trHeadClasses` - Adds custom classes to the table header row (( inside )). This allows you to style the header separately, such as applying background colors, text styles, or spacing adjustments.

- `trClasses` - Applies custom classes to all table body rows ( inside ). Use this to control row styling, such as padding, text alignment, or hover effects.

- `thClasses` - Adds custom classes to all table header cells (), enabling control over the header text size, padding, alignment, or other styles.

- `tdClasses` - Adds custom classes to all table cells (), enabling precise control over text size, padding, alignment, or other styles.

> **Note:** you can use `class` attribute with any table related component to add your custom CSS classes.

## Accessibility

A data table is read cell by cell, so a screen reader has to know which header each cell belongs to. Build the table from `headers` and `data` and that is handled: every header cell is written as `<th scope="col">`.

Writing the rows yourself works the same way, because `TH` now sets `scope="col"` on its own. Change it to `scope="row"` on a header cell that names its row, such as the first cell of each line in a comparison table.

**A header cell that names its row**

```svelte
<TR>
  <TH scope="row">Starter</TH>
  <TD>$9</TD>
  <TD>3 projects</TD>
</TR>
```

Give the table a name with `ariaLabel`, or write a `<caption>` as the first thing inside it. Screen readers list the tables on a page, and an unnamed one is listed as nothing but "table".

**Naming the table**

```svelte
<Table ariaLabel="Pricing plans" {headers} {data} />
```

A table wider than its container scrolls sideways. That box is a tab stop while it overflows, so people who do not use a mouse can scroll it with the arrow keys, and it is announced as a region using the name from `ariaLabel`. When the table fits, the tab stop disappears again, so it never adds a stop for nothing.

Two things are still yours to get right: keep the header row in a `THead` rather than styling the first body row to look like one, and do not use a table for layout, since everything in it is announced as data.

## Configuration

---

Category: Components
Keywords: table, data, grid, component, svelte, svelte-5, theui-svelte, component-library, ui, tailwindcss
Full documentation set: https://www.theui.dev/llms-full.txt
