skills/sanky369/vibe-building-skills/component-architecture

component-architecture

SKILL.md

Component Architecture

Overview

Components are the building blocks of modern interfaces. A well-designed component system enables consistency, speeds up development, and makes maintenance easier. This skill teaches you to think about components systematically: designing for reusability, managing complexity, documenting thoroughly, and building a library that your team loves to use.

Core Methodology: Atomic Design

Atomic Design is a methodology for creating design systems by breaking down interfaces into fundamental building blocks.

The Five Levels

1. Atoms The smallest, most basic components. They can't be broken down further without losing their meaning.

Examples: Button, Input, Label, Icon, Badge, Spinner

Characteristics:

  • Single responsibility
  • Highly reusable
  • No dependencies on other components (except styling)
  • Fully self-contained

Example Atom: Button

interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  disabled?: boolean;
  loading?: boolean;
  onClick?: () => void;
  children: React.ReactNode;
}

export const Button: React.FC<ButtonProps> = ({
  variant = 'primary',
  size = 'md',
  disabled = false,
  loading = false,
  onClick,
  children,
}) => {
  return (
    <button
      className={`button button--${variant} button--${size}`}
      disabled={disabled || loading}
      onClick={onClick}
    >
      {loading && <Spinner size="sm" />}
      {children}
    </button>
  );
};

2. Molecules Groups of atoms bonded together to form relatively simple functional units.

Examples: Form Input (Label + Input + Error Message), Search Bar (Icon + Input + Button), Card Header (Avatar + Name + Date)

Characteristics:

  • Composed of atoms
  • Serve a specific purpose
  • Reusable across the product
  • Have a clear interface (props)

Example Molecule: Form Input

interface FormInputProps {
  label: string;
  placeholder?: string;
  error?: string;
  value: string;
  onChange: (value: string) => void;
  disabled?: boolean;
}

export const FormInput: React.FC<FormInputProps> = ({
  label,
  placeholder,
  error,
  value,
  onChange,
  disabled,
}) => {
  return (
    <div className="form-input">
      <Label>{label}</Label>
      <Input
        placeholder={placeholder}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        disabled={disabled}
        aria-invalid={!!error}
      />
      {error && <ErrorMessage>{error}</ErrorMessage>}
    </div>
  );
};

3. Organisms Relatively complex UI sections composed of groups of molecules and/or atoms and/or other organisms.

Examples: Navigation Bar, Form, Card, Modal, Sidebar

Characteristics:

  • Composed of molecules and atoms
  • Serve a specific business purpose
  • More complex interfaces
  • Often have state management

Example Organism: Card

interface CardProps {
  title: string;
  description?: string;
  image?: string;
  action?: {
    label: string;
    onClick: () => void;
  };
  children?: React.ReactNode;
}

export const Card: React.FC<CardProps> = ({
  title,
  description,
  image,
  action,
  children,
}) => {
  return (
    <div className="card">
      {image && <img src={image} alt={title} className="card-image" />}
      <div className="card-content">
        <h3 className="card-title">{title}</h3>
        {description && <p className="card-description">{description}</p>}
        {children}
        {action && (
          <Button onClick={action.onClick} variant="secondary">
            {action.label}
          </Button>
        )}
      </div>
    </div>
  );
};

4. Templates Page-level objects that place components into a layout and articulate the design's underlying content structure.

Examples: Blog Post Template, Product Page Template, Dashboard Template

Characteristics:

  • Composed of organisms, molecules, and atoms
  • Define page structure and layout
  • Show how components work together
  • Not typically reusable (specific to page type)

Example Template: Blog Post

export const BlogPostTemplate: React.FC<BlogPostTemplateProps> = ({
  title,
  author,
  date,
  image,
  content,
  relatedPosts,
}) => {
  return (
    <div className="blog-post-template">
      <Header />
      <article className="blog-post">
        <div className="blog-post-hero">
          <img src={image} alt={title} />
        </div>
        <div className="blog-post-content">
          <h1>{title}</h1>
          <div className="blog-post-meta">
            <Avatar src={author.avatar} alt={author.name} />
            <span>{author.name}</span>
            <span>{formatDate(date)}</span>
          </div>
          <div className="blog-post-body">{content}</div>
        </div>
      </article>
      <section className="related-posts">
        <h2>Related Posts</h2>
        <div className="related-posts-grid">
          {relatedPosts.map((post) => (
            <Card key={post.id} {...post} />
          ))}
        </div>
      </section>
      <Footer />
    </div>
  );
};

5. Pages Specific instances of templates that show what the UI looks like with real data.

Examples: Homepage, Product Page, User Profile, Dashboard

Characteristics:

  • Instances of templates with real data
  • Used for testing and demonstration
  • Show how components behave with actual content
  • Help identify edge cases and issues

Component Design Principles

Principle 1: Single Responsibility

