Naar inhoud

Tabel

Een semantische HTML-tabel voor facturen, administratieve lijsten en prijslijsten — rijen met randen, vetgedrukte kopteksten en een strakke, neobrutalistische schaduw.

import {
  Table,
  TableBody,

De table stylet de native HTML-tabelelementen — <table>, <thead>, <tbody>, <th>, <td>, <caption> — zonder primitive-bibliotheek eronder; de Radix- en Base-varianten leveren hetzelfde bestand. Het neobrutalistische recept: een dikke rand en harde schaduw rond de hele tabel, koptekstcellen in het koppenlettertype en rijscheidingen van 2px.

Ideaal voor:

  • Facturen en bestellingen — regelitems met een TableFooter-rij voor het totaal.
  • Beheerlijsten — gebruikers, API-sleutels, abonnementen, met een dropdown met rijacties.
  • Prijs- en vergelijkingstabellen — featurematrices waarin de kolomkoppen de betekenis dragen.

Installatie

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/table.json
npx shadcn@latest add https://neobrutalism.com/r/base/table.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/table.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/table.json

Kopieer en plak de volgende code in je project.

components/ui/table.tsx
"use client"

import * as React from "react"

import { cn } from "@/lib/utils"

function Table({ className, ...props }: React.ComponentProps<"table">) {
  return (
    <div
      data-slot="table-container"
      className="relative w-full overflow-x-auto rounded border-2 shadow-md"
    >
      <table
        data-slot="table"
        className={cn("w-full caption-bottom text-sm", className)}
        {...props}
      />
    </div>
  )
}

function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
  return (
    <thead
      data-slot="table-header"
      className={cn("[&_tr]:border-b-2", className)}
      {...props}
    />
  )
}

function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
  return (
    <tbody
      data-slot="table-body"
      className={cn("[&_tr:last-child]:border-0", className)}
      {...props}
    />
  )
}

function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
  return (
    <tfoot
      data-slot="table-footer"
      className={cn(
        "border-t-2 bg-muted/50 font-medium [&>tr]:last:border-b-0",
        className
      )}
      {...props}
    />
  )
}

function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
  return (
    <tr
      data-slot="table-row"
      className={cn(
        "border-b-2 transition-colors hover:bg-accent has-aria-expanded:bg-accent data-[state=selected]:bg-accent",
        className
      )}
      {...props}
    />
  )
}

function TableHead({ className, ...props }: React.ComponentProps<"th">) {
  return (
    <th
      data-slot="table-head"
      className={cn(
        "h-10 bg-muted px-2 text-left align-middle font-head font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
        className
      )}
      {...props}
    />
  )
}

function TableCell({ className, ...props }: React.ComponentProps<"td">) {
  return (
    <td
      data-slot="table-cell"
      className={cn(
        "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
        className
      )}
      {...props}
    />
  )
}

function TableCaption({
  className,
  ...props
}: React.ComponentProps<"caption">) {
  return (
    <caption
      data-slot="table-caption"
      className={cn("mt-4 text-sm text-muted-foreground", className)}
      {...props}
    />
  )
}

export {
  Table,
  TableHeader,
  TableBody,
  TableFooter,
  TableHead,
  TableRow,
  TableCell,
  TableCaption,
}

Werk de import-paden bij zodat ze overeenkomen met je projectconfiguratie.

Gebruik

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
<Table>
  <TableCaption>A list of your recent invoices.</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead className="w-[100px]">Invoice</TableHead>
      <TableHead>Status</TableHead>
      <TableHead>Method</TableHead>
      <TableHead className="text-right">Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell className="font-medium">INV001</TableCell>
      <TableCell>Paid</TableCell>
      <TableCell>Credit Card</TableCell>
      <TableCell className="text-right">$250.00</TableCell>
    </TableRow>
  </TableBody>
</Table>

Compositie

Gebruik de volgende compositie om een Table te bouwen:

Table
├── TableCaption
├── TableHeader
│   └── TableRow
│       ├── TableHead
│       ├── TableHead
│       ├── TableHead
│       └── TableHead
├── TableBody
│   ├── TableRow
│   │   ├── TableCell
│   │   ├── TableCell
│   │   ├── TableCell
│   │   └── TableCell
│   └── TableRow
│       ├── TableCell
│       ├── TableCell
│       ├── TableCell
│       └── TableCell
└── TableFooter

Voorbeelden

Tabelvoettekst

Gebruik de component <TableFooter /> om een voettekst aan de tabel toe te voegen.

import {
  Table,
  TableBody,

Acties

Een tabel die acties voor elke rij toont met behulp van een <DropdownMenu />-component.

import { MoreHorizontalIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

Data Table

Je kunt de component <Table /> gebruiken om complexere gegevenstabellen te bouwen. Combineer hem met @tanstack/react-table om tabellen met sorteren, filteren en paginering te maken.

Zie de documentatie van Data Table voor meer informatie.

Je kunt ook een voorbeeld van een gegevenstabel bekijken in de Tasks-demo.

RTL

Om RTL-ondersteuning in Neobrutalism in te schakelen, zie de RTL-configuratiegids.

"use client"

import * as React from "react"

Toegankelijkheid

Doordat native tabelelementen worden gerenderd, krijgen schermlezers tabelaankondiging, rij- en kolomnavigatie en kopkoppeling zonder enige ARIA-bedrading. Geef elke tabel een naam met TableCaption en reserveer TableHead voor echte koptekstcellen. De scrollcontainer is niet focusbaar, dus wie alleen een toetsenbord gebruikt, kan een overlopende tabel niet scrollen — verwacht je brede tabellen, voeg dan in jouw kopie van de component tabIndex={0}, role="region" en een aria-label toe aan de container-div.