Pattern

Comparison table

Cities or plans side by side, row by row.

betav0.1.0 Chromium 103 ui-scale safe

Install

Copies the file into components/ds/, with its registry dependencies and npm packages. See Installation for the one-time setup.
bunx shadcn@3 add @fastrp/comparison-table

Examples

Default

Open alone
—
Los Santos
Janti
KonumİstanbulAnkara
GirişBaşvuru ileHerkese açık
Para birimi$₺
Karakter adıLatinTürkçe
Kapasite300 oyuncu200 oyuncu

API

<ComparisonTable />

Cities — or tiers, or plans — side by side, row by row, for the reader who wants it in one look. Scrolls sideways on a phone rather than squeezing the columns.

PropTypeDefaultNotes
columns*ComparisonColumn[]—
rows*ComparisonRow[]—
classNamestring—

Dependencies

npm

  • None

Registry

Source

components/ds/comparison-table.tsxShow
import type * as React from 'react';
import { AccentScope } from '@/components/ds/accent-scope';
import { cn } from '@/lib/utils';

// @fast-ds [email protected]

export type ComparisonColumn = {
  key: string;
  title: React.ReactNode;
  /** The column's city colour, for its dot. A refused colour falls back to the page's. */
  accent?: string;
};

export type ComparisonRow = {
  key: string;
  label: React.ReactNode;
  /** One cell per column, in column order. */
  cells: React.ReactNode[];
};

export type ComparisonTableProps = {
  columns: ComparisonColumn[];
  rows: ComparisonRow[];
  className?: string;
};

/**
 * Cities — or tiers, or plans — side by side, row by row, for the reader who wants it in one
 * look. Scrolls sideways on a phone rather than squeezing the columns.
 */
function ComparisonTable({ columns, rows, className }: ComparisonTableProps) {
  return (
    <div data-slot="comparison-table" className={cn('glass overflow-x-auto', className)}>
      <table className="w-full min-w-[36rem] border-collapse text-left">
        <thead>
          <tr className="border-b border-line">
            <th className="p-5 md:p-6">
              <span className="sr-only">—</span>
            </th>
            {columns.map((column) => (
              <th key={column.key} className="p-5 md:p-6">
                <AccentScope
                  accent={column.accent}
                  className="flex items-center gap-3 font-display text-2xl font-normal text-foreground md:text-3xl"
                >
                  <span className="size-2.5 shrink-0 rounded-full bg-primary shadow-glow" />
                  {column.title}
                </AccentScope>
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => (
            <tr key={row.key} className="border-b border-line last:border-0">
              <th
                scope="row"
                className="p-5 align-top text-xs font-normal uppercase tracking-widest text-muted-foreground md:p-6"
              >
                {row.label}
              </th>
              {columns.map((column, index) => (
                <td key={column.key} className="p-5 align-top text-sm text-foreground md:p-6">
                  {row.cells[index]}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export { ComparisonTable };