---
name: ui-system-extractor
description: Audit an existing React or Next.js application's UI and incrementally extract its reusable primitives, component variants, patterns, themes, content adapters, and CMS layouts into a central UI package without redesigning the application. Use this skill whenever a user asks to centralize UI, create or extend a design system, migrate local components into a shared package, deduplicate Tailwind or Radix components, make an existing frontend themeable, publish a component registry, or preserve an existing design while making it reusable. Prefer existing application implementations and official upstream primitives over inventing new components.
compatibility: Requires repository read/write access for implementation, a shell for deterministic inventory and validation, and browser or screenshot tooling for visual parity checks. Optimized for React, Next.js, TypeScript, Tailwind CSS, Radix Primitives, Motion, and CMS ecosystems.
---

# UI System Extractor

Convert existing UI into a reusable package while preserving the rendered product.

This is an extraction and normalization workflow, not a redesign workflow. The source application is the visual specification unless the user explicitly requests design changes.

## Default target

When the user does not specify another central package, use:

```text
https://github.com/mleem97/mm-ui
```

Do not push or open a pull request unless the user requested repository changes or already authorized implementation. For repository writes, use a focused branch and pull request. Never merge into the default branch automatically.

## Non-negotiable behavior

1. Do not invent a new visual component when an equivalent implementation already exists.
2. Do not materially alter layout, spacing, typography, color, responsive behavior, animation, or interaction during extraction.
3. Preserve every observed variant, size, state, breakpoint, content density, and composition before consolidating APIs.
4. Keep business logic, data fetching, routes, permissions, analytics, feature flags, and CMS queries in the application.
5. Move reusable presentation, interaction, accessibility behavior, variants, tokens, content adapters, and layout contracts into the UI package.
6. Make all package components theme-compatible through semantic variables rather than application palette names.
7. Make CMS layouts installable and replaceable through typed layout definitions and named slots.
8. Keep migration incremental and reversible. Avoid broad rewrites when one component family can be migrated independently.
9. Verify current primary documentation when framework or library behavior may have changed.
10. Report uncertainty instead of silently approximating the source design.

## Source precedence

Use this order for every extracted component:

1. **Source application** — existing DOM, CSS, Tailwind classes, variants, states, screenshots, tests, and usage sites.
2. **Central UI package** — existing `mm-ui` primitive, pattern, theme token, adapter, or layout.
3. **Official Radix Primitive** — behavior, focus management, keyboard navigation, ARIA, portals, dismiss layers, and state attributes.
4. **Official shadcn implementation or registry item** — reusable composition reference that can be adapted to the source design.
5. **Official specialized primitive** — React Aria for date, collection, selection, locale, or complex accessibility; Floating UI for positioning; Motion for presence, layout, gestures, or coordinated animation.
6. **Thin adapter** — only when the sources above do not directly match. An adapter may compose behavior and preserve the source DOM, but must not introduce a new design direction.

Do not use unofficial snippets as authoritative behavior when an official implementation exists. Third-party examples may be used only after reviewing their license, dependencies, accessibility, maintenance status, and fit with the source implementation.

Read `references/source-priority.md` when choosing an upstream basis or when two candidate implementations conflict.

## Package layers

Classify every UI item into exactly one primary layer:

### Primitive

Small application-independent building block, such as Button, Input, Label, Surface, Stack, Dialog, Select, Tooltip, Tabs, Separator, Avatar, or Typography.

### Pattern

Reusable composition of primitives without product business logic, such as FormField, ConfirmationDialog, EmptyState, FilterBar, DataTableToolbar, SearchBox, PageHeader, or NotificationPanel.

### Layout

Structural arrangement of named regions, such as marketing, dashboard, article, documentation, authentication, storefront, split-pane, or portal layouts. Layouts receive slots and do not fetch CMS data.

### Content adapter

Styling and rendering contract for external content formats, such as Markdown, MDX, WordPress/Gutenberg, rich text, code blocks, embeds, or media.

### Application component

Contains domain rules, services, route assumptions, permissions, application state, CMS queries, or one-off product content. Keep it in the application. Split mixed components into an application controller and reusable package view.

Read `references/migration-playbook.md` for detailed split rules and migration patterns.

## Workflow

Follow these phases in order. Do not begin extraction before the inventory and mapping exist.

### Phase 1: Establish scope and safeguards

1. Identify the source application repository, package manager, framework, React version, Tailwind version, Radix usage, Motion usage, styling entry points, test tools, and target UI package.
2. Read repository instructions such as `AGENTS.md`, `CLAUDE.md`, contribution guides, package manifests, workspace configuration, and CI workflows.
3. Identify supported browsers, locales, RTL requirements, accessibility target, and responsive breakpoints from repository evidence.
4. Record the current branch and working tree state. Do not overwrite unrelated user changes.
5. Determine whether visual baseline tooling already exists. Prefer the project's existing Storybook, Playwright, Chromatic, screenshot, or component test setup.

### Phase 2: Inventory all UI

Run the bundled inventory script when a shell is available:

```bash
python3 <skill-directory>/scripts/inventory_ui.py \
  --root <application-root> \
  --json <output-directory>/ui-inventory.json \
  --markdown <output-directory>/ui-inventory.md
```

Then supplement automated results with repository search for:

- JSX and TSX components;
- `components`, `ui`, `layouts`, `blocks`, `patterns`, `features`, and `app` directories;
- global CSS, CSS Modules, Sass, styled components, and inline styles;
- Tailwind utility clusters and variant helpers;
- Radix, shadcn, Motion, React Aria, Floating UI, icon, chart, editor, and form imports;
- repeated DOM structures and repeated class strings;
- hard-coded colors, radii, shadows, z-indexes, animation values, and breakpoints;
- all component props, default values, states, sizes, and variants;
- loading, empty, error, success, disabled, invalid, selected, open, closed, hover, focus, active, and responsive states;
- route layouts, CMS templates, prose styles, theme providers, and layout selectors.

Use the schema in `references/audit-schema.md`. The inventory must include usage counts and source locations, not only component names.

### Phase 3: Capture visual and behavioral baselines

For each candidate component family:

1. Capture representative pages and states at every supported breakpoint.
2. Record DOM semantics, accessible names, keyboard behavior, focus order, portal behavior, scroll locking, and reduced-motion behavior.
3. Record computed values or source tokens for spacing, colors, radii, shadows, typography, and animation.
4. Identify intentional visual differences between usage sites. Do not collapse differences merely because names are similar.
5. Mark states that cannot be reproduced locally because of missing data or credentials.

Screenshots are evidence, not a license to approximate hidden behavior.

### Phase 4: Build the extraction map

For every candidate, create a mapping row with:

- source files and usage sites;
- classification: primitive, pattern, layout, content adapter, or application component;
- existing variants and states;
- target package path and public import;
- chosen upstream basis and official source;
- semantic tokens required;
- application dependencies to remove or inject;
- visual baseline references;
- migration order;
- verification commands;
- rollback boundary.

Reject extraction when the item is truly one-off and no stable reusable view can be separated.

### Phase 5: Freeze contracts before moving code

Define or extend these contracts before component migration:

1. Semantic theme variables and Tailwind mappings.
2. Variant and size naming conventions.
3. Public package exports.
4. Theme metadata and runtime selection behavior.
5. Layout definition, slot, and registry types.
6. Content adapter boundaries.
7. Icon strategy.
8. Motion defaults and reduced-motion behavior.
9. Ref, `className`, `asChild`, native prop, and event composition rules.

A component must not depend on an application-specific token such as `svh-gold`, `dashboard-card`, or `marketing-green`. Map it to a semantic role and assign that role in the application's theme.

Read `references/cms-theming.md` before changing global CSS, themes, layouts, prose, or CMS templates.

### Phase 6: Extract foundation first

Migrate in dependency order:

1. class composition and ref utilities;
2. theme contract and application theme preset;
3. typography and layout primitives;
4. surface, separator, icon, link, and button;
5. form field foundations and native controls;
6. Radix interaction primitives;
7. feedback and data display;
8. patterns;
9. content adapters;
10. layouts;
11. domain-specific reusable modules.

Do not migrate a pattern before its required primitives are stable.

### Phase 7: Preserve variants exactly

For each extracted component:

1. Start from the most complete existing implementation.
2. Merge only variants demonstrated by current usage or an accepted upstream contract.
3. Preserve consumer `className` and merge it last.
4. Preserve refs and native/upstream props.
5. Preserve semantic HTML. Do not replace buttons with generic elements.
6. Keep Radix internal; export the package API rather than upstream namespaces wholesale.
7. Keep client boundaries at interactive leaves.
8. Use CSS for simple transitions and Motion only for presence, layout, gestures, or coordinated sequences.
9. Respect `prefers-reduced-motion` and Motion's user preference mode.
10. Keep dynamic application values as props or slots rather than package imports.

### Phase 8: Migrate application usage incrementally

For one component family at a time:

1. Add the package implementation.
2. Add tests and documentation.
3. Replace imports in a limited set of usage sites.
4. Preserve the original component as a compatibility adapter when many call sites remain.
5. Verify before deleting local implementations.
6. Remove dead CSS only after repository search confirms there are no remaining consumers.
7. Commit or open a focused pull request with a reversible boundary.

Avoid a single repository-wide rename unless existing tests and visual tooling make it safe.

### Phase 9: Verify parity

Run the repository's own checks and, where available:

```text
TypeScript
lint
unit tests
component tests
accessibility tests
Playwright/browser tests
visual regression
production build
bundle analysis
registry validation
```

Test each migrated component in:

- all observed variants and sizes;
- all interaction and validation states;
- every built-in theme plus the source application's theme;
- supported breakpoints;
- keyboard-only operation;
- reduced motion;
- LTR and RTL when supported;
- server rendering and hydration in Next.js;
- nested portals and overlays when applicable.

Visual acceptance means no material change to layout or design. Pixel differences caused by extraction require investigation, not automatic approval.

### Phase 10: Report and continue

Produce:

1. inventory location;
2. extraction map;
3. components moved and public imports;
4. upstream bases used;
5. themes and layouts added or changed;
6. application adapters retained;
7. verification commands and results;
8. visual differences, if any;
9. remaining candidates in dependency order;
10. pull request links and branch names when repository changes were requested.

## Theme extension contract

A custom theme must assign the complete semantic `--ui-*` contract under a stable selector such as:

```css
[data-theme="customer-theme"] {
  color-scheme: light;
  --ui-background: ...;
  --ui-foreground: ...;
  --ui-surface: ...;
  --ui-surface-raised: ...;
  --ui-surface-sunken: ...;
  --ui-primary: ...;
  --ui-primary-foreground: ...;
  --ui-secondary: ...;
  --ui-secondary-foreground: ...;
  --ui-accent: ...;
  --ui-accent-foreground: ...;
  --ui-muted: ...;
  --ui-muted-foreground: ...;
  --ui-link: ...;
  --ui-selection: ...;
}
```

User theme CSS is imported after package defaults. New themes must work without rebuilding package components.

## CMS layout extension contract

A layout package exports a typed definition containing:

- a stable id and human-readable label;
- a component receiving named slots;
- the slots it supports;
- optional metadata for preview, capabilities, version, or CMS compatibility.

Layouts arrange content. CMS data acquisition remains outside the layout and is passed through slots or serializable view models.

## Prohibited shortcuts

Do not:

- generate a fresh design system from generic preferences;
- replace source UI with default shadcn styling;
- apply `dark:` classes as the primary multi-theme mechanism;
- hard-code a brand palette into universal primitives;
- move API clients or CMS queries into the UI package;
- remove local components before all call sites are migrated;
- flatten distinct variants without evidence;
- use screenshot similarity as the only accessibility test;
- add dependencies solely because they are fashionable;
- claim parity without baseline evidence and executed checks.

## Completion criteria

The task is complete only when:

- the requested UI scope has an evidence-backed inventory;
- each migrated item has a documented existing or official basis;
- reusable code lives in the central package with stable exports;
- the source application uses the package for the migrated scope;
- current appearance and layout are materially preserved;
- custom themes can implement the semantic contract;
- custom layouts can register through the layout contract;
- tests and builds pass, or failures are explicitly reported with evidence;
- remaining application-owned UI is listed rather than silently ignored.
