---
components: ["DataTable", "Pagination","Toolbar", "ToolbarContent", "ToolbarSearch", "ToolbarMenu", "ToolbarMenuItem", "ToolbarBatchActions"]
---

<script>
  import { InlineNotification, DataTable, DataTableSkeleton, Pagination, Toolbar, ToolbarContent, ToolbarSearch, ToolbarMenu, ToolbarMenuItem, Button, Link } from "carbon-components-svelte";
  import Launch from "carbon-icons-svelte/lib/Launch.svelte";
  import Preview from "../../components/Preview.svelte";

  const pagination = { pageSize: 5, page: 1}
</script>

`DataTable` is keyed for performance reasons.

<InlineNotification svx-ignore lowContrast title="Note:" kind="info" hideCloseButton>
  <div class="body-short-01">Every <code>headers</code> object must have a unique "key" property.</div>
</InlineNotification>

<InlineNotification svx-ignore lowContrast title="Note:" kind="info" hideCloseButton>
  <div class="body-short-01">Every <code>rows</code> object must have a unique "id" property.</div>
</InlineNotification>

### Default

The key value in `headers` corresponds to the key value defined in `rows`.

For example, the header key `"name"` will use the value of `rows[index].name`.

<DataTable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Slotted cells

Use the `"cell"` slot to control the display value per table cell. Individual row and cell data are provided through the `let:row` and `let:cell` directives.

The slot name for the table header cells is `"cell-header"`.

<DataTable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
 <svelte:fragment slot="cell-header" let:header>
    {#if header.key === 'port'}
      {header.value} (network)
    {:else}
      {header.value}
    {/if}
  </svelte:fragment>
  <svelte:fragment slot="cell" let:row let:cell>
    {#if cell.key === 'rule' && cell.value === 'Round robin'}
      <Link icon={Launch} href="https://en.wikipedia.org/wiki/Round-robin_DNS" target="_blank">{cell.value}</Link>
    {:else}
      {cell.value}
    {/if}
  </svelte:fragment>
</DataTable>

### With title, description

<DataTable title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Slottable title, description

The `title` and `description` props are slottable.

<DataTable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
    <strong slot="title">Load balancers</strong>
    <span slot="description" style="font-size: 1rem">
      Your organization's active load balancers.
    </span>
</DataTable>

### Static width

Set `useStaticWidth` to `true` to render the table with a width of "auto" instead of "100%".

<DataTable useStaticWidth
title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Custom column widths

Specify a `width` or `minWidth` property in the `headers` object to customize the width of each column.

A [table-layout: fixed](https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout#values) rule will be applied to the `table` element when using custom widths.

<InlineNotification svx-ignore lowContrast kind="warning" title="Note:" hideCloseButton>
  <div class="body-short-01">Custom column widths do not work with a <a class="bx--link" href="#sticky-header">sticky header</a>.</div>
</InlineNotification>

<FileSource src="/framed/DataTable/DataTableHeaderWidth" />

### Sticky header

Set `stickyHeader` to `true` for the header to be fixed in place.

A maximum height will applied to the datatable to force a scrollbar.

<DataTable
  stickyHeader
  headers={[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" },
  ]}
  rows={Array.from({ length: 20 }).map((_, i) => ({
    id: i,
    name: "Load Balancer " + (i + 1),
    protocol: "HTTP",
    port: i % 3 ? (i % 2 ? 3000 : 80) : 443,
    rule: i % 3 ? "Round robin" : "DNS delegation",
  }))}
/>

### With toolbar

<DataTable title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <Toolbar>
    <ToolbarContent>
      <ToolbarSearch />
      <ToolbarMenu>
        <ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem>
        <ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">
          API documentation
        </ToolbarMenuItem>
        <ToolbarMenuItem hasDivider danger>Stop all</ToolbarMenuItem>
      </ToolbarMenu>
      <Button>Create balancer</Button>
    </ToolbarContent>
  </Toolbar>
</DataTable>

### With toolbar (small size)

<DataTable size="short" title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <Toolbar size="sm">
    <ToolbarContent>
      <ToolbarSearch />
      <ToolbarMenu>
        <ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem>
        <ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">API documentation</ToolbarMenuItem>
        <ToolbarMenuItem hasDivider danger>Stop all</ToolbarMenuItem>
      </ToolbarMenu>
      <Button>Create balancer</Button>
    </ToolbarContent>
  </Toolbar>
</DataTable>

### Filterable

By default, `ToolbarSearch` will not filter `DataTable` rows.

Set `shouldFilterRows` to `true` to enable client-side filtering. The default filtering performs a basic string comparison on cell values that are of a string or a number type.

Note that in-memory filtering is not optimal for large data sets, where you might consider using server-side search.

<FileSource src="/framed/DataTable/DataTableFilterable" />

### Filterable (custom)

`shouldFilterRows` also accepts a function and passes it the current row and value. It expects the function to return a boolean.

<FileSource src="/framed/DataTable/DataTableFilterCustom" />

### Zebra stripes

<DataTable zebra
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Tall rows

<DataTable size="tall"
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Medium rows

<DataTable size="medium"
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Short rows

<DataTable size="short"
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Compact rows

<DataTable size="compact"
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Sortable

Set `sortable` to `true` to enable table column sorting.

To disable sorting on a specific column, set `sort` to `false` in the header object passed to the `headers` prop.

In the example below, the "Protocol" column is not sortable.

<DataTable sortable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol", sort: false },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
/>

### Sortable with pagination

If you want `DataTable` to sort the whole dataset but still display paginated content, you need to pass the whole dataset in the `rows` prop, 
and then limit displayed content by using `pageSize` and `page` props, which are corresponding to the same props in the `Pagination` component.

<DataTable sortable title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "cost", value: "Cost", display: (cost) => cost + " €" },
    {
      key: "expireDate",
      value: "Expire date",
      display: (date) => new Date(date).toLocaleString(),
      sort: (a, b) => new Date(a) - new Date(b),
    },
  ]}"
  pageSize={pagination.pageSize}
  page={pagination.page}
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      cost: 100,
      expireDate: "2020-10-21",
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      cost: 200,
      expireDate: "2020-09-10",
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      cost: 150,
      expireDate: "2020-11-24",
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      cost: 250,
      expireDate: "2020-12-01",
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      cost: 550,
      expireDate: "2021-03-21",
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      cost: 400,
      expireDate: "2020-11-14",
    },
  ]}"
/>
<Pagination 
  bind:pageSize={pagination.pageSize}
  bind:page={pagination.page}
  totalItems={6}
  pageSizeInputDisabled
/>

### Sortable with custom display and sort methods

<DataTable sortable title="Load balancers" description="Your organization's active load balancers."
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "cost", value: "Cost", display: (cost) => cost + " €" },
    {
      key: "expireDate",
      value: "Expire date",
      display: (date) => new Date(date).toLocaleString(),
      sort: (a, b) => new Date(a) - new Date(b),
    },
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      cost: 100,
      expireDate: "2020-10-21",
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      cost: 200,
      expireDate: "2020-09-10",
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      cost: 150,
      expireDate: "2020-11-24",
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      cost: 250,
      expireDate: "2020-12-01",
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      cost: 550,
      expireDate: "2021-03-21",
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      cost: 400,
      expireDate: "2020-11-14",
    },
  ]}"
/>

### Sortable with nested object values

<DataTable sortable title="Load balancers" description="Your organization's active load balancers."
           headers="{[
    { key: "name", value: "Name" },
    { key: "network.protocol", value: "Protocol" },
    { key: "network.port", value: "Port" },
    { key: "cost", value: "Cost", display: (cost) => cost + " €" },
    {
      key: "expireDate",
      value: "Expire date",
      display: (date) => new Date(date).toLocaleString(),
      sort: (a, b) => new Date(a) - new Date(b),
    },
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      network: {
        protocol: "HTTP",
        port: 3000,
      },
      cost: 100,
      expireDate: "2020-10-21",
    },
    {
      id: "b",
      name: "Load Balancer 1",
      network: {
        protocol: "HTTP",
        port: 443,
      },
      cost: 200,
      expireDate: "2020-09-10",
    },
    {
      id: "c",
      name: "Load Balancer 2",
      network: {
        protocol: "HTTP",
        port: 80,
      },
      cost: 150,
      expireDate: "2020-11-24",
    },
    {
      id: "d",
      name: "Load Balancer 6",
      network: {
        protocol: "HTTP",
        port: 3000,
      },
      cost: 250,
      expireDate: "2020-12-01",
    },
    {
      id: "e",
      name: "Load Balancer 4",
      network: {
        protocol: "HTTP",
        port: 443,
      },
      cost: 550,
      expireDate: "2021-03-21",
    },
    {
      id: "f",
      name: "Load Balancer 5",
      network: {
        protocol: "HTTP",
        port: 80,
      },
      cost: 400,
      expireDate: "2020-11-14",
    },
  ]}"
/>

### Programmatic sorting

Use the reactive `sortKey` and `sortDirection` props for programmatic sorting.

By default, the table is not sorted by a specific key. The `sortKey` value must be a valid `key` specified in the `headers` object.

Possible values for `sortDirection` include `"none"` or `"ascending"` or `"descending"`.

Setting `sortKey` to `null` and `sortDirection` to `"none"` should reset the table rows to their initial order.

<FileSource src="/framed/DataTable/DataTableProgrammaticSorting" />

### Empty column with overflow menu

Some use cases require an empty column in the table body without a corresponding table header.

For an object in the `headers` array, set `empty` to `true` to render an empty column.

In the following example, each row in the sortable data table has an overflow menu. There isn't a separate, useless table header column for the overflow menu.

<FileSource src="/framed/DataTable/DataTableAppendColumns" />

### Selectable

<FileSource src="/framed/DataTable/SelectableDataTable" />

### Batch selection

<FileSource src="/framed/DataTable/DataTableBatchSelection" />

### Batch selection with initial selected rows

Use the `selectedRowIds` prop to specify which rows should be selected.

<FileSource src="/framed/DataTable/DataTableBatchSelectionInitial" />

### Selectable with batch actions

<FileSource src="/framed/DataTable/DataTableBatchSelectionToolbar" />

### Selectable (radio)

<FileSource src="/framed/DataTable/RadioSelectableDataTable" />

### Non-selectable rows

Use `nonSelectableRowIds` to specify the ids for rows that should not be selectable.

<FileSource src="/framed/DataTable/DataTableNonSelectableRows" />

### Expandable

<DataTable expandable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <svelte:fragment slot="expanded-row" let:row>
    <pre>{JSON.stringify(row, null, 2)}</pre>
  </svelte:fragment>
</DataTable>

### Non-expandable rows

Use `nonExpandableRowIds` to specify the ids for rows that should not be expandable.

<FileSource src="/framed/DataTable/DataTableNonExpandableRows" />

### Expandable (zebra styles)

<FileSource src="/framed/DataTable/DataTableExpandableZebra" />

### Expandable (compact size)

<DataTable size="compact" expandable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <svelte:fragment slot="expanded-row" let:row>
    <pre>{JSON.stringify(row, null, 2)}</pre>
  </svelte:fragment>
</DataTable>

### Expandable (short size)

<DataTable size="short" expandable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <svelte:fragment slot="expanded-row" let:row>
    <pre>{JSON.stringify(row, null, 2)}</pre>
  </svelte:fragment>
</DataTable>

### Expandable (tall size)

<DataTable size="tall" expandable
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <svelte:fragment slot="expanded-row" let:row>
    <pre>{JSON.stringify(row, null, 2)}</pre>
  </svelte:fragment>
</DataTable>

### Batch expansion

<DataTable batchExpansion
  headers="{[
    { key: "name", value: "Name" },
    { key: "protocol", value: "Protocol" },
    { key: "port", value: "Port" },
    { key: "rule", value: "Rule" }
  ]}"
  rows="{[
    {
      id: "a",
      name: "Load Balancer 3",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "b",
      name: "Load Balancer 1",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "c",
      name: "Load Balancer 2",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
    {
      id: "d",
      name: "Load Balancer 6",
      protocol: "HTTP",
      port: 3000,
      rule: "Round robin"
    },
    {
      id: "e",
      name: "Load Balancer 4",
      protocol: "HTTP",
      port: 443,
      rule: "Round robin"
    },
    {
      id: "f",
      name: "Load Balancer 5",
      protocol: "HTTP",
      port: 80,
      rule: "DNS delegation"
    },
  ]}"
>
  <svelte:fragment slot="expanded-row" let:row>
    <pre>{JSON.stringify(row, null, 2)}</pre>
  </svelte:fragment>
</DataTable>

### Expandable and selectable

<FileSource src="/framed/DataTable/DataTableExpandableSelectable" />

### Skeleton

<DataTableSkeleton />

### Skeleton with headers, row count

<DataTableSkeleton headers={["Name", "Protocol", "Port", "Rule"]} rows={10} />

### Skeleton with object headers

`headers` can also be an array of objects. The type is the same as the `headers` prop type used in `DataTable`.

<DataTableSkeleton headers={[{ value: "Name" }, {value: "Protocol"}, {value:"Port"}, { value: "Rule"}]} rows={10} />

### Skeleton with empty header

Pass an object with `"empty"` set to `true` to render an empty table header column.

<DataTableSkeleton headers={[{ value: "Name" }, {value: "Protocol"}, {value:"Port"}, { value: "Rule"}, { empty: true }]} rows={10} />

### Skeleton without header, toolbar

<DataTableSkeleton showHeader={false} showToolbar={false} />

### Skeleton (tall size)

<DataTableSkeleton showHeader={false} showToolbar={false} size="tall" />

### Skeleton (short size)

<DataTableSkeleton showHeader={false} showToolbar={false} size="short" />

### Skeleton (compact size)

<DataTableSkeleton showHeader={false} showToolbar={false} size="compact" />
