add-component

Create a reusable UI component with factory pattern, theme compatibility, and proper cleanup

16 stars

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

$curl -o ~/.claude/skills/add-component/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/add-component/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/add-component/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How add-component Compares

Feature / Agentadd-componentStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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

16
from diegosouzapw/awesome-omni-skill

Build interactive web components and artifacts. Creates interactive UI elements, visualizations, and web-based applications.

fullstory-component-wellbeing

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

Build responsive frontend pages, reusable components, layouts, and styling using modern best practices.

frontend-mobile-development-component-scaffold

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

Generate React components for IntelliFill following patterns (forwardRef, CVA variants, Radix UI, TailwindCSS). Use when creating UI components, forms, or pages.

components

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

Add shadcn/ui components via pnpm dlx, then normalize generated Tailwind color classes to Scaffa theme tokens

ui-design-create-component

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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.