> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage

> Build front-end UI by composing components, hooks, icons, fonts, styles, and utils from the design module.

The design module is the front-end design system — a `type: "design"` module under `modules/<name>/`, published as `@module/<name>` and consumed primarily by the [Single Page App](/spa/overview). Its `src/` ships ready-made building blocks so you compose UI instead of writing ad-hoc markup: `components/` (React primitives), `hooks/` (presentation hooks), `icons/` (SVG sets), `fonts/` (bundled web fonts), `styles/` (global stylesheets and tokens), and `utils/` (class-name helpers).

This page walks through using each asset kind. It is not part of the backend pipeline — see the [overview](/design-system/overview) for what it is and the [structure](/design-system/structure) for how it is laid out.

<Note>
  Exact import paths and component props depend on your skeleton-design source. The examples below are illustrative — always consult the actual components in `modules/<name>/src/` for the real API.
</Note>

## Composing components

`components/` holds React (`.tsx`) UI primitives, one folder per grouping that collects its variants — for example `button/` contains `Button.tsx`, `ButtonSave.tsx`, and friends. There are around fifty: accordion, avatar, badge, button, card, dialog, form, input, select, table, tabs, tooltip, and more.

Compose these primitives rather than reinventing markup or duplicating their internals. Import the pieces you need and assemble a screen:

```tsx theme={null}
import { Button } from "@module/<name>/components/button";
import { Card } from "@module/<name>/components/card";

export const ProfileCard = ({ name }: { name: string }) => {
  return (
    <Card>
      <Card.Header>
        <Card.Title>{name}</Card.Title>
      </Card.Header>
      <Card.Body>Welcome back to your workspace.</Card.Body>
      <Card.Footer>
        <Button onClick={() => console.log("saved")}>Save changes</Button>
      </Card.Footer>
    </Card>
  );
};
```

Reach for a purpose-built variant (such as `ButtonSave`) when one exists instead of re-implementing its behavior on a base `Button`.

## Using hooks

`hooks/` provides reusable React hooks for presentation-layer concerns — state, DOM, and events. The set includes `useClickOutside`, `useMobile`, `useControlledState`, and `useAutoHeight`. Keep data-fetching and domain logic out of these hooks; that work belongs in services.

Use `useClickOutside` to dismiss a transient surface like a dropdown:

```tsx theme={null}
import { useRef, useState } from "react";
import { useClickOutside } from "@module/<name>/hooks";

export const Dropdown = () => {
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  useClickOutside(ref, () => setOpen(false));

  return (
    <div ref={ref}>
      <button onClick={() => setOpen((value) => !value)}>Menu</button>
      {open && <ul>{/* menu items */}</ul>}
    </div>
  );
};
```

Use `useMobile` to branch on viewport for responsive behavior:

```tsx theme={null}
import { useMobile } from "@module/<name>/hooks";

export const Layout = ({ children }: { children: React.ReactNode }) => {
  const isMobile = useMobile();

  return isMobile ? <Stack>{children}</Stack> : <SplitView>{children}</SplitView>;
};
```

## Using icons

`icons/` ships SVG icons organized by variant, category, and size — the path is `icons/<variant>/<category>/<size>/<IconName>.tsx`. Variants are `fill/` and `outline/`, sizes are `sm`, `md`, and `lg`, and each icon is its own component file (for example `icons/fill/accessibility/lg/AccessibilityLiftIcon.tsx`). Import the specific icon you need rather than pasting inline SVG into your components.

```tsx theme={null}
import { AccessibilityLiftIcon } from "@module/<name>/icons/fill/accessibility/lg/AccessibilityLiftIcon";
import { SearchIcon } from "@module/<name>/icons/outline/interface/sm/SearchIcon";

export const Toolbar = () => {
  return (
    <div>
      <SearchIcon />
      <AccessibilityLiftIcon />
    </div>
  );
};
```

The size lives in the import path, not in a prop, so pick it by importing from the matching `sm`/`md`/`lg` folder. Choose `outline` for neutral, interface-level affordances and `fill` for emphasis or active states, and keep sizes consistent within a control by importing its icons from the same size folder.

## Fonts and styles

`fonts/` bundles the web fonts (Space Grotesk) with their `@font-face` declarations. Reference the bundled fonts — never pull from an external font CDN — so typography stays self-contained and offline-safe.

`styles/` holds the global stylesheets: `app.css`, `brand.css`, `shape.css`, `status.css`, and `typography.css`. Import them once at the app entry point and edit them for app-wide tokens, themes, and base styling.

```tsx theme={null}
// app entry point (e.g. main.tsx)
import "@module/<name>/fonts/space-grotesk.css";
import "@module/<name>/styles/app.css";
import "@module/<name>/styles/brand.css";
import "@module/<name>/styles/typography.css";
```

```css theme={null}
/* fonts/space-grotesk.css — bundled, no external CDN */
@font-face {
  font-family: "Space Grotesk";
  src: url("./space-grotesk.woff2") format("woff2");
  font-weight: 300 700;
  font-display: swap;
}
```

Change a token in one place — `brand.css` for colors, `typography.css` for type scale, `shape.css` for radii — and every component that reads it updates with it.

## Merging class names with `cn`

`utils/` carries front-end helpers: `cn` (class-name merge) and `staleChunk`. Use `cn` to compose conditional and overriding class names cleanly instead of hand-built string concatenation:

```tsx theme={null}
import { cn } from "@module/<name>/utils";

export const Tag = ({ active, className }: { active: boolean; className?: string }) => {
  return (
    <span
      className={cn(
        "rounded px-2 py-1",
        active && "bg-brand text-white",
        className,
      )}
    >
      Tag
    </span>
  );
};
```

Accepting a `className` prop and merging it with `cn` lets callers override styling without you forking the component.

## Best practices

* **Compose, don't duplicate.** Build screens from existing primitives and their variants; never copy a component's internals into your own markup.
* **Keep hooks generic.** Use hooks for presentation state, DOM, and events only — keep data-fetching and domain logic in services, not in the design module.
* **Use the provided icons and fonts.** Pick a `fill`/`outline` icon at a standard size; reference the bundled Space Grotesk fonts rather than inline SVG or external CDNs.
* **Centralize tokens in styles.** Put colors, type scale, shape, and status tokens in the `styles/` files so changes propagate from one place.
* **No business logic here.** The design module is presentation only; domain rules and data access live elsewhere in the stack.
* **Merge class names with `cn`.** Accept a `className` prop and combine it with `cn` so consumers can extend styling safely.
* **Verify against the source.** Import paths and props depend on the skeleton-design source — confirm the real API by reading the components in `modules/<name>/src/`.

## Related

* [Design System overview](/design-system/overview) — what the design module is and why it exists.
* [Design System structure](/design-system/structure) — how the `src/` assets are organized.
* [SPA overview](/spa/overview) — the app that consumes this design system.
* [SPA features](/spa/features) — where these components and hooks come together in product UI.
