Table
A responsive table component for displaying tabular data. Perfect for dashboards, admin panels, and data management in React applications with Next.js, TypeScript, and Tailwind CSS.
You know how tables can either make your data crystal clear or turn into an unreadable mess? The right table structure makes complex information digestible, while poor tables just frustrate users trying to find what they need.
Basic data display
Clean table for invoices or similar data:
Simple semantic HTML table with proper structure - caption, header, body, and footer. This free open source React component gives you all the building blocks for accessible data presentation.
npx shadcn@latest add table
Why structured tables matter
Tables aren't just grids - they're about making data relationships clear:
- Visual hierarchy - Headers, rows, and cells create natural reading patterns
- Comparison support - Users can quickly scan columns to compare values
- Accessibility built-in - Screen readers understand table structure
- Mobile adaptable - Can transform into cards or lists for small screens
- Sorting context - Natural place for interactive data controls
- Semantic meaning - HTML table elements convey data relationships
Real-world table patterns
Interactive data table
Full-featured table with sorting, filtering, and pagination:
Mobile-responsive design
Table that transforms to cards on smaller screens:
These examples show tables doing real work - managing payments, displaying orders, handling large datasets. Each pattern solves specific user needs for data interaction.
Perfect for data management
Tables work best when data has clear relationships between columns and rows. Admin dashboards, financial reports, user lists, inventory management, analytics displays. Much better than trying to squeeze structured data into cards or lists.
Built with semantic HTML table elements. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
Advanced data tables
For complex data operations, combine the basic Table with TanStack Table:
import {
useReactTable,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
getFilteredRowModel,
} from "@tanstack/react-table"
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
})
This gives you enterprise-level features:
- Column sorting - Click headers to sort by any field
- Global filtering - Search across all table data
- Column filtering - Filter by specific field values
- Pagination - Handle large datasets efficiently
- Server-side operations - Connect to APIs for dynamic data
- Custom cell rendering - Status badges, actions, formatting
- Row selection - Bulk operations and data management
API Reference
Table Components
The table is built from semantic HTML elements:
Component | Element | Description |
---|---|---|
Table | <table> | Root table container |
TableHeader | <thead> | Table header section |
TableBody | <tbody> | Table body with data rows |
TableFooter | <tfoot> | Table footer section |
TableRow | <tr> | Individual table row |
TableHead | <th> | Header cell with semantic meaning |
TableCell | <td> | Data cell containing content |
TableCaption | <caption> | Table description for accessibility |
Component Props
All table components accept standard HTML attributes plus:
Prop | Type | Description |
---|---|---|
className | string | Additional CSS classes |
children | ReactNode | Table content |
Table Structure
Proper table markup follows this pattern:
<Table>
<TableCaption>Description of table contents</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Column 1</TableHead>
<TableHead>Column 2</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Data 1</TableCell>
<TableCell>Data 2</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
<TableCell>Summary 1</TableCell>
<TableCell>Summary 2</TableCell>
</TableRow>
</TableFooter>
</Table>
TanStack Table Integration
For advanced features, use TanStack Table with our components:
// Column definition
const columns: ColumnDef<Data>[] = [
{
accessorKey: "email",
header: "Email",
cell: ({ row }) => row.getValue("email"),
},
{
accessorKey: "amount",
header: ({ column }) => (
<Button onClick={() => column.toggleSorting()}>
Amount
</Button>
),
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
return <div>${amount.toFixed(2)}</div>
},
},
]
// Table rendering
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
Accessibility Features
Built-in accessibility support includes:
- Semantic structure - Proper table, header, body, cell relationships
- Caption support - TableCaption describes table purpose
- Header associations - Screen readers connect data to headers
- Keyboard navigation - Tab through cells naturally
- Focus management - Clear focus indicators for interactive elements
- ARIA attributes - Additional context for complex tables
- Responsive text - Content remains readable at different sizes
Common Table Patterns
Status indicators with badges
<TableCell>
<Badge variant={status === "paid" ? "default" : "secondary"}>
{status}
</Badge>
</TableCell>
Numeric alignment
<TableHead className="text-right">Amount</TableHead>
<TableCell className="text-right">$299.99</TableCell>
Fixed column widths
<TableHead className="w-[100px]">ID</TableHead>
<TableHead className="w-[200px]">Name</TableHead>
Action buttons
<TableCell>
<Button variant="ghost" size="sm">
Edit
</Button>
</TableCell>
Design guidelines for tables
Keep these principles in mind when building data tables:
- Use captions - Always describe what the table contains
- Align consistently - Numbers right, text left, maintain alignment
- Group related data - Logical column ordering helps comprehension
- Show relationships - Related columns should be visually connected
- Handle empty states - Show helpful message when no data
- Consider mobile - Tables become hard to read on small screens
- Test with real data - Long text, missing values, edge cases
- Performance matters - Virtual scrolling for large datasets
- Sort thoughtfully - Default to most useful sort order
- Filter clearly - Make active filters obvious to users
Switch
A control that allows users to toggle between checked and not checked states. Perfect for settings, preferences, and feature toggles in React applications with Next.js, TypeScript, and Tailwind CSS.
Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time. Perfect for organizing complex interfaces in React applications with Next.js, TypeScript, and Tailwind CSS.