Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsData

Table

A complete primitive set for tabular data — header, body, footer, sortable columns, sticky header, row states, plus cell helpers for avatars, status, currency amounts, and actions. Designed in the Wise / PrimeReact tradition.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import {
  TableRoot,
  TableHeader,
  TableBody,
  TableFooter,
  TableRow,
  TableHead,
  TableCell,
  TableCaption,
  TableEmpty,
  TableCellAvatar,
  TableCellAmount,
  TableCellStatus,
  TableCellActions,
} from "@tessinaui/ui";
<TableRoot variant="lined" hoverable>
  <TableHeader>
    <TableRow hoverable={false}>
      <TableHead sortable sortDirection="asc" onSort={handleSort("name")}>User</TableHead>
      <TableHead>Role</TableHead>
      <TableHead>Status</TableHead>
      <TableHead numeric>Amount</TableHead>
      <TableHead align="end" />
    </TableRow>
  </TableHeader>

  <TableBody>
    {users.map((u) => (
      <TableRow key={u.id}>
        <TableCell>
          <TableCellAvatar
            avatar={<Avatar size="sm" initials={initialsOf(u.name)} />}
            name={u.name}
            secondary={u.email}
          />
        </TableCell>
        <TableCell>{u.role}</TableCell>
        <TableCell>
          <TableCellStatus intent="success" label="Active" />
        </TableCell>
        <TableCell numeric>
          <TableCellAmount currency="$" amount={u.amount.toFixed(2)} />
        </TableCell>
        <TableCell align="end">
          <TableCellActions>
            <IconButton variant="ghost" size="xs" icon={<MoreHorizontal />} aria-label="Actions" />
          </TableCellActions>
        </TableCell>
      </TableRow>
    ))}
  </TableBody>
</TableRoot>

Showcase

When to use

Table is the workhorse for any structured tabular data — users, transactions, orders, audit logs, settings rows, etc. It's a primitive set: bring your own data fetching, pagination, and selection state, and Tessina handles the visual layer plus sorting indicators, sticky header, and the cell patterns that show up everywhere.

For a turnkey component with built-in filtering / pagination / selection, layer TanStack Table on top of these primitives — the styling will carry through unchanged.

API Reference

TableRoot props

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg" | "xl""md"Cell padding + text size
variant"lined" | "striped" | "bordered" | "borderless""lined"Visual treatment — lined is default, striped adds zebra rows, bordered adds vertical separators, borderless removes the container chrome
rounded"none" | "sm" | "md" | "lg" | "full""md"Container corner radius
intent"none" | "primary" | "error" | "warning" | "success" | "info""none"Subtle border accent on the container
dir"ltr" | "rtl""ltr"Text direction — flips alignment and sticky-column side
hoverablebooleantrueHighlight rows on hover
stickyHeaderbooleanfalseStick the header to the top of the scroll container
withContainerbooleantrueWrap the <table> in a TableContainer (you can disable to use your own)

TableContainer props

A standalone scroll container — useful if you need to wrap a table you didn't build with TableRoot.

PropTypeDefaultDescription
size, variant, rounded, intentsame as Root—Visual chrome
scrollablebooleantrueAdd horizontal overflow scrolling

TableHeader / TableBody / TableFooter

Semantic <thead> / <tbody> / <tfoot> wrappers. Header gets the muted background; footer gets the same styling for totals rows.

TableRow props

PropTypeDefaultDescription
selectedbooleanfalseHighlights the row in the primary tint
disabledbooleanfalseGreys out the row and disables pointer events
destructivebooleanfalseTints the row in error colour (e.g. flagged for deletion)
hoverablebooleaninheritedOverride the parent's hoverable setting for this row

TableHead props

PropTypeDefaultDescription
align"start" | "center" | "end""start"Text alignment
numericbooleanfalseRight-align with tabular numerals
sortablebooleanfalseShow a sort indicator and accept clicks to cycle
sortDirection"asc" | "desc" | "none""none"Current sort direction (controlled)
onSort(next: SortDirection) => void—Called when the user clicks the indicator. Receives the next direction in the cycle (none → asc → desc → none)
stickybooleanfalseStick this column to the start (left in LTR, right in RTL)
widthnumber | string—Column width hint

Sets aria-sort automatically when sortable is true.

TableCell props

Same align, numeric, sticky, width props as TableHead, plus truncate for ellipsis overflow.

TableEmpty props

PropTypeDefaultDescription
colSpannumberrequiredNumber of columns in the table — required so the cell spans correctly
iconReactNode—Optional icon shown above the message
titleReactNode—Bold title above the body text

Renders a single row with one cell that spans the table.

Cell helpers

These compose inside TableCell and cover the patterns that show up in nearly every product table.

TableCellAvatar

<TableCell>
  <TableCellAvatar
    avatar={<Avatar src={user.photo} initials={initialsOf(user.name)} />}
    name={user.name}
    secondary={user.email}
  />
</TableCell>
PropDescription
avatarSlot for any avatar component
namePrimary text (bold)
secondaryOptional second line (muted)

TableCellAmount

Right-aligns a currency amount with optional comparison delta (tinted by intent).

<TableCell numeric>
  <TableCellAmount
    currency="$"
    amount="1,240.50"
    delta="+12.4%"
    deltaIntent="success"
  />
</TableCell>
PropDescription
amountMain number (tabular numerals)
currencyOptional symbol or code shown before
deltaOptional comparison line below
deltaIntent"none" | "success" | "error"

TableCellStatus

Dot + label, in 6 intents (neutral, primary, error, warning, success, info).

<TableCell>
  <TableCellStatus intent="success" label="Active" />
</TableCell>

TableCellActions

A trailing-edge container for icon-button actions.

<TableCell align="end">
  <TableCellActions>
    <IconButton variant="ghost" size="xs" icon={<Pencil />} aria-label="Edit" />
    <IconButton variant="ghost" size="xs" icon={<Trash />} aria-label="Delete" />
  </TableCellActions>
</TableCell>

TableCellText

Two-line cell with primary + muted secondary.

<TableCell>
  <TableCellText primary="Wire transfer" secondary="ACH · 2 days" />
</TableCell>

Notes

  • The <table> element renders inside a TableContainer by default, which provides the rounded card chrome, intent border, and horizontal scroll for narrow viewports. Pass withContainer={false} if you want to nest the table inside your own container (e.g. a Card).
  • aria-sort="ascending" | "descending" | "none" is set automatically on sortable headers.
  • For huge datasets, virtualize the body with TanStack Virtual or a similar library — the primitives don't impose any virtualization but compose naturally with one.
  • For RTL: alignment, sortable indicators, and sticky-column side all flip via the dir prop. Numbers and currency stay LTR-formatted (which is the typographic norm even in Arabic-script copy).

Scroll Area

A scrollable container with custom overlay scrollbars that do not steal layout space. Supports vertical, horizontal, and both-axis content with a neutral branded thumb, RTL, and a compound API for full control.

ChatBubble

AI chat message bubbles with role-aware alignment, streaming state, action buttons, and RTL support.

On this page

PlaygroundInstallationUsageShowcaseWhen to useAPI ReferenceTableRoot propsTableContainer propsTableHeader / TableBody / TableFooterTableRow propsTableHead propsTableCell propsTableEmpty propsCell helpersTableCellAvatarTableCellAmountTableCellStatusTableCellActionsTableCellTextNotes