add-component
Create a reusable UI component with factory pattern, theme compatibility, and proper cleanup
Best use case
add-component is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Create a reusable UI component with factory pattern, theme compatibility, and proper cleanup
Teams using add-component should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/add-component/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How add-component Compares
| Feature / Agent | add-component | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Create a reusable UI component with factory pattern, theme compatibility, and proper cleanup
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Add Component Skill
## Usage
```
/add-component <ComponentName>
```
## Step 1: Ask Questions
### 1. Check Existing Components First
```
Does an existing component cover ~80% of the need?
→ Check src/ui/components/ before creating new
```
Existing: `ArcadeButton`, `BasePetCard`, `GeminiIconButton`, `Modal`, `ProgressBar`, `SegmentedControl`, `SeeMore`, `SoundPicker`, `Tab`, `TeamListItem`
### 2. Component Purpose
```
Brief description (1 sentence):
```
### 3. Configuration Options
```
What options does it need?
- Required: ___________
- Optional with defaults: ___________
- Event handlers: ___________
```
### 4. Sprites
```
Does it display game sprites? → MGSprite.toCanvas()
```
### 5. Dynamic State
```
Does it need reactive updates?
A) Manual setters only (setLabel, setDisabled, setValue, etc.)
B) Reactive to Globals (subscribe to myInventory, currentTile, weather, etc.)
C) Both
If B/C: Component subscribes to Globals and auto-updates UI
→ Remember to unsubscribe in destroy()!
```
### 6. Child Components (IMPORTANT)
```
Does this component need sub-components?
→ REUSE existing components, never recreate!
Available:
- ArcadeButton, GeminiIconButton → Buttons
- Modal → Dialogs/popups
- ProgressBar → Progress indicators
- SegmentedControl → Tab-like selection
- Tab → Tabs
- SoundPicker → Audio selection
- BasePetCard, TeamListItem → List items
- SeeMore → Expandable content
Example: A "SettingsPanel" component might use:
- SegmentedControl for sections
- Toggle for on/off settings
- ArcadeButton for actions
```
---
## Step 2: Create Structure
```
src/ui/components/<ComponentName>/
├── <ComponentName>.ts # Logic + factory function
├── <componentName>.css.ts # Styles (CSS string)
└── index.ts # Re-exports
```
**Read existing components for templates:** `src/ui/components/*/`
---
## Step 3: Required API
### Options Interface
```typescript
export interface <ComponentName>Options {
// Required (no default)
label: string;
// Optional (have defaults)
variant?: 'primary' | 'secondary';
disabled?: boolean;
// Event handlers
onClick?: () => void;
}
```
### Handle Interface
```typescript
export interface <ComponentName>Handle {
root: HTMLElement; // REQUIRED
set<Property>(value): void; // Public setters (minimal)
destroy(): void; // REQUIRED - cleanup
}
```
### Factory Function
```typescript
export function create<ComponentName>(options: <ComponentName>Options): <ComponentName>Handle
```
---
## Step 4: Style Rules
### Theme Tokens (REQUIRED)
```css
/* NO hardcoded colors */
background: var(--color-bg);
color: var(--color-text);
border: 1px solid var(--color-border);
```
### Responsive (REQUIRED)
```css
min-height: 44px; /* Touch-friendly */
width: 100%; /* Flexible, not fixed */
max-width: 300px; /* Constraint if needed */
```
### Scoped Styles
```css
/* Prefix all classes with component name */
.component-name { }
.component-name__label { }
.component-name--variant { }
```
---
## Step 5: Register
### Export → `src/ui/components/index.ts`
```typescript
export { create<ComponentName> } from './<ComponentName>/<ComponentName>';
export type { <ComponentName>Options, <ComponentName>Handle } from './<ComponentName>/<ComponentName>';
```
---
## Step 6: Validate
### Required
- [ ] `root: HTMLElement` in Handle
- [ ] `destroy()` removes ALL listeners/observers/intervals
- [ ] Factory function returns Handle
### Styling
- [ ] Uses CSS variables (no hardcoded colors)
- [ ] Touch-friendly (min 44px targets)
- [ ] Flexible widths (not fixed px)
- [ ] Focus states visible (`:focus-visible`)
### Composability
- [ ] Safe to nest inside other components
- [ ] No global CSS (scoped classes only)
- [ ] Styles injected into `root`, not `document.head`
- [ ] **Reuses existing components** (never recreate Button, Modal, ProgressBar, etc.)
- [ ] Child components' `destroy()` called in parent's `destroy()`
### If using Sprites
- [ ] Uses `MGSprite.toCanvas()` (never hardcoded paths)
### If using Globals (reactive)
- [ ] Subscribes in factory function
- [ ] **Unsubscribes in `destroy()`** (memory leak otherwise!)
- [ ] Updates UI elements on subscription callback
### If using Child Components
```typescript
import { createProgressBar, createArcadeButton } from '../index';
// In factory:
const progressBar = createProgressBar({ ... });
root.appendChild(progressBar.root);
// In destroy:
destroy() {
progressBar.destroy();
root.remove();
}
```
### If using Globals (reactive UI)
```typescript
import { getMyInventory } from '../../../globals/variables/myInventory';
// In factory:
const unsub = getMyInventory().subscribe((inventory) => {
// Update UI when inventory changes
updateItemCount(inventory.items.length);
});
// In destroy - CRITICAL!
destroy() {
unsub(); // Unsubscribe from Global
root.remove();
}
```
---
## References
- Rules: `.claude/rules/ui/components.md`
- Existing components: `src/ui/components/*/`
- Theme tokens: `src/ui/theme/`
- Reuse workflow: `.claude/workflows/ui/component/reuse-existing-component.md`Related Skills
interactive-component-creator
Build interactive web components and artifacts. Creates interactive UI elements, visualizations, and web-based applications.
fullstory-component-wellbeing
Expert guidance for monitoring frontend component health, performance, and rendering stability within Fullstory. Framework-agnostic patterns for React, Vue, Angular, Svelte, and React Native.
frontend-pages-components
Build responsive frontend pages, reusable components, layouts, and styling using modern best practices.
frontend-mobile-development-component-scaffold
You are a React component architecture expert specializing in scaffolding production-ready, accessible, and performant components. Generate complete component implementations with TypeScript, tests, s
frontend-component
Generate React components for IntelliFill following patterns (forwardRef, CVA variants, Radix UI, TailwindCSS). Use when creating UI components, forms, or pages.
components
React component architecture for creating composable, accessible components with data attributes. Use when creating/updating composable components, not for higher-level feature/page components.
component-fixtures
Use when creating or updating component fixtures for screenshot testing, or when designing UI components to be fixture-friendly. Covers fixture file structure, theming, service setup, CSS scoping, async rendering, and common pitfalls.
c4-component
Expert C4 Component-level documentation specialist. Synthesizes C4 Code-level documentation into Component-level architecture, defining component boundaries, interfaces, and relationships. Creates component diagrams and documentation. Use when synthesizing code-level documentation into logical components.
building-streamlit-custom-components-v2
Builds bidirectional Streamlit Custom Components v2 (CCv2) using `st.components.v2.component`. Use when authoring inline HTML/CSS/JS components or packaged components (manifest `asset_dir`, js/css globs), wiring state/trigger callbacks, theming via `--st-*` CSS variables, or bundling with Vite / `component-template` v2.
add-shadcn-component
Add shadcn/ui components via pnpm dlx, then normalize generated Tailwind color classes to Scaffa theme tokens
ui-design-create-component
Guided component creation with proper patterns Use when: the user asks to run the `create-component` workflow and the task requires multi-step orchestration. Do not use when: the task is small, single-step, and can be completed directly without orchestration overhead.
ui-components
UI component library patterns for shadcn/ui and Radix Primitives. Use when building accessible component libraries, customizing shadcn components, using Radix unstyled primitives, or creating design system foundations.