- Accordion
- Avatar
- Badge
- Breadcrumb
- Button
- Calendar
- ChatContainer
- ChatInput
- ChatMessage
- ChatMultiChoiceQuestion
- ChatMultiOptionQuestion
- ChatThinking
- Checkbox
- Combobox
- Container
- CurrencyInput
- DistributionSlider
- Drawer
- Dropdown
- FilePicker
- Grid
- Heading
- Image
- Input
- InputGroup
- Label
- Logo
- MapPin
- Markdown
- Modal
- NativeSelect
- NumberInput
- OptionSlider
- OtpInput
- PhoneInput
- Popover
- Progress
- PropertyCalendar
- RadioGroup
- RadioGroupCards
- ResponsiveModal
- ScrollArea
- SearchBar
- SearchBarFallback
- SearchInput
- Select
- Separator
- Spinner
- Switch
- Table
- Tabs
- Text
- Textarea
- TimePicker
- Toast
- Toggle
- ToggleCard
- ToggleGroup
- Toolbar
- Tooltip
Table
Responsive semantic table primitives for structured data and rich states
pnpm add @wandercom/design-system-web
Compose the table primitives directly. TableContainer adds horizontal
overflow on small screens while Table stays a plain semantic table that is
easy to use with server rendering or a virtualized data layer.
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableHeader,
TableRow,
} from '@wandercom/design-system-web/ui/table';
export function ReservationsTable({ reservations }) {
return (
<TableContainer>
<Table className="min-w-[720px]">
<TableHeader>
<TableRow className="h-10">
<TableHead>Property</TableHead>
<TableHead>Customer</TableHead>
<TableHead>Date</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{reservations.map((reservation) => (
<TableRow interactive key={reservation.id}>
<TableCell>{reservation.property}</TableCell>
<TableCell>{reservation.customer}</TableCell>
<TableCell>{reservation.dates}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}Table cells accept any content, including image-and-label pairs, badges, and two-line values.
Use TableState inside TableBody to preserve the header while centering an
empty, loading, or permissions state across the table columns.
Override contentClassName when a state needs additional vertical room for
actions or a longer message.
Table ships without a data engine, state, effects, or client-only directive.
For ordinary datasets, map rows directly as shown above. For very long
datasets, use these primitives as the styled markup emitted by TanStack Table
and a virtualizer such as react-virtuoso; TableContainer is intentionally
separate so a virtualizer can own its scroll parent.
Keep a readable minimum table width and place it in TableContainer for
horizontal touch scrolling on narrow layouts:
<TableContainer>
<Table className="min-w-[720px]">{/* columns and rows */}</Table>
</TableContainer>