suiss/ui · Pattern
Table List
Tabular data that renders as a table on desktop and a grouped list on mobile.
Table List is an open-source pattern from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
TableList displays rows of data from a column definition. On desktop it renders a suiss/ui Table inside a bordered section, with a header row and one cell per column. On mobile (below 48rem, via useIsMobile), where wide tables do not fit, it renders an inset grouped list: each row shows a title line, a secondary line that joins description columns with a middle dot, and trailing values on the end.
Each column chooses its place in the mobile row through slot, and can provide a simpler mobileCell. Use it for orders, invoices, transactions and other records that people compare in columns on large screens.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
-
Add the
cnhelper. -
Add the pieces it builds on: Table,
use-mobile. -
Copy the source into
components/patterns/table-list.tsx:
- Update the import paths to match your project.
Usage
- Each
TableListColumnhas akey, aheaderand acellrenderer. Optional fields aremobileCell,slot(title,description,trailingorhidden) andalign(startorend). - On mobile, the first
titlecolumn becomes the primary line,descriptioncolumns form the secondary line, andtrailingcolumns appear at the end. Columns without a slot, or withhidden, are left out on mobile. mobileCellreplacescellon mobile, for example to drop styling that does not fit the list.align: "end"right-aligns the desktop header and cells.
Examples
Without title
Renders the table without a heading or region.
Empty
Shows custom emptyText when there are no rows.
API Reference
TableList
The section that renders the rows as a table or a grouped list.
| Prop | Type | Default | Description |
|---|---|---|---|
rows | T[] | Required | The data rows to display. |
columns | TableListColumn<T>[] | Required | The column definitions that render each row. |
getKey | (row: T, index: number) => React.Key | (_, index) => index | Returns the React key for a row. |
title | React.ReactNode | - | A heading above the data that also names the section. |
emptyText | React.ReactNode | "No results." | Content shown when rows is empty. |
Also accepts the props of React.ComponentProps<"section">.
Accessibility
- With a
title, the section is labelled by its heading and exposed as a region. - On desktop the data is a real table with column headers; an empty state is a single cell that spans every column.
- On mobile the rows are list items in a
ul.
Notes
Styling hooks: data-slot="table-list" and table-list-title; on mobile also table-list-items and table-list-item. The TableListColumn type is exported.

TableList takes rows and a columns definition, and renders each row as a TableListRow inside one rounded group. Each column has a slot that decides where its cell goes: the row title, the description line, the trailing side, or nowhere.
The row parts are also exported, so you can build the same grouped look inside a FlatList for long or virtualized lists.
Installation
The CLI also adds what it builds on: Item, Text.
Manual
-
Target iOS 17 or later.
-
Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
Define columns with key, header, cell and slot. Several description columns are joined with ·, and several trailing columns are shown side by side. Use mobileCell to render a different value than cell in the list, such as a shorter date.
Pass onRowPress to make rows pressable. When there are no rows, emptyText is shown in the group. The TableListColumn type is exported.
With a FlatList, use TableListRow as the item, pass first and last to round the ends, TableListSeparator as ItemSeparatorComponent, and TableListHeader and TableListFooter around the list.
Examples
With flat list
Builds the grouped list in a FlatList with a header, footer and separators.

API Reference
TableListTitle
A large heading above the list.
Also accepts the props of React.ComponentProps<typeof Text>.
TableListHeader
A small uppercase heading above a group.
Also accepts the props of React.ComponentProps<typeof Text>.
TableListFooter
A note below a group.
Also accepts the props of React.ComponentProps<typeof Text>.
TableListSeparator
An inset divider between rows.
Also accepts the props of ViewProps.
TableListRow
One row with a title, description and trailing content.
| Prop | Type | Default | Description |
|---|---|---|---|
title | React.ReactNode | - | The row's main text. |
description | React.ReactNode | - | A single-line secondary text. |
trailing | React.ReactNode | - | Content on the end side; text is shown in secondary color with tabular numbers. |
first | boolean | false | Rounds the top corners. |
last | boolean | false | Rounds the bottom corners. |
children | React.ReactNode | - |
Also accepts the props of React.ComponentProps<typeof Item>.
TableList
Renders rows from a column definition, with an optional title and empty state.
| Prop | Type | Default | Description |
|---|---|---|---|
rows | T[] | Required | The data to render. |
columns | TableListColumn<T>[] | Required | Column definitions with key, header, cell, optional mobileCell, slot and align. |
getKey | (row: T, index: number) => React.Key | (_, index) => index | Returns a unique key for a row. Defaults to the index. |
title | React.ReactNode | - | Heading shown above the list. |
emptyText | React.ReactNode | "No results." | Content shown when rows is empty. Defaults to No results.. |
onRowPress | (row: T, index: number) => void | - | Called with the row and index when a row is pressed. |
Also accepts the props of ViewProps.
Accessibility
- The group has the
listrole; rows have thelistitemrole, orbuttonwhenonRowPressis set. TableListTitleandTableListHeaderhave theheadingrole.- Separators are hidden from screen readers.
Notes
- Rows use
bg-mutedandopacity-80when pressed. - The
headerandaligncolumn fields are not rendered by the list layout.