Each component should have one clear purpose. If a component does too much, break it down.

Bad:

// Does too much: rendering, data fetching, form handling, validation
const UserProfile = () => {
  const [user, setUser] = useState(null);
  const [formData, setFormData] = useState({});
  const [errors, setErrors] = useState({});
  
  useEffect(() => {
    fetchUser().then(setUser);
  }, []);
  
  const handleSubmit = () => {
    // validation logic
    // submission logic
  };
  
  return (
    // complex JSX
  );
};

Good:

// UserProfile: Orchestrates the page
const UserProfile = () => {
  const { user } = useUser();
  return (
    <>
      <UserHeader user={user} />
      <UserEditForm user={user} />
      <UserActivity user={user} />
    </>
  );
};

// UserHeader: Displays user info
const UserHeader = ({ user }) => (
  <div className="user-header">
    <Avatar src={user.avatar} />
    <h1>{user.name}</h1>
  </div>
);

// UserEditForm: Handles form state and submission
const UserEditForm = ({ user }) => {
  // form logic
};

// UserActivity: Displays user activity
const UserActivity = ({ user }) => {
  // activity logic
};

Principle 2: Composition Over Inheritance

Build complex components by composing simpler ones, not by inheritance.

Bad:

// Inheritance approach (avoid)
class Button extends React.Component {}
class PrimaryButton extends Button {}
class LargeButton extends Button {}
class LargePrimaryButton extends Button {}

Good:

// Composition approach (prefer)
const Button = ({ variant = 'primary', size = 'md', ...props }) => (
  <button className={`button button--${variant} button--${size}`} {...props} />
);

// Use composition to create variants
const PrimaryButton = (props) => <Button variant="primary" {...props} />;
const LargeButton = (props) => <Button size="lg" {...props} />;
const LargePrimaryButton = (props) => <Button variant="primary" size="lg" {...props} />;

Principle 3: Props Interface Design

Design component props carefully. Props should be:

  • Intuitive — Props should be self-explanatory
  • Flexible — Props should support common use cases
  • Constrained — Props should prevent invalid states
  • Documented — Props should be clearly documented

Example: Well-Designed Props

interface ButtonProps {
  // Variant and size are constrained to valid options
  variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  
  // Boolean props are explicit
  disabled?: boolean;
  loading?: boolean;
  fullWidth?: boolean;
  
  // Callbacks are clearly named
  onClick?: () => void;
  onHover?: () => void;
  
  // Content is flexible
  children: React.ReactNode;
  icon?: React.ReactNode;
  
  // HTML attributes can be passed through
  className?: string;
  'aria-label'?: string;
}

Principle 4: Controlled vs. Uncontrolled

Be explicit about whether a component is controlled (parent manages state) or uncontrolled (component manages state).

Controlled Component:

const ControlledInput = ({ value, onChange }) => (
  <input value={value} onChange={(e) => onChange(e.target.value)} />
);

// Parent manages state
const Parent = () => {
  const [value, setValue] = useState('');
  return <ControlledInput value={value} onChange={setValue} />;
};

Uncontrolled Component:

const UncontrolledInput = ({ defaultValue, onSubmit }) => {
  const inputRef = useRef(null);
  
  return (
    <>
      <input ref={inputRef} defaultValue={defaultValue} />
      <button onClick={() => onSubmit(inputRef.current.value)}>Submit</button>
    </>
  );
};

// Parent doesn't manage state
const Parent = () => {
  return <UncontrolledInput onSubmit={(value) => console.log(value)} />;
};

Component Variants

Defining Variants

Variants are different versions of a component for different contexts. Define them clearly:

interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  state?: 'default' | 'hover' | 'active' | 'disabled' | 'loading';
}

// Variants matrix
const Button = ({ variant = 'primary', size = 'md', state = 'default', ...props }) => {
  const variantClass = `button--${variant}`;
  const sizeClass = `button--${size}`;
  const stateClass = `button--${state}`;
  
  return (
    <button className={`button ${variantClass} ${sizeClass} ${stateClass}`} {...props} />
  );
};

// Usage
<Button variant="primary" size="md" state="default">Primary</Button>
<Button variant="secondary" size="lg" state="hover">Secondary Large</Button>
<Button variant="danger" size="sm" state="disabled">Delete</Button>

Variant Documentation

Document all variants with examples:

# Button Component

## Variants

### Variant: primary
- Default button style
- Used for primary actions
- Example: "Save", "Submit", "Create"

### Variant: secondary
- Secondary button style
- Used for secondary actions
- Example: "Cancel", "Back", "Skip"

### Variant: ghost
- Minimal button style
- Used for tertiary actions
- Example: "Learn More", "View Details"

### Variant: danger
- Danger button style
- Used for destructive actions
- Example: "Delete", "Remove", "Discard"

## Sizes

### Size: sm
- 32px height
- 12px font size
- Used in compact spaces

