Table
Table is the styled semantic primitive; DataTable adds client-side search, sorting, and pagination on top.
Basic table
Borderless, with footer
DataTable: search, sort, and pagination
- Search and page-size are ordinary component state; DataTable just receives the filtered rows
- The empty state renders when data is empty; emptyMessage sets its text (default "No results."). Search for a name that is not listed to see it
Infinite loading instead of pagination
Appends the next page as the table's end comes into view. pageSize is set to the number of rows fetched so far, since infinite loading is what replaces the pager.
- Keep the scroll container bounded (max-h) so there is something to scroll
When to use
- Table: any tabular data with a fixed, known row set - a summary, a static report, a small list.
- DataTable: the same tabular data plus client-side search, column sorting, and pagination without hand-wiring any of it.
When not to use
- Server-side pagination/sorting over a large dataset - DataTable's search/sort/pagination are all client-side over the rows you pass it; wire your own controls to a server query for large datasets instead.
- Non-tabular grouped content - List or DescriptionList usually reads better than forcing rows/columns.
Keyboard
Mobile behavior
- The table wrapper scrolls horizontally (overflow-x-auto) rather than reflowing columns, so wide tables stay readable instead of squeezing every column.
- DataTable's search/page-size controls stack above the table and remain fully usable at phone widths.
Accessibility notes
- Renders real <table>/<thead>/<tbody>/<th>/<td> elements, so assistive tech gets native table semantics for free - no ARIA table role reimplementation.
- Table.Row's interactive mode adds a roving tabIndex and Enter/Space activation only when paired with onClick, so plain display rows never pick up unwanted focus stops.
Common mistakes
- Making every row interactive/clickable when only a few need it - it adds unnecessary Tab stops for rows with no action.
- Passing thousands of rows straight into DataTable and expecting virtualization - it's a client-paginated table, not a virtualized grid.
Known limitations
- No column resizing, reordering, or row virtualization - DataTable covers search/sort/pagination only.
Related components
API reference
Wraps the table in a bordered panel. Defaults to on - pass `false` for a borderless table.
Also accepts everything from React.TableHTMLAttributes<HTMLTableElement>.
Table.Row props
Hover/click row; with `onClick`, also Enter/Space-activatable. Defaults to off. **Not the accessible affordance:** a `<tr>` has no activatable role/name; put the real action in a cell.
Also accepts everything from React.HTMLAttributes<HTMLTableRowElement>.
DataTable props
Column definitions, in display order.
Every row. Sorting and paging happen here, not in the consumer.
Stable React key per row - an id, not the array index.
Draws the table's cell borders.
Shown in place of the rows when `data` is empty.
Shows skeleton rows instead of data - for async loads.
Rows per page. Wrapping the table in `InfiniteScroll` instead? Set this to the number of rows fetched so far, so nothing is paged out of view.
Also accepts everything from React.HTMLAttributes<HTMLDivElement>.
Coding agents read this reference, with its examples, from the version your project has installed, through the Fuji UI MCP server. Set up your agent
