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.

AI index

@lssm-tech/lib.design-system

High-level design system components, patterns, and layouts for LSSM applications. Built on top of @lssm-tech/lib.ui-kit.

Installation

bun add @lssm-tech/lib.design-system

What It Provides

  • Composite Components: Molecules and Organisms that solve common UI problems
  • Layouts: Ready-to-use page structures for dashboards, marketing sites, and lists
  • Data Views: Standardized renderers for lists, tables, and detail views
  • Forms: Zod-integrated form layouts and components
  • Code Display: Syntax-highlighted code blocks with package manager tabs
  • Platform Utilities: Hooks for responsive and adaptive design
  • Object References: Clickable references for addresses, phone numbers, users, customers, files, URLs, and custom objects
  • Adaptive Panels: One panel API that resolves to a desktop sheet or mobile drawer
  • Theme Bridge: ThemeSpec to Tailwind variables, presets, CSS text, and runtime light/dark mode
  • Legal Templates: Compliant templates for Terms, Privacy, and GDPR

ThemeSpec to Tailwind

The theme bridge keeps ThemeSpec as the source of truth and exposes no-generation Tailwind helpers, optional CSS text serialization, runtime CSS variables, light/dark modes, and OKLCH color pass-through.

import {
  DesignSystemThemeProvider,
  resolveThemeModeTokens,
  themeSpecToCssVariables,
  themeSpecToTailwindCss,
  themeSpecToTailwindPreset,
} from '@lssm-tech/lib.design-system';

const tokens = resolveThemeModeTokens(themeSpec, 'light', {
  targets: ['tenant:acme'],
});

export default themeSpecToTailwindPreset(tokens);

const css = themeSpecToTailwindCss(
  themeSpecToCssVariables(themeSpec, { targets: ['tenant:acme'] }),
  { includeCustomVariant: true }
);

export function TenantSurface({ children }: { children: React.ReactNode }) {
  return (
    <DesignSystemThemeProvider
      theme={themeSpec}
      targets={['tenant:acme']}
      mode="dark"
      applyCssVariables
    >
      {children}
    </DesignSystemThemeProvider>
  );
}

Focused import surfaces

New code can use focused subpaths for theme, controls, forms, and layout while existing root imports remain compatible.

import { themeSpecToTailwindPreset } from '@lssm-tech/lib.design-system/theme';
import { Select } from '@lssm-tech/lib.design-system/controls';
import { FormDialog } from '@lssm-tech/lib.design-system/forms';
import { HStack } from '@lssm-tech/lib.design-system/layout';
import { AdaptivePanel } from '@lssm-tech/lib.design-system/components/overlays';
import { ObjectReferenceHandler } from '@lssm-tech/lib.design-system/components/object-reference';

// Root imports remain supported:
import { Button, DataTable } from '@lssm-tech/lib.design-system';

Actionable object references

Use ObjectReferenceHandler whenever a product surface renders an object that may need quick interaction: addresses, phone numbers, emails, users, customers, files, URLs, and tenant-specific objects. The goal is to avoid inert references while keeping the descriptor contract declarative enough for OSS consumers and future contract-generated surfaces.

Descriptor model

  • References use data-only descriptors: id, kind, label, value, href, openTarget, metadata, iconKey, and ariaLabel.
  • Rich references use nested properties and sections, so one user or customer can expose email, phone, address, files, and links inside the same panel.
  • Reference kinds are address, email, phone, user, customer, file, url, and custom.

Runtime behavior

  • Choose visibility with interactivityVisibility:none, underline, or icon.
  • Detail navigation defaults to same-page; set openTarget="new-page" on the handler, reference, or action when a new page is required.
  • Host apps provide behavior through copyHandler, openHref, actionHandlers, onAction, and onActionError.

Default actions

  • createDefaultObjectReferenceActions adds copy, open, email, phone, and map actions when the descriptor supports them.
  • createMapsReferenceActions creates Google Maps, Apple Maps, Waze, or geo actions for address references.
  • Safe href handling allows expected app, web, email, phone, and map URLs while rejecting unsafe schemes.

Extension points

  • Use renderTrigger, renderDetail, renderAction, renderProperty, renderSection, and iconRenderer to wrap or overload presentation.
  • Keep tenant-specific permissions, analytics, and integration side effects at the host boundary through runtime handlers.
import {
  ObjectReferenceHandler,
  createDefaultObjectReferenceActions,
  createMapsReferenceActions,
  type ObjectReferenceDescriptor,
  type ObjectReferenceOpenHrefHandler,
} from '@lssm-tech/lib.design-system';

const customerContact: ObjectReferenceDescriptor = {
  id: 'user.amina',
  kind: 'user',
  label: 'Amina Laurent',
  description: 'Customer success owner',
  href: '/customers/acme/users/amina',
  properties: [
    {
      id: 'user.amina.email',
      kind: 'email',
      label: 'Email',
      value: 'amina@example.com',
    },
    {
      id: 'user.amina.phone',
      kind: 'phone',
      label: 'Phone',
      value: '+33 1 23 45 67 89',
    },
  ],
  sections: [
    {
      id: 'customer-site',
      title: 'Primary site',
      properties: [
        {
          id: 'customer-site.address',
          kind: 'address',
          label: 'Paris office',
          value: '10 rue de Rivoli, 75001 Paris',
          actions: createMapsReferenceActions({
            id: 'customer-site.address',
            kind: 'address',
            label: 'Paris office',
            value: '10 rue de Rivoli, 75001 Paris',
          }),
        },
      ],
    },
  ],
};

const openHref: ObjectReferenceOpenHrefHandler = (href, _event, options) => {
  if (options.target === 'new-page') {
    window.open(href, '_blank', 'noopener,noreferrer');
    return;
  }

  window.location.assign(href);
};

<ObjectReferenceHandler
  reference={customerContact}
  actions={createDefaultObjectReferenceActions(customerContact)}
  interactivityVisibility="icon"
  openTarget="same-page"
  panelMode="responsive"
  mobilePanelMode="drawer"
  desktopPanelMode="sheet"
  responsiveBreakpoint="md"
  openHref={openHref}
/>;

Adaptive panels

AdaptivePanel is the shared overlay decision for surfaces that should feel native on both desktop and small screens. Its default responsive mode renders a sheet at the configured desktop breakpoint and a drawer below it. ObjectReferenceHandler uses this panel contract through panelMode, mobilePanelMode, desktopPanelMode, and responsiveBreakpoint.

import { AdaptivePanel } from '@lssm-tech/lib.design-system/components/overlays';

<AdaptivePanel
  open={open}
  onOpenChange={setOpen}
  trigger={<button type="button">Edit</button>}
  title="Edit customer"
  description="Update contact and site details."
  mode="responsive"
  mobileMode="drawer"
  desktopMode="sheet"
  breakpoint="md"
  sheetSide="right"
  drawerDirection="bottom"
>
  {content}
</AdaptivePanel>;

Prompt for adoption work

Use this prompt when asking an agent or downstream OSS consumer to replace inert references across an application.

Find every user-facing address, phone number, email, user, customer, file, URL, and tenant-specific object reference currently rendered as inert text.

Replace each one with ObjectReferenceHandler from @lssm-tech/lib.design-system. Keep descriptors data-only: id, kind, label, value, href, openTarget, properties, sections, metadata, iconKey, and ariaLabel are allowed; React callbacks belong in handler props only.

Use properties and sections for rich references. For example, a user reference can expose email, phone, address, files, and customer links in one panel instead of rendering separate disconnected strings.

Use panelMode="responsive" by default. Let desktop render a sheet and small screens render a bottom drawer through AdaptivePanel. Do not call Sheet or Drawer directly for this interaction unless a lower-level primitive is being implemented.

Use openTarget="same-page" unless product requirements explicitly require a new page. Put custom copy, navigation, analytics, permissions, or tenant-specific actions in copyHandler, openHref, actionHandlers, onAction, and onActionError.

For addresses, use createMapsReferenceActions so users can choose Google Maps, Apple Maps, or Waze. For email and phone references, prefer createDefaultObjectReferenceActions unless a product-specific action set is required.

After replacing references, verify keyboard access, visible affordance choice (none, underline, or icon), safe href behavior, mobile drawer layout, and desktop sheet layout.

Data table example

This is the composed lane from the canonical Data Grid Showcase. The design-system wrapper owns title, description, header actions, and the opinionated card shell on top of the raw web primitive.

import { Button, DataTable } from '@lssm-tech/lib.design-system';
import { useContractTable } from '@lssm-tech/lib.presentation-runtime-react';

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

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

  const controller = useContractTable({
    data: SHOWCASE_ROWS,
    columns,
    selectionMode: 'multiple',
    initialState: {
      sorting: [{ id: 'arr', 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}
      title="Account health"
      description="Composed table surface for the canonical account grid."
      headerActions={<Button variant="outline">Reset</Button>}
      toolbar={
        <ShowcaseToolbar
          controller={controller}
          label="Client mode"
          primaryColumnId="account"
          toggleColumnId="notes"
          pinColumnId="owner"
          sortColumnIds={['arr', 'renewalDate']}
        />
      }
      loading={false}
      emptyState={<div>No rows available.</div>}
      footer={`Page ${controller.pageIndex + 1} of ${controller.pageCount}`}
    />
  );
}

Key Exports

Organisms

  • AppShell, PageOutline
  • AppLayout, AppHeader, AppSidebar
  • MarketingLayout, HeroSection
  • ListCardPage, ListTablePage

Data & Forms

  • DataTable
  • DataViewTable
  • DataViewRenderer
  • ZodForm
  • FormLayout, FormDialog

Code Display

  • CodeBlock (syntax highlighting)
  • CommandTabs (package manager tabs)
  • InstallCommand (convenience wrapper)
  • CopyButton

Providers

  • PackageManagerProvider

References & Overlays

  • ObjectReferenceHandler
  • createDefaultObjectReferenceActions
  • createMapsReferenceActions
  • AdaptivePanel

Where this layer fits

Read Application shell for the shared sidebar, topbar, command search, mobile navigation, and PageOutline pattern. Read Cross-platform UI for the package split between shared runtime controllers, leaf platform primitives, and this composed design-system layer.