Skip to content

IndexTable

IndexTable displays structured data in rows and columns with selection, sorting, and bulk actions. It’s ideal for managing lists of items like products, orders, or customers.

<script>
import { IndexTable, Card, Text, Badge } from 'svelte-polaris';
const orders = [
{ id: '1001', customer: 'John Doe', total: '$24.90', status: 'paid' },
{ id: '1002', customer: 'Jane Smith', total: '$18.50', status: 'pending' },
{ id: '1003', customer: 'Bob Johnson', total: '$31.20', status: 'paid' }
];
const headings = [
{ title: 'Order' },
{ title: 'Customer' },
{ title: 'Total' },
{ title: 'Status' }
];
</script>
<Card>
<IndexTable
itemCount={orders.length}
headings={headings}
selectable={false}
>
{#each orders as order}
<IndexTable.Row id={order.id} position={orders.indexOf(order)}>
<IndexTable.Cell>
<Text fontWeight="semibold">#{order.id}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{order.customer}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{order.total}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Badge tone={order.status === 'paid' ? 'success' : 'warning'}>
{order.status}
</Badge>
</IndexTable.Cell>
</IndexTable.Row>
{/each}
</IndexTable>
</Card>
<script>
import { IndexTable, Card, Text, Button, ButtonGroup } from 'svelte-polaris';
const products = [
{ id: 'p1', name: 'T-Shirt', price: '$19.99', inventory: 45 },
{ id: 'p2', name: 'Jeans', price: '$49.99', inventory: 23 },
{ id: 'p3', name: 'Sneakers', price: '$79.99', inventory: 12 }
];
let selectedItems = [];
const headings = [
{ title: 'Product' },
{ title: 'Price' },
{ title: 'Inventory' }
];
function handleSelectionChange(selection) {
selectedItems = selection;
}
function handleBulkEdit() {
console.log('Bulk edit:', selectedItems);
}
function handleBulkDelete() {
console.log('Bulk delete:', selectedItems);
}
</script>
<Card>
<IndexTable
itemCount={products.length}
headings={headings}
selectedItemsCount={selectedItems.length}
onSelectionChange={handleSelectionChange}
promotedBulkActions={[
{
content: 'Edit products',
onAction: handleBulkEdit
}
]}
bulkActions={[
{
content: 'Delete products',
onAction: handleBulkDelete
}
]}
>
{#each products as product}
<IndexTable.Row
id={product.id}
position={products.indexOf(product)}
selected={selectedItems.includes(product.id)}
>
<IndexTable.Cell>
<Text fontWeight="semibold">{product.name}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{product.price}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{product.inventory} in stock</Text>
</IndexTable.Cell>
</IndexTable.Row>
{/each}
</IndexTable>
</Card>
<script>
import { IndexTable, Card, Text } from 'svelte-polaris';
let customers = [
{ id: 'c1', name: 'Alice Brown', email: 'alice@example.com', orders: 12 },
{ id: 'c2', name: 'Bob Wilson', email: 'bob@example.com', orders: 8 },
{ id: 'c3', name: 'Carol Davis', email: 'carol@example.com', orders: 15 }
];
let sortedBy = null;
let sortDirection = 'ascending';
const headings = [
{ title: 'Name' },
{ title: 'Email' },
{ title: 'Orders', sortable: true }
];
function handleSort(index, direction) {
sortedBy = index;
sortDirection = direction;
if (index === 2) { // Orders column
customers = [...customers].sort((a, b) => {
const multiplier = direction === 'ascending' ? 1 : -1;
return (a.orders - b.orders) * multiplier;
});
}
}
</script>
<Card>
<IndexTable
itemCount={customers.length}
headings={headings}
selectable={false}
sortable={[false, false, true]}
sortedColumnIndex={sortedBy}
sortDirection={sortDirection}
onSort={handleSort}
>
{#each customers as customer}
<IndexTable.Row id={customer.id} position={customers.indexOf(customer)}>
<IndexTable.Cell>
<Text fontWeight="semibold">{customer.name}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{customer.email}</Text>
</IndexTable.Cell>
<IndexTable.Cell>
<Text>{customer.orders}</Text>
</IndexTable.Cell>
</IndexTable.Row>
{/each}
</IndexTable>
</Card>
PropTypeDefaultDescription
headingsIndexTableHeading[]Column headings
itemCountnumberTotal number of items
selectedItemsCountnumber0Number of selected items
selectablebooleantrueEnable row selection
sortableboolean[]Which columns are sortable
sortedColumnIndexnumberCurrently sorted column
sortDirection'ascending' | 'descending'Sort direction
onSelectionChange(selection: string[]) => voidSelection change handler
onSort(index: number, direction: string) => voidSort handler
promotedBulkActionsBulkAction[]Primary bulk actions
bulkActionsBulkAction[]Secondary bulk actions
PropTypeDefaultDescription
idstringUnique row identifier
positionnumberRow position
selectedbooleanfalseRow selection state
disabledbooleanfalseDisable row selection
PropTypeDefaultDescription
flushbooleanfalseRemove cell padding
  • Use clear, descriptive column headings
  • Implement sorting for numerical and date columns
  • Provide bulk actions for common operations
  • Use consistent data formatting across columns
  • Show loading states during data fetching
  • Handle empty states gracefully
  • Use appropriate column widths for content
  • Implement pagination for large datasets
  • Provide clear selection feedback
  • Use semantic row identifiers
  • Table uses proper semantic HTML structure
  • Column headers are properly associated with data
  • Keyboard navigation works correctly
  • Screen readers can navigate table structure
  • Sort controls are accessible
  • Selection state is announced
  • Bulk actions are keyboard accessible
  • Focus management works during interactions