### Size: md
- 40px height
- 14px font size
- Default size

### Size: lg
- 48px height
- 16px font size
- Used for prominent actions

## States

### State: default
- Normal appearance

### State: hover
- Slightly darker or lighter
- Indicates interactivity

### State: active
- Pressed appearance
- Indicates the button is being clicked

### State: disabled
- Grayed out
- Cursor is not-allowed
- Not clickable

### State: loading
- Shows spinner
- Indicates action in progress
- Not clickable

Component Documentation

What to Document

  1. Purpose — What does this component do?
  2. Props — What props does it accept?
  3. Variants — What variants are available?
  4. States — What states can it be in?
  5. Examples — How do you use it?
  6. Accessibility — What accessibility features does it have?
  7. Edge Cases — What edge cases should you be aware of?

Documentation Template

# Component Name

## Purpose
Brief description of what this component does and when to use it.

## Props

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `variant` | 'primary' \| 'secondary' | 'primary' | Visual variant |
| `size` | 'sm' \| 'md' \| 'lg' | 'md' | Component size |
| `disabled` | boolean | false | Disable the component |
| `children` | ReactNode | - | Component content |

## Variants

### Primary
Used for primary actions.
```jsx
<Button variant="primary">Primary Action</Button>

Secondary

Used for secondary actions.

<Button variant="secondary">Secondary Action</Button>

States

Default

Normal appearance.

Disabled

Grayed out, not clickable.

<Button disabled>Disabled</Button>

Loading

Shows spinner, not clickable.

<Button loading>Loading...</Button>

Accessibility

  • Keyboard accessible (Enter, Space to activate)
  • Screen reader friendly (announces button text)
  • Focus visible (outline on focus)
  • Aria-label support for icon-only buttons

Examples

Basic Button

<Button onClick={() => alert('Clicked!')}>Click Me</Button>

With Icon

<Button icon={<SaveIcon />}>Save</Button>

Full Width

<Button fullWidth>Full Width Button</Button>

Edge Cases

  • Icon-only buttons must have aria-label
  • Disabled buttons should not be clickable
  • Loading state should show spinner
  • Very long text should wrap or truncate

## How to Use This Skill with Claude Code

### Audit Your Components

"I'm using the component-architecture skill. Can you audit my components?

  • Identify components that violate single responsibility
  • Suggest component composition improvements
  • Check component documentation completeness
  • Identify reusable patterns I'm missing
  • Suggest component library structure"

### Design a Component System

"Can you help me design a component system?

  • Define atomic components (atoms, molecules, organisms)
  • Create component architecture
  • Design component props interfaces
  • Define variants for each component
  • Create component documentation"

### Refactor Components

"Can you help me refactor my components?

  • Break down complex components
  • Improve component composition
  • Simplify prop interfaces
  • Add missing variants
  • Improve documentation"

### Generate Component Library

"Can you generate a component library?

  • Create all atomic components (Button, Input, Label, etc.)
  • Create molecules (FormInput, SearchBar, etc.)
  • Create organisms (Card, Modal, etc.)
  • Include TypeScript types
  • Include Tailwind CSS styling
  • Include comprehensive documentation"

## Design Critique: Evaluating Your Components

Claude Code can critique your components:

"Can you evaluate my component architecture?

  • Are my components following single responsibility?
  • Is my component composition good?
  • Are my prop interfaces well-designed?
  • Is my documentation comprehensive?
  • What's one thing I could improve immediately?"

## Integration with Other Skills

- **design-foundation** — Component tokens and styling
- **layout-system** — Component layout patterns
- **typography-system** — Component typography
- **color-system** — Component colors
- **accessibility-excellence** — Component accessibility
- **interaction-design** — Component interactions

## Key Principles

**1. Single Responsibility**
Each component should have one clear purpose.

**2. Composition Over Inheritance**
Build complex components by composing simpler ones.

**3. Props Interface Design**
Design props carefully for clarity and flexibility.

**4. Variants Enable Reusability**
Well-designed variants make components reusable across contexts.

**5. Documentation Enables Adoption**
Comprehensive documentation helps your team use components effectively.

## Checklist: Is Your Component Architecture Ready?

- [ ] Components follow single responsibility principle
- [ ] Components are composed from simpler components
- [ ] Props interfaces are well-designed and documented
- [ ] All variants are defined and documented
- [ ] All states are defined and documented
- [ ] Components are accessible (keyboard, screen reader, focus)
- [ ] Components have comprehensive documentation
- [ ] Component library is organized (atoms, molecules, organisms)
- [ ] Components are reusable across the product
- [ ] Components are tested (unit tests, visual tests)

A well-designed component architecture is the foundation of a scalable, maintainable product.
Weekly Installs
17
First Seen
Jan 24, 2026
Installed on
claude-code13
gemini-cli13
codex13
antigravity12
opencode12
cline8