Table
Native table in a named, focusable scroll region.
beta
Try it
<Table label="Data table" height="bounded" />Examples
Deployments
| Environment | Build | Status | Started | |
|---|---|---|---|---|
| production | #1247 | deployed | 2026-11-06 14:22 | |
| staging | #1246 | building | 2026-11-06 14:18 | |
| preview | #1245 | pending approval | 2026-11-06 13:45 | |
| development | #1244 | failed | 2026-11-06 12:30 |
<script lang="ts">
import Table from '@tcpsystems/ui/foundation/Table';
import Stack from '@tcpsystems/ui/foundation/Stack';
import Cluster from '@tcpsystems/ui/foundation/Cluster';
import Badge from '@tcpsystems/ui/foundation/Badge';
import Status from '@tcpsystems/ui/foundation/Status';
import Button from '@tcpsystems/ui/foundation/Button';
import Icon from '@tcpsystems/ui/foundation/Icon';
</script>
<Stack data-gap="lg">
<Table label="Recent deployments">
<thead>
<tr>
<Table mode="sort-header" href="#" sort="descending">Environment</Table>
<Table mode="sort-header" href="#" kind="num">Build</Table>
<Table mode="sort-header" href="#">Status</Table>
<Table mode="sort-header" href="#" sort="ascending">Started</Table>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<td>production</td>
<td>#1247</td>
<td><Status tone="ok">deployed</Status></td>
<td>2026-11-06 14:22</td>
<td><Button variant="ghost" icon="eye" aria-label="View deployment" /></td>
</tr>
<tr>
<td>staging</td>
<td>#1246</td>
<td><Status tone="progress">building</Status></td>
<td>2026-11-06 14:18</td>
<td><Button variant="ghost" icon="eye" aria-label="View deployment" /></td>
</tr>
<tr>
<td>preview</td>
<td>#1245</td>
<td><Status tone="warn">pending approval</Status></td>
<td>2026-11-06 13:45</td>
<td><Button variant="ghost" icon="eye" aria-label="View deployment" /></td>
</tr>
<tr>
<td>development</td>
<td>#1244</td>
<td><Status tone="danger">failed</Status></td>
<td>2026-11-06 12:30</td>
<td><Button variant="ghost" icon="eye" aria-label="View deployment" /></td>
</tr>
</tbody>
</Table>
<Cluster justify="end">
<Button variant="ghost">View all deployments</Button>
</Cluster>
</Stack>Empty and bounded
<script lang="ts">
import Table from '@tcpsystems/ui/foundation/Table';
import Stack from '@tcpsystems/ui/foundation/Stack';
import Cluster from '@tcpsystems/ui/foundation/Cluster';
import EmptyState from '@tcpsystems/ui/foundation/EmptyState';
import Button from '@tcpsystems/ui/foundation/Button';
const uid = $props.id();
let busy = $state(false);
</script>
<Stack data-gap="lg">
<Table label="Incidents" height="bounded" {busy}>
<thead>
<tr>
<Table mode="sort-header" href="#" sort="descending">Incident</Table>
<Table mode="sort-header" href="#" kind="num">Severity</Table>
<Table mode="sort-header" href="#">Service</Table>
<Table mode="sort-header" href="#">Since</Table>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{#if busy}
<tr><td colspan="5"><EmptyState title="Loading incidents…" /></td></tr>
{:else}
<tr>
<td colspan="5">
<EmptyState title="No active incidents">
{#snippet actions()}
<Button variant="primary" icon="plus">Create incident</Button>
{/snippet}
</EmptyState>
</td>
</tr>
{/if}
</tbody>
</Table>
<Cluster>
<Button variant="ghost" onclick={() => busy = !busy}>{busy ? 'Done loading' : 'Simulate loading'}</Button>
</Cluster>
</Stack>API
import Table from '@tcpsystems/ui/foundation/Table';| Prop | Type | Default |
|---|---|---|
mode? | 'table' | 'sort-header' | 'table' |
label? | string | none |
height? | 'bounded' | none |
busy? | boolean | false |
href? | string | none |
sort? | 'none' | 'ascending' | 'descending' | 'none' |
kind? | 'num' | none |
priority? | 'medium' | 'low' | none |
| Snippet |
|---|
children |
| Hook | Kind |
|---|---|
.tcp-table-frame | Root class |
data-height | Data attribute |
data-kind | Data attribute |
data-priority | Data attribute |