Skip to content

Simple Table

Server-safe static table: uppercase caption, ink header row with column rules, zebra rows, right-aligned mono numeric columns and an optional yellow totals footer.

brutalist/ui/simple-table
Open ↗

Source

import type { ReactNode } from "react";
import { cn } from "@/lib/utils";

export interface SimpleTableProps {
  caption: string;
  headers: string[];
  rows: ReactNode[][];
  /** Column indexes aligned right (numbers). */
  numeric?: number[];
  /** Zebra striping. */
  striped?: boolean;
  footer?: ReactNode[];
  className?: string;
}

export function SimpleTable({ caption, headers, rows, numeric = [], striped = true, footer, className }: SimpleTableProps) {
  const align = (i: number) => (numeric.includes(i) ? "text-right tabular-nums" : "text-left");
  return (
    <div className={cn("da-stroke overflow-x-auto bg-da-surface text-da-surface-fg shadow-da-md", className)}>
      <table className="w-full border-collapse text-sm">
        <caption className="da-stroke-b px-4 py-3 text-left font-da-display text-lg tracking-da-display uppercase">{caption}</caption>
        <thead>
          <tr className="da-stroke-b bg-da-fg text-da-bg">
            {headers.map((h, i) => (
              <th key={h} scope="col" className={cn("px-4 py-2.5 font-da-mono text-[11px] font-bold tracking-da-label uppercase", i > 0 && "border-l-[length:var(--da-border-width)] border-current", align(i))}>
                {h}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((r, ri) => (
            <tr key={ri} className={cn("[&+tr]:da-stroke-t", striped && ri % 2 === 1 && "bg-da-surface-2")}>
              {r.map((c, ci) => (
                <td key={ci} className={cn("px-4 py-3", ci > 0 && "da-stroke-l", ci === 0 && "font-bold", numeric.includes(ci) && "font-da-mono", align(ci))}>
                  {c}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
        {footer && (
          <tfoot>
            <tr className="da-stroke-t bg-da-primary text-da-primary-fg">
              {footer.map((c, ci) => (
                <td key={ci} className={cn("px-4 py-3 font-bold", ci > 0 && "da-stroke-l", numeric.includes(ci) && "font-da-mono", align(ci))}>
                  {c}
                </td>
              ))}
            </tr>
          </tfoot>
        )}
      </table>
    </div>
  );
}

export default SimpleTable;

modules/brutalist/ui/simple-table/index.tsx

Props

PropTypeDefaultDescription
caption*string—Visible caption.
headers*string[]—Column headers.
rows*ReactNode[][]—Cells per row.
numericnumber[]—Right-aligned mono columns.
stripedbooleantrueZebra rows.
footerReactNode[]—Totals row.
classNamestring—Classes on the wrapper.

Other table variants in Brutalist

Table in other art directions

Action Items Table

Action items table with Open / Done / All filter pills and counts, gradient checkboxes that strike tasks through, owner, due chip (overdue in red) and source meeting; empty state.

GlassTable

Data Table

Frosted table panel with title, description, pill search field and actions slot; rows are separated translucent rounded strips that brighten on hover. Typed generic columns, sorting, mobile hiding, empty state.

GlassTable

Meetings Table

Recent meetings glass table: title with gradient video icon and platform, date, mono duration, participant avatar stack and a recap status pill (ready, processing, private).

GlassTable

Usage Table

Team usage glass table: member, inline gradient bar of recorded hours relative to the top member, meetings count and hours saved, with a tinted totals row.

GlassTable

Data Table

Typed generic table with hairline rows, sortable headers, optional row selection (select-all with indeterminate state) and a floating bulk-action bar. Custom cells, mobile column hiding, empty state.

MinimalTable

Grouped Table

Services table grouped by team: collapsible tinted group rows with service count and alert subtotal, then rows with status dot, mono service name, owner, alerts and MTTA.

MinimalTable

Paginated Table

Audit-log table with client-side pagination: page-size select, “1–10 of 47” range, numbered pages with ellipsis and prev/next; mono timestamps and IPs, horizontal scroll on mobile.

MinimalTable

Uptime Table

Status-page uptime table: one row per service with 30 daily bars colored by threshold (≥ 99.99 %, ≥ 99 %, below), a current-status dot, the 30-day average and a legend.

MinimalTable

Changelog Table

Release log laid out as a table: mono version + ISO date column, a square type tag (New in signal color, Improved outlined, Fixed gray) and dash-listed notes; hairline rows.

Mono CleanTable

Data Table

Analytics table in pure typography: mono headers that sort (↑/↓ glyph, aria-sort), hairline rows, tabular numbers, inline hairline bars for share of views, and an ink total row.

Mono CleanTable

Projects Table

Studio project index (the classic portfolio list): large titles with client, discipline and year in mono columns; each row is one link that inverts to ink on hover with an ↗.

Mono CleanTable

Sites Table

Sites dashboard table: name + domain link, dot status in mono, template, updated time and a “…” Radix dropdown (open, duplicate, archive); hairline rows.

Mono CleanTable

Approvals Table

Bill approval queue: vendor + requester, category, mono amount and inline Approve / Reject buttons that turn the row into a decided state (with Undo); pending count in the header.

Neo CorporateTable

Data Table

Customer data table: sortable headers (aria-sort), row checkboxes with select-all (indeterminate), bulk-action bar when rows are selected, mono amounts and pagination.

Neo CorporateTable

Invoice Table

Receivables table with status pills, days-late aging text, mono amounts, a totals footer and a per-row Radix dropdown (view, send reminder, duplicate, void).

Neo CorporateTable

Ledger Table

General-ledger table grouped by date: journal ref and memo, GL account, debit/credit columns in mono, credits indented, and balanced totals row with a “Balanced” check.

Neo CorporateTable

Actions Table

Reduction plan table: round checkboxes mark actions done (row softens), owner and due date, mono savings, and a progress header showing tonnes secured toward the target.

Organic SoftTable

Emissions Table

Emissions by category: rounded cream table with scope leaf chips, inline sage share bars behind the tonnes, mono figures, colored year-over-year change and a total row.

Organic SoftTable

Monthly Table

Month × scope heat table: each cell tinted by intensity along a sand→sage→forest scale with mono values; row totals and a legend; readable without color.

Organic SoftTable

Supplier Table

Supplier engagement table: filter pills by status, arch avatars, share of footprint, status pill and 3-dot data quality meter, with a per-row “Nudge” pill that turns into “Sent”.

Organic SoftTable

Activity Table

Activity log table: kind icon in a pastel circle, emoji avatar and sentence (“Ana completed …”), board chip and relative time; rows highlight softly on hover.

Soft FlatTable

Simple Table

Plain friendly data table in a rounded white card: soft header well, roomy rows, gentle zebra and right-aligned numbers; generic columns and rows props.

Soft FlatTable

Task Table

“My tasks” table where each row is a soft rounded strip: round done checkbox, title (struck when done), pastel board chip, owner initial avatar and due chip (red when overdue).

Soft FlatTable

Workload Table

Team workload heat table: a row per person (emoji + name), one rounded cell per weekday tinted mint → butter → peach by number of tasks, with a legend.

Soft FlatTable