# Data Table

A data table built on [TanStack Table](https://tanstack.com/table) v9. Column headers sort on click, the search box filters across every column, and rows briefly highlight when their values change, which suits live feeds. Every cell can be customized with a `#cell-<key>` slot.

<demo-data-table>



</demo-data-table>

## Usage

```vue
<script setup lang="ts">
  import DataTable from '~/components/ui/data-table/DataTable.vue';
  import type { DataTableColumn } from '~/components/ui/data-table/types';

  interface Order {
    id: string;
    customer: string;
    status: string;
    amount: number;
  }

  const columns: DataTableColumn<Order>[] = [
    { key: 'id', header: 'Order' },
    { key: 'customer', header: 'Customer' },
    { key: 'status', header: 'Status' },
    { key: 'amount', header: 'Amount', align: 'end', format: (v) => `$${v}` },
  ];

  const orders: Order[] = [
    { id: 'ORD-1', customer: 'Ada Lovelace', status: 'Paid', amount: 1240 },
  ];
</script>

<template>
  <DataTable :columns="columns" :data="orders" row-key="id">
    <template #cell-status="{ row }">
      <span class="rounded-full bg-muted px-2 py-0.5 text-xs">{{
        row.status
      }}</span>
    </template>
  </DataTable>
</template>
```

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        columns
      </code>
    </td>
    
    <td>
      <code>
        { key; header; align?; sortable?; format? }[]
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Column definitions; <code>
        key
      </code>
      
       names a row field
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        data
      </code>
    </td>
    
    <td>
      <code>
        TRow[]
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Rows; replace the array to update
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        row-key
      </code>
    </td>
    
    <td>
      <code>
        keyof TRow
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Field that uniquely identifies a row
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        searchable
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the global search input
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        search-placeholder
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Search…'
      </code>
    </td>
    
    <td>
      Placeholder and label for the search input
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flash-changes
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Highlights rows whose values change
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        empty-text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'No results.'
      </code>
    </td>
    
    <td>
      Shown when no rows match
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        caption
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Screen-reader caption for the table
    </td>
  </tr>
</tbody>
</table>

Each `#cell-<key>` slot receives `{ row, value }`, where `row` is fully typed.

Motion respects `prefers-reduced-motion`.
