UI Lab

    Data Table Variants

    26 production-ready patterns — pick one, see the live preview, copy the code

    Simple Contact List

    Basic table with search and pagination — ideal starter.

    Contacts

    A simple list of contacts.

    Phone
    Alice Johnsonalice@example.com+1 555-0101
    Bob Smithbob@example.com+1 555-0102
    Carol Whitecarol@example.com+1 555-0103
    David Browndavid@example.com+1 555-0104
    Eva Martinezeva@example.com+1 555-0105
    Frank Leefrank@example.com+1 555-0106
    Grace Hopgrace@example.com+1 555-0107
    Henry Fordhenry@example.com+1 555-0108

    Showing 18 of 8

    1 / 1
    Source Code

    Install & set up

    Everything this table needs: 2 generated files to copy and 23 shared engine files the CLI can install for you.

    1

    Data Source

    Choose how data is loaded — only the matching helpers are generated.

    2

    Install it with the CLI

    recommended

    Installs every file below and its packages in one command. The steps after this are only for doing it by hand.

    npx afnoui add tables/tables-simple-list
    Writes to 4 places
    3

    Or install the packages yourself

    Only needed if you copied the files by hand instead of running the command above.

    Runtime dependencies

    npm install @radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-dropdown-menu @radix-ui/react-progress @radix-ui/react-radio-group @radix-ui/react-scroll-area @radix-ui/react-select @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-tooltip @tanstack/react-virtual class-variance-authority clsx lucide-react react tailwind-merge

    Dev dependencies

    npm install -D @types/react typescript

    Generated files

    Generated files are yours to copy and edit; shared engine files are installed once and reused.

    Generated per table(2)

    Shared engine — copy once(23)

    Generated per table

    Strongly-typed config object + Row interface for this table.

    src/components/tables/tableConfig.ts
    src/components/tables/tableConfig.ts
    import type { TableBuilderConfig, TableRow } from "./types";
    
    export interface Row extends TableRow {
      id: string;
      "name": string;
      "email": string;
      "phone": string;
    }
    
    
    export const tableConfig: TableBuilderConfig = {
      "title": "Contacts",
      "description": "A simple list of contacts.",
      "direction": "ltr",
      "density": "comfortable",
      "pageSize": 8,
      "sortMode": "client",
      "paginationMode": "client",
      "expandableLayout": "details",
      "expandableIconStyle": "chevron",
      "expandableIconPosition": "first",
      "paginationLayout": "full",
      "pageSizeOptions": [
        5,
        10,
        20,
        50,
        100
      ],
      "virtualRowHeight": 44,
      "virtualMaxHeight": 520,
      "enableDnD": false,
      "enableHover": true,
      "enableSearch": true,
      "enableExport": false,
      "enableFooter": false,
      "enableStriped": false,
      "enableBordered": false,
      "enableMultiSort": false,
      "enablePagination": true,
      "enableInlineEdit": false,
      "enableRowGrouping": false,
      "enableBulkActions": false,
      "enableAggregation": false,
      "enableRowSelection": false,
      "enableStickyHeader": false,
      "enableColumnResize": false,
      "enableColumnFilters": false,
      "enableNestedHeaders": false,
      "enablePinnedColumns": false,
      "enableVirtualization": false,
      "enableExpandableRows": false,
      "enableColumnVisibility": false,
      "columns": [
        {
          "id": "c1",
          "key": "name",
          "label": "Name",
          "type": "text",
          "sortable": true,
          "filterable": true,
          "visible": true,
          "align": "left"
        },
        {
          "id": "c2",
          "key": "email",
          "label": "Email",
          "type": "email",
          "sortable": true,
          "filterable": true,
          "visible": true,
          "align": "left"
        },
        {
          "id": "c3",
          "key": "phone",
          "label": "Phone",
          "type": "text",
          "sortable": false,
          "filterable": false,
          "visible": true,
          "align": "left"
        }
      ],
      "stickyMaxHeight": 600
    } as const satisfies TableBuilderConfig;