---
name: using-design-system-components
description: Builds UI from an existing design system instead of inventing components. Enforces search-before-generate, an existence allow-list, verbatim import paths, and composition rules. Use when writing or editing any UI code in a repo that has a component library, when the user mentions a design system, component library, or asks to build a screen, page, form, dialog, table or any interface. Applies whenever a component is about to be created — check this skill before writing a new component file.
license: CC0-1.0
---

# Using design system components

An agent's fastest path to a working component is to write a new one. That is
also how a codebase drifts away from its own design system. This skill makes
the existing system the cheaper path.

## Fill this in first

Replace every `{{PLACEHOLDER}}`. If a section does not apply, delete it —
an unmaintained instruction is worse than a missing one, because the agent has
no reason to doubt it.

- Package: `{{@scope/design-system}}`
- Component source: `{{src/components}}`
- Search command: `{{rg "export (function|const) [A-Z]" src/components}}`
- Typecheck: `{{pnpm typecheck}}`

## Procedure

Follow in order. Step 1 is the one that matters.

1. **Search before you generate.** Run the search command above. If a
   component with the needed behaviour exists, use it. Do not create a
   variant of something that already exists.
2. **Check the allow-list.** If the component is not in the list below, it
   does not exist in this system. Do not create it — ask.
3. **Copy the import verbatim** from the table. Do not infer an import path
   from the component name.
4. **Compose rather than extend.** A settings page is Tabs + Card + form
   controls, not a new SettingsPanel.
5. **Run the typecheck** before reporting the task complete. A passing build
   is the only evidence that counts.

## Components that exist

| Component | Import | Notes |
|---|---|---|
| `{{Button}}` | `{{import { Button } from '@scope/design-system'}}` | `{{variant: 'primary' | 'secondary' | 'ghost'}}` |
| `{{TextField}}` | `{{import { TextField } from '@scope/design-system'}}` | `{{label is required}}` |

Generate this table from the package's real exports. A hand-maintained list
rots, and a rotted list is worse than none: agents faithfully reproduce
documented names that no longer exist, which is a build failure you wrote
yourself.

## Components that do not exist

**There is no `Box`, `Stack`, `Container`, or `Flex` in this system.** Models
reach for these because other libraries have them. Use `{{layout primitive}}`.

Name the specific inventions your system suffers from. A prohibition that
names the mistake is something a model can pattern-match against; "follow our
conventions" is not. Ant Design ships an export allow-list for exactly this.

## Composition rules

- `{{ComponentA}}` may only contain `{{ComponentB}}` and `{{ComponentC}}`.
- `{{Never nest Card inside Card.}}`
- `{{Form fields outside a Form will not submit.}}`

Agents nest wrongly by default, because nothing in a type signature says
`TabPanel` has to sit inside `Tabs`.

## Do not

- Invent prop values. The union type is the whole list. If the compiler
  rejects a value, the fix is a valid value, not a wider type.
- Re-implement a component that exists, even "just this once, simpler".
- Add a dependency to avoid using a component that already ships.
- Edit generated files. They are regenerated from `{{source}}`.

## Verification

Run `{{pnpm typecheck}}`. Then confirm every component you used appears in the
allow-list above. If you introduced a component that is not on it, say so
explicitly in your summary rather than letting it pass silently.
