Table
A foundational table component built with semantic HTML elements, providing the building blocks for displaying structured data in rows and columns.
Features
- Semantic HTML - Uses proper table elements for accessibility
- Responsive container - Horizontal scrolling on smaller screens
- Flexible styling - Customizable classes for headers, cells, and rows
- Selection support - Built-in checkbox styling and states
- Hover effects - Visual feedback on row interaction
Installation
pnpm add @helgadigitals/vera-uinpm install @helgadigitals/vera-uiyarn add @helgadigitals/vera-uiUsage
Basic Table
| Name | Role | |
|---|---|---|
| John Doe | john@example.com | Admin |
| Jane Smith | jane@example.com | User |
| Bob Johnson | bob@example.com | Editor |
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow,} from "@helgadigitals/vera-ui";import { useState } from "react";function BasicTableExample() { const users = [ { name: "John Doe", email: "john@example.com", role: "Admin" }, { name: "Jane Smith", email: "jane@example.com", role: "User" }, { name: "Bob Johnson", email: "bob@example.com", role: "Editor" }, ]; return ( <Table> <TableHeader> <TableRow> <TableHead>Name</TableHead> <TableHead>Email</TableHead> <TableHead>Role</TableHead> </TableRow> </TableHeader> <TableBody> {users.map((user, index) => ( <TableRow key={index}> <TableCell>{user.name}</TableCell> <TableCell>{user.email}</TableCell> <TableCell>{user.role}</TableCell> </TableRow> ))} </TableBody> </Table> );}Selectable Table
| Name | Price | Status | |
|---|---|---|---|
| Product A | $99.99 | Active | |
| Product B | $149.99 | Inactive | |
| Product C | $79.99 | Active |
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow,} from "@helgadigitals/vera-ui";import { useState } from "react";function SelectableTableExample() { const [selectedRows, setSelectedRows] = useState<number[]>([]); const data = [ { id: 1, name: "Product A", price: 99.99, status: "Active" }, { id: 2, name: "Product B", price: 149.99, status: "Inactive" }, { id: 3, name: "Product C", price: 79.99, status: "Active" }, ]; const handleSelectRow = (id: number) => { setSelectedRows(prev => prev.includes(id) ? prev.filter(rowId => rowId !== id) : [...prev, id] ); }; const handleSelectAll = () => { setSelectedRows( selectedRows.length === data.length ? [] : data.map(item => item.id) ); }; return ( <Table> <TableHeader> <TableRow> <TableHead className="w-12"> <input type="checkbox" checked={selectedRows.length === data.length} onChange={handleSelectAll} className="rounded" aria-label="Select all rows" /> </TableHead> <TableHead>Name</TableHead> <TableHead>Price</TableHead> <TableHead>Status</TableHead> </TableRow> </TableHeader> <TableBody> {data.map((item) => ( <TableRow key={item.id} data-state={selectedRows.includes(item.id) ? "selected" : undefined} > <TableCell> <input type="checkbox" checked={selectedRows.includes(item.id)} onChange={() => handleSelectRow(item.id)} className="rounded" aria-label={`Select ${item.name}`} /> </TableCell> <TableCell>{item.name}</TableCell> <TableCell>${item.price}</TableCell> <TableCell> <span className={`px-2 py-1 rounded-full text-xs ${ item.status === 'Active' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' }`}> {item.status} </span> </TableCell> </TableRow> ))} </TableBody> </Table> );}Table with Footer
| Invoice | Status | Amount |
|---|---|---|
| INV001 | Paid | $250.00 |
| INV002 | Pending | $150.00 |
| INV003 | Unpaid | $350.00 |
| INV004 | Paid | $450.00 |
| Total | $1200.00 | |
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow,} from "@helgadigitals/vera-ui";import { useState } from "react";function TableWithFooterExample() { const invoices = [ { invoice: "INV001", paymentStatus: "Paid", totalAmount: 250.00 }, { invoice: "INV002", paymentStatus: "Pending", totalAmount: 150.00 }, { invoice: "INV003", paymentStatus: "Unpaid", totalAmount: 350.00 }, { invoice: "INV004", paymentStatus: "Paid", totalAmount: 450.00 }, ]; const total = invoices.reduce((sum, invoice) => sum + invoice.totalAmount, 0); return ( <Table> <TableHeader> <TableRow> <TableHead className="w-[100px]">Invoice</TableHead> <TableHead>Status</TableHead> <TableHead className="text-right">Amount</TableHead> </TableRow> </TableHeader> <TableBody> {invoices.map((invoice) => ( <TableRow key={invoice.invoice}> <TableCell className="font-medium">{invoice.invoice}</TableCell> <TableCell>{invoice.paymentStatus}</TableCell> <TableCell className="text-right">${invoice.totalAmount.toFixed(2)}</TableCell> </TableRow> ))} </TableBody> <TableFooter> <TableRow> <TableCell colSpan={2}>Total</TableCell> <TableCell className="text-right">${total.toFixed(2)}</TableCell> </TableRow> </TableFooter> </Table> );}Table with Caption
| Customer | Amount | |
|---|---|---|
| Liam Johnson | liam@example.com | $250.00 |
| Olivia Smith | olivia@example.com | $150.00 |
| Noah Williams | noah@example.com | $350.00 |
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow,} from "@helgadigitals/vera-ui";import { useState } from "react";function TableWithCaptionExample() { const recentSales = [ { customer: "Liam Johnson", email: "liam@example.com", amount: 250.00 }, { customer: "Olivia Smith", email: "olivia@example.com", amount: 150.00 }, { customer: "Noah Williams", email: "noah@example.com", amount: 350.00 }, ]; return ( <Table> <TableCaption>A list of your recent sales.</TableCaption> <TableHeader> <TableRow> <TableHead>Customer</TableHead> <TableHead>Email</TableHead> <TableHead className="text-right">Amount</TableHead> </TableRow> </TableHeader> <TableBody> {recentSales.map((sale, index) => ( <TableRow key={index}> <TableCell className="font-medium">{sale.customer}</TableCell> <TableCell>{sale.email}</TableCell> <TableCell className="text-right">${sale.amount.toFixed(2)}</TableCell> </TableRow> ))} </TableBody> </Table> );}API Reference
Table
The main table container with responsive overflow handling.
Prop
Type
TableHeader
Table header section containing column headers.
Prop
Type
TableBody
Table body section containing data rows.
Prop
Type
TableFooter
Table footer section for summary information.
Prop
Type
TableRow
Individual table row element.
Prop
Type
TableHead
Header cell element with appropriate styling.
Prop
Type
TableCell
Data cell element for table content.
Prop
Type
TableCaption
Table caption for describing the table content.
Prop
Type
Use Cases
Data Presentation
- Simple lists - Product catalogs, user directories
- Financial reports - Invoices, transaction history
- Comparison tables - Feature matrices, pricing tables
Administrative Interfaces
- User management - List users with roles and permissions
- Content management - Articles, posts with metadata
- System logs - Event listings with timestamps
Dashboard Components
- Recent activity - Latest actions or updates
- Summary tables - Key metrics and statistics
- Status overviews - System health, task progress
E-commerce
- Product listings - Inventory with prices and stock
- Order history - Customer purchase records
- Shopping carts - Item lists with quantities
Accessibility
The Table component includes:
- Semantic HTML - Proper table structure for screen readers
- ARIA attributes - Enhanced accessibility information
- Keyboard navigation - Tab through interactive elements
- Selection states - Clear indication of selected rows
- Focus management - Visible focus indicators
Best Practices
Structure
- Use
TableHeaderfor column headers - Group data in
TableBody - Add summaries in
TableFooter - Include
TableCaptionfor context
Styling
- Apply consistent alignment (left, center, right)
- Use appropriate column widths
- Highlight selected or active rows
- Provide visual feedback on hover
Performance
- Consider virtualization for large datasets
- Use the DataTable component for advanced features
- Implement proper loading states
- Handle empty states gracefully
Responsive Design
- Allow horizontal scrolling on mobile
- Consider hiding non-essential columns
- Stack information vertically when needed
- Maintain touch-friendly targets
Related Components
- DataTable - Advanced table with sorting, filtering, and pagination
- Card - Alternative layout for displaying structured data
- Badge - Status indicators for table cells
- Pagination - Navigate through large datasets
Tabs Container
An enhanced tabbed interface component that provides advanced features like URL persistence, scrollable navigation, and improved accessibility. Perfect for organizing complex content with multiple views.
Toast
A succinct message that is displayed temporarily to provide feedback about an action result. Built on top of [Sonner](https://sonner.emilkowal.ski/) for an excellent toast experience.