Skip to main content

Component Architecture

Table Primitives

All tables use styled HTML primitives from @/components/ui/Table.tsx. These replace HeroUI's <Table> component which used a rigid React Aria collection system that enforced cell counts at the element level, breaking fragment-based row composition.

Available Components

ComponentElementPurpose
TableWrapper<div>Glass card wrapper with border, blur, shadow, rounded corners
Table<table>Base table with border-collapse, optional fixed layout
TableHead<thead>Header section (transparent row backgrounds)
TableBody<tbody>Body section
TableFooter<tfoot>Footer section
TableRow<tr>Row with hover state and divider border
TableHeaderCell<th>Sticky, glassy header cell with sort indicator support
TableCell<td>Data cell with compact and truncate options
TableLoading<tr>Full-width loading spinner row
TableEmpty<tr>Full-width empty state row

Usage

import {
TableWrapper,
Table,
TableHead,
TableBody,
TableRow,
TableHeaderCell,
TableCell,
} from '@/components/ui/Table';

<TableWrapper>
<Table aria-label="Example">
<TableHead>
<TableRow>
<TableHeaderCell sortable sorted="asc" onSort={handleSort}>
Name
</TableHeaderCell>
<TableHeaderCell>Status</TableHeaderCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>Arthas</TableCell>
<TableCell>Active</TableCell>
</TableRow>
</TableBody>
</Table>
</TableWrapper>;

Sticky Headers + Horizontal Scroll

Both work when the scroll container uses overflow: auto in both directions. The <th> elements use position: sticky; top: 0 within that same scroll context.

<div className="h-[500px] overflow-auto">
<Table>
<TableHead>...</TableHead>
<TableBody>...</TableBody>
</Table>
</div>

Do not put overflow-x-hidden or separate overflow wrappers between the sticky headers and the scroll container.

Handling Wide Content

  • <Table fixed>table-fixed layout constrains columns to available width. Set widths on <th> with className="w-[200px]".
  • <TableCell truncate> — clips text with ellipsis via text-overflow: ellipsis.
  • Responsive hiding — use className="hidden md:table-cell" on both <th> and <td> to hide columns on small screens.

Fragment Row Components

Unlike HeroUI's collection system, plain HTML tables support fragment-based row components:

function MemberRow({ member }) {
return (
<>
<TableCell>{member.name}</TableCell>
<TableCell>{member.role}</TableCell>
</>
);
}

// Works fine — fragments flatten into the <tr>
<TableRow>
<MemberRow member={m} />
</TableRow>;

Styling

Header cells use HeroUI theme tokens for visual consistency:

  • Background: bg-default-100/50 with backdrop-blur-md backdrop-saturate-150
  • Text: text-foreground-500 text-tiny font-semibold uppercase
  • Corners: first:rounded-l-lg last:rounded-r-lg

TableWrapper provides the glass card look: backdrop-blur-xl bg-content1/70 border-divider/80.

TanStack Table

@tanstack/react-table is installed for headless table logic (client-side sorting, filtering, pagination). The styled primitives handle rendering while TanStack handles data.