Skip to main content

Table

A fully accessible, theme-aware, and sortable table component for displaying structured data in a clean and responsive way.


Usage

Basic usage

import { Table } from '@nofinite/nui';

const columns = [
{ key: 'name', label: 'Name', sortable: true },
{ key: 'age', label: 'Age', sortable: true },
{ key: 'role', label: 'Role' },
] as const;

const data = [
{ name: 'Sam', age: 21, role: 'Engineer' },
{ name: 'John', age: 30, role: 'Manager' },
{ name: 'Dev', age: 25, role: 'Designer' },
];

<Table columns={columns} data={data} />;

With typical interaction

<Table
columns={columns}
data={data}
emptyText="No employees found"
className="custom-table"
/>

Variants

Table supports sortable and non-sortable columns.

<Table columns={columns} data={data} />
<Table columns={columns} data={data} /> // all non-sortable columns

Available variants:

  • sortable – Columns can be clicked to sort data ascending/descending.
  • non-sortable – Static columns without sorting functionality.

Guidelines:

  • Use sortable columns for data where order matters.
  • Use non-sortable for static or categorical data.

Sizes

Table does not have size variants, but column widths adjust automatically to content. Use CSS for further customization.

<Table className="w-full" columns={columns} data={data} />

States

<Table columns={columns} data={[]} emptyText="No records" />
  • empty – Displays a message when there is no data.
  • hover – Row highlights on hover for better visibility.
  • sorted – Visual indication for sorted columns with ascending/descending arrows.

Native Props / Composition

<Table className="my-custom-table" data-testid="employee-table">
{/* content rendered via columns/data */}
</Table>

Supports className for custom styling, and any additional native div or table props can be forwarded as needed.


Props

PropTypeDefaultDescription
columnsTableColumn<T>[]Column definitions including key, label, sortable
dataT[]Array of objects representing table rows
emptyTextstring"No data available"Message shown when there is no data
classNamestring""Additional CSS classes for the table

Column props (TableColumn<T>):

PropTypeDefaultDescription
keykeyof TProperty key in the data object
labelstringColumn header text
sortablebooleanfalseWhether the column supports sorting

Behavior Notes

  • Clicking a sortable column cycles through ascending → descending → unsorted.
  • Sorting is applied client-side and does not mutate the original data array.
  • Non-sortable columns ignore clicks.
  • Table supports reduced motion preferences for accessibility.
<Table columns={columns} data={data} />

Accessibility

  • Renders as a semantic <table> with <thead> and <tbody>.
  • Sort buttons are focusable and accessible via keyboard.
  • aria-sort is implicitly indicated via visual arrow indicators.
  • Empty state uses a single cell spanning all columns for screen reader clarity.
<Table columns={columns} data={[]} aria-label="Employee Table" />

Layout

  • Full-width by default, scrollable horizontally on overflow.
  • Rows highlight on hover.
  • Use className or custom CSS for further layout adjustments.
<Table className="w-full" columns={columns} data={data} />

Best Practices

Do

  • Use sortable columns for numeric or date data.
  • Provide meaningful emptyText for better UX.
  • Customize styles with className as needed.

Don’t

  • Overload with too many columns; keep tables readable.
  • Use Table for non-tabular layouts.
  • Hide important data in unsortable columns without clear labels.