Index table
An index table displays a collection of objects of the same type, like orders or products. The main job of an index table is to help merchants get an at-a-glance of the objects to perform actions or navigate to a full-page representation of it.
A index table with simple items and no bulk actions, sorting, or filtering.
import {IndexTable, Card, useIndexResourceState, Text} from '@shopify/polaris';
import React from 'react';
function SimpleIndexTableExample() {
const customers = [
{
id: '3411',
url: 'customers/341',
name: 'Mae Jemison',
location: 'Decatur, USA',
orders: 20,
amountSpent: '$2,400',
},
{
id: '2561',
url: 'customers/256',
name: 'Ellen Ochoa',
location: 'Los Angeles, USA',
orders: 30,
amountSpent: '$140',
},
];
const resourceName = {
singular: 'customer',
plural: 'customers',
};
const {selectedResources, allResourcesSelected, handleSelectionChange} =
useIndexResourceState(customers);
const rowMarkup = customers.map(
({id, name, location, orders, amountSpent}, index) => (
<IndexTable.Row
id={id}
key={id}
selected={selectedResources.includes(id)}
position={index}
>
<IndexTable.Cell>
<Text variant="bodyMd" fontWeight="bold" as="span">
{name}
</Text>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
),
);
return (
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={
allResourcesSelected ? 'All' : selectedResources.length
}
onSelectionChange={handleSelectionChange}
headings={[
{title: 'Name'},
{title: 'Location'},
{title: 'Order count'},
{title: 'Amount spent'},
]}
>
{rowMarkup}
</IndexTable>
</Card>
);
}
Props
Want to help make this feature better? Please share your feedback.
- headings[T, ...T[]]< | >
- promotedBulkActions?( | ( & ))[]
- bulkActions?( | ( & ))[]
- children?React.ReactNode
- emptyState?React.ReactNode
- sort?React.ReactNode
- paginatedSelectAllActionText?string
- lastColumnSticky?boolean
- selectable?boolean
- sortable?boolean[]
List of booleans, which maps to whether sorting is enabled or not for each column. Defaults to false for all columns.
- defaultSortDirection?'ascending' | 'descending'
The direction to sort the table rows on first click or keypress of a sortable column heading. Defaults to ascending.
Defaults to 'descending'.
- sortDirection?'ascending' | 'descending'
The current sorting direction.
- sortColumnIndex?number
The index of the heading that the table rows are sorted by.
- onSort?(headingIndex: number, direction: 'ascending' | 'descending') => void
Callback fired on click or keypress of a sortable column heading.
- sortToggleLabels?
Optional dictionary of sort toggle labels for each sortable column, with ascending and descending label, with the key as the index of the column.
- itemCountnumber
- selectedItemsCount?number | "All"
- resourceName?{ singular: string; plural: string; }
- loading?boolean
- hasMoreItems?boolean
- condensed?boolean
- onSelectionChange?(selectionType: SelectionType, toggleType: boolean, selection?: string | Range) => void
Index tables can also:
- Support customized index rows and columns
- Include bulk actions so merchants can act on multiple objects at once
- Support sorting and filtering of long lists
- Be paired with pagination to make long lists digestible
Build
Using an index table in a project involves combining the following components and subcomponents:
- IndexTable
- IndexTableRow
- IndexTableCell
- Filters (optional)
- Pagination component (optional)
The index table component provides the UI elements for list sorting, filtering, and pagination, but doesn’t provide the logic for these operations. When a sort option is changed, filter added, or second page requested, you’ll need to handle that event (including any network requests) and then update the component with new props.
Purpose
Shopify is organized around objects that represent merchants businesses, like customers, products, and orders. Each individual order, for example, is given a dedicated page that can be linked to. In Shopify, we call these types of objects resources, and we call the object’s dedicated page its details page.
Problem
Take orders as an example. Merchants may have a lot of them. They need a way to scan their orders, view the different attributes on each order, and find out which ones need action first. In other words, they need a way find an individual order, call up more information about it, and take action on it.
Solution
Index tables function as:
- A content format, presenting a set of individual resources with multiple columns of information for each
- A system for taking action on one or more individual resources
- A way to navigate to an individual resource’s details page
Because a details page displays all the content and actions for an individual resource, you can think of a resource list as a summary of these details pages. In this way resource lists bridge a middle level in Shopify’s navigation hierarchy.
Best practices
Index tables should:
- Have items that perform an action when clicked. The action should navigate to the resource’s details page or otherwise provide more detail about the item.
- Customize the content and layout of their items rows to surface information to support merchants’ needs.
- Support sorting if the list can be long, and especially if different merchant tasks benefit from different sort orders.
- Support filtering if the list can be long.
- Paginate when the current list contains more than 50 items.
- Use the skeleton page component on initial page load for the rest of the page if the loading prop is true and items are processing.
Index tables can optionally:
- Provide bulk actions for tasks that are often applied to many list items at once. For example, merchants may want to add the same tag to a large number of products.
Content guidelines
Index tables should:
- Identify the type of resource, usually with a heading
Do
- Products
- Showing 50 products
Don’t
- No heading
- Indicate when not all members of a resource are being shown. For a card summarizing and linking to recently purchased products:
Do
- Popular products this week
Don’t
- Products
-
Follow the verb + noun formula for bulk actions
-
Follow the content guidelines for filter options and applied filters
IndexTableRow
An IndexTableRow
is used to render a row representing an item within an IndexTable
IndexTableRow properties
Prop | Type | Description |
---|---|---|
id | string | A unique identifier for the row |
selected | boolean | A boolean property indicating whether the row is selected |
position | number | The index position of the row |
subdued | boolean | A boolean property indicating whether the row should be subdued |
status | RowStatus | A property indicating whether the row should have a status |
disabled | boolean | A boolean property indicating whether the row should be disabled |
onClick | () => void | A function which overrides the default click behaviour |
IndexTableCell
An IndexTableCell
is used to render a single cell within an IndexTableRow
IndexTableCell properties
Prop | Type | Description |
---|---|---|
flush | boolean | A boolean property indicating whether the cell should remove the default padding |
className | string | Adds a class to the cell, used for setting widths of a cell |
Related components
- To create an actionable list of related items that link to details pages, such as a list of customers, use the resource list component
- To present structured data for comparison and analysis, like when helping merchants to gain insights or review analytics, use the data table component
- To display a simple list of related content, use the list component