Table

free

Table gives dense records a scannable grid you compose from styled row and cell primitives.

MemberRoleStatus
Aria Patel
Aria Patel
aria@acme.io
OwnerActive
Diego Ramos
Diego Ramos
diego@acme.io
AdminActive
Mei Lin
Mei Lin
mei@acme.io
EditorInvited
Sam Turner
Sam Turner
sam@acme.io
ViewerActive
import Table from '@/components/ui/table';
import Avatar from '@/components/ui/avatar';
import Tag from '@/components/ui/tag';

Installation

Add this component with the NateUI CLI.

npx nateui@latest add Table

Examples

Basic

InvoiceClientAmount
INV-1024Northwind Traders$1,280.00
INV-1025Globex Corp$3,540.00
INV-1026Soylent Industries$920.00
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td } = Table;

Compact

SKUProductIn stock
KB-01Mechanical Keyboard132
MS-04Wireless Mouse58
HS-02Studio Headset9
WC-06HD Webcam0
DK-03Docking Station24
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td } = Table;

Bordered

ProjectLeadProgress
Website relaunchAria Patel80%
Mobile app v2Diego Ramos45%
Billing migrationMei Lin12%
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td } = Table;

Vertical Divider

RegionDealsRevenue
North America42$128k
Europe31$96k
Asia Pacific27$74k
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td } = Table;

Grouped Header

RepMeetingsOutcomes
Q1Q2WonLost
Aria Patel2431124
Diego Ramos182297
Mei Lin3027153
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td } = Table;

Sorting

ORD-3014$9607
ORD-3012$4203
ORD-3015$2752
ORD-3013$1801
import { useState } from 'react';
import Table from '@/components/ui/table';

const { THead, TBody, Tr, Th, Td, Sorter } = Table;

Filtering

NameTeam
Aria PatelDesign
Diego RamosEngineering
Mei LinEngineering
Sam TurnerSupport
Priya ShahDesign
import { useState } from 'react';
import Table from '@/components/ui/table';
import Input from '@/components/ui/input';

Row Selection

FileSize
Q3-report.pdf2.4 MB
brand-assets.zip18 MB
roadmap.png640 KB
contract.docx82 KB
import { useState } from 'react';
import Table from '@/components/ui/table';
import Checkbox from '@/components/ui/checkbox';

Pagination

ReferenceAmount
TXN-5000$42.00
TXN-5001$79.00
TXN-5002$116.00
TXN-5003$153.00
TXN-5004$190.00
23 transactions
import { useState } from 'react';
import Table from '@/components/ui/table';
import Pagination from '@/components/ui/pagination';

Expandable Rows

ShipmentCarrierStatus
SHP-01FedExIn transit
  • Picked up - Austin, TX
  • Departed - Memphis, TN
SHP-02UPSDelivered
SHP-03DHLPending
import { Fragment, useState } from 'react';
import Table from '@/components/ui/table';
import { PiCaretRight } from 'react-icons/pi'

TanStack Table

Ticket
Subject
Priority
Updated
TCK-201Checkout button unresponsiveHigh2h ago
TCK-198Export CSV missing a columnMedium5h ago
TCK-195Typo in confirmation emailLow1d ago
TCK-190Slow load on reports pageMedium2d ago
TCK-187Dark mode toggle resets on reloadMedium3d ago
    import { useMemo, useState } from 'react';
    import {
      columnVisibilityFeature,
      createPaginatedRowModel,

    API

    Table is a compound component: the default export is the styling wrapper, and the section, row, and cell primitives hang off it as Table.THead, Table.TBody, Table.TFoot, Table.Tr, Table.Th, Table.Td, and Table.Sorter. Each primitive renders its matching native element and forwards native props, so you own the data and behavior yourself.

    Table

    PropDescriptionTypeDefault
    borderedWrap the table or overflow renderer in a bordered card surface.booleanfalse
    compactReduce cell padding for dense data.booleanfalse
    hoverableHighlight body rows on hover.booleantrue
    overflowWrap the table in an overflow container. Uses the native overflow wrapper unless renderOverflow is supplied.booleantrue
    overflowClassExtra classes for the default overflow container.string-
    renderOverflowRenders a custom overflow container around the table when overflow is enabled. The result is placed inside the bordered surface when bordered is enabled.(table: ReactNode) => ReactNode-
    verticalDividerShow vertical column dividers per section.TableVerticalDivider{ head: false, body: false, footer: false }
    asElementRender the table as a different element, for example a flex layout.ElementType'table'
    ...nativePropsNative table element props.ComponentPropsWithRef<'table'>-

    Table.THead / Table.TBody / Table.TFoot

    PropDescriptionTypeDefault
    asElementRender the section as a different element.ElementType'thead' / 'tbody' / 'tfoot'
    ...nativePropsNative section element props.ComponentPropsWithRef<'thead'>-

    Table.Tr

    PropDescriptionTypeDefault
    asElementRender the row as a different element.ElementType'tr'
    ...nativePropsNative tr props, including className for selected or active rows.ComponentPropsWithRef<'tr'>-

    Table.Th / Table.Td

    PropDescriptionTypeDefault
    asElementRender the cell as a different element.ElementType'th' / 'td'
    ...nativePropsNative cell props, including colSpan, rowSpan, and className.ComponentPropsWithRef<'th'>-

    Table.Sorter

    PropDescriptionTypeDefault
    sortCurrent sort direction. true shows the neutral indicator; 'asc' and 'desc' show the active arrows.boolean | 'asc' | 'desc'-
    classNameExtra classes for the sorter wrapper.string-

    Types

    type TableVerticalDivider = {
      head?: boolean
      body?: boolean
      footer?: boolean
    }