OSS-first docs

These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.

@contractspec/lib.ui-kit-web

Web-first React and Next primitives for ContractSpec. The canonical data-table example uses this package to render the raw browser table layer directly, without the design-system shell on top.

Installation

bun add @contractspec/lib.ui-kit-web

Data table example

This is the raw browser lane from the canonical Data Grid Showcase. It demonstrates the primitive renderer with sorting, pagination, single selection, column visibility, column resizing, left/right pinning, row expansion, loading, and empty-state slots.

web-account-grid.tsx
import { DataTable } from '@contractspec/lib.ui-kit-web/ui/data-table';
import { useContractTable } from '@contractspec/lib.presentation-runtime-react';

import { SHOWCASE_ROWS } from '@contractspec/example.data-grid-showcase/ui/data-grid-showcase.data';
import { useShowcaseColumns } from '@contractspec/example.data-grid-showcase/ui/data-grid-showcase.columns';
import {
  ExpandedRowContent,
  ShowcaseToolbar,
} from '@contractspec/example.data-grid-showcase/ui/data-grid-showcase.parts';

export function WebAccountGrid() {
  const columns = useShowcaseColumns();

  const controller = useContractTable({
    data: SHOWCASE_ROWS,
    columns,
    selectionMode: 'single',
    initialState: {
      sorting: [{ id: 'lastActivityAt', desc: true }],
      pagination: { pageIndex: 0, pageSize: 4 },
      columnVisibility: { notes: false },
      columnPinning: { left: ['account'], right: [] },
    },
    renderExpandedContent: (row) => <ExpandedRowContent row={row} />,
    getCanExpand: () => true,
  });

  return (
    <DataTable
      controller={controller}
      toolbar={
        <ShowcaseToolbar
          controller={controller}
          label="Web primitive"
          primaryColumnId="account"
          toggleColumnId="notes"
          pinColumnId="owner"
          sortColumnIds={['arr', 'renewalDate']}
        />
      }
      loading={false}
      emptyState={<div>No rows available.</div>}
      footer={`Rows ${controller.totalItems}`}
    />
  );
}

What this layer owns

  • The raw table renderer and browser interaction model.
  • Pagination, column visibility menus, pin menus, resize handles, and empty/loading states.
  • Accessibility helpers and other web-specific primitives that stay outside the native-first package.