HextaUI

Table: Pinned column

pinned="start" keeps the first column in view while the rest scrolls, and pinnedEdge shows a shadow once content slides under it.

TeamQ1 2025Q2 2025Q3 2025Q4 2025Q1 2026Q2 2026Q3 2026
Design systems12141518212224
Platform31303335343840
Growth891110121516
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const quarters = [
  "Q1 2025",
  "Q2 2025",
  "Q3 2025",
  "Q4 2025",
  "Q1 2026",
  "Q2 2026",
  "Q3 2026",
]

const teams = [
  { name: "Design systems", values: [12, 14, 15, 18, 21, 22, 24] },
  { name: "Platform", values: [31, 30, 33, 35, 34, 38, 40] },
  { name: "Growth", values: [8, 9, 11, 10, 12, 15, 16] },
]

export function TablePinned() {
  return (
    <Table variant="surface" className="w-max min-w-full">
      <TableHeader>
        <TableRow>
          <TableHead pinned="start" pinnedEdge>
            Team
          </TableHead>
          {quarters.map((quarter) => (
            <TableHead key={quarter} align="end">
              {quarter}
            </TableHead>
          ))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {teams.map((team) => (
          <TableRow key={team.name}>
            <TableHead scope="row" pinned="start" pinnedEdge>
              {team.name}
            </TableHead>
            {team.values.map((value, index) => (
              <TableCell key={quarters[index]} align="end">
                {value}
              </TableCell>
            ))}
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

This adds the example as components/examples/table/pinned.tsx, together with the Table component and the HextaUI theme tokens it needs.

pnpm dlx shadcn@latest add https://hextaui.com/r/table-pinned.json

To add only the component, follow the Table installation.

Props in this example

The Table props this example sets, from the API reference.

PropTypeDefault
variantsurface adds a rounded hairline frame and a muted header band.
"default" | "surface""default"
PropTypeDefault
scopeUse row for the cell that names a row. Inside the body it gets cell padding and foreground text.
"col" | "row"–
alignend also switches to tabular numbers so digits line up.
"start" | "center" | "end""start"
pinnedKeep the column in view while the table scrolls sideways. Set the same value on its header and every cell.
"start" | "end"–
pinnedEdgeDraw a soft shadow on the inner edge of the last pinned column while content is hidden behind it.
booleanfalse
PropTypeDefault
alignend also switches to tabular numbers so digits line up.
"start" | "center" | "end""start"

Every prop is in the Table API reference.

See them all, with keyboard support and accessibility notes, on the Table page.