home / skills / popup-studio-ai / bkit-claude-code / phase-5-design-system

phase-5-design-system skill

/skills/phase-5-design-system

This skill helps you build a platform-independent design system with a reusable component library and design tokens across web, mobile, and frameworks.

npx playbooks add skill popup-studio-ai/bkit-claude-code --skill phase-5-design-system

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
13.4 KB
---
name: phase-5-design-system
description: |
  Skill for building platform-independent design systems.
  Develops consistent component libraries for all UI frameworks.

  Use proactively when user needs consistent UI components or mentions design tokens.

  Triggers: design system, component library, design tokens, shadcn, 디자인 시스템, デザインシステム, 设计系统,
  sistema de diseño, biblioteca de componentes, tokens de diseño,
  système de design, bibliothèque de composants, jetons de design,
  Design-System, Komponentenbibliothek, Design-Tokens,
  sistema di design, libreria di componenti, token di design

  Do NOT use for: one-off UI changes, backend development, or simple static sites.
imports:
  - ${PLUGIN_ROOT}/templates/pipeline/phase-5-design-system.template.md
# hooks: Managed by hooks/hooks.json (unified-write-post.js, unified-stop.js) - GitHub #9354 workaround
agent: bkit:pipeline-guide
allowed-tools:
  - Read
  - Write
  - Edit
  - Glob
  - Bash
user-invocable: false
next-skill: phase-6-ui-integration
pdca-phase: do
task-template: "[Phase-5] {feature}"
---

# Phase 5: Design System

> Build platform-independent design system

## Purpose

Build a reusable UI component library. Enable consistent design and fast development.

---

## What is a Design System?

### Definition

A design system is **a collection of reusable components and clear standards** that enables building consistent user experiences at scale.

### Why is it Needed? (Framework Agnostic)

| Problem | Design System Solution |
|---------|----------------------|
| Designer-developer mismatch | Single Source of Truth |
| Duplicate component development | Reusable component library |
| Inconsistent UI/UX | Unified design tokens and rules |
| Increased maintenance cost | Centralized change management |
| Delayed new member onboarding | Documented component catalog |

### 3 Layers of Design System

```
┌─────────────────────────────────────────────────────┐
│              Design Tokens                           │
│   Color, Typography, Spacing, Radius, Shadow, ...   │
├─────────────────────────────────────────────────────┤
│              Core Components                         │
│   Button, Input, Card, Dialog, Avatar, Badge, ...   │
├─────────────────────────────────────────────────────┤
│            Composite Components                      │
│   Form, DataTable, Navigation, SearchBar, ...       │
└─────────────────────────────────────────────────────┘
```

### Platform-specific Implementation Tools

| Platform | Recommended Tools | Design Token Method |
|----------|------------------|---------------------|
| **Web (React/Next.js)** | shadcn/ui, Radix | CSS Variables |
| **Web (Vue)** | Vuetify, PrimeVue | CSS Variables |
| **Flutter** | Material 3, Custom Theme | ThemeData |
| **iOS (SwiftUI)** | Native Components | Asset Catalog, Color Set |
| **Android (Compose)** | Material 3 | MaterialTheme |
| **React Native** | NativeBase, Tamagui | StyleSheet + Theme |

---

## What to Do in This Phase

1. **Install Base Components**: Button, Input, Card, etc.
2. **Customize**: Adjust to project style
3. **Composite Components**: Combine multiple base components
4. **Documentation**: Document component usage

## Deliverables

```
components/
└── ui/                     # shadcn/ui components
    ├── button.tsx
    ├── input.tsx
    ├── card.tsx
    └── ...

lib/
└── utils.ts                # Utilities (cn function, etc.)

docs/02-design/
└── design-system.md        # Design system specification
```

## PDCA Application

- **Plan**: Required component list
- **Design**: Component structure, variants design
- **Do**: Implement/customize components
- **Check**: Review consistency
- **Act**: Finalize and proceed to Phase 6

## Level-wise Application

| Level | Application Method |
|-------|-------------------|
| Starter | Optional (simple projects may skip) |
| Dynamic | Required |
| Enterprise | Required (including design tokens) |

## shadcn/ui Installation

```bash
# Initial setup
npx shadcn@latest init

# Add components
npx shadcn@latest add button
npx shadcn@latest add input
npx shadcn@latest add card
```

## Required Component List

### Basic
- Button, Input, Textarea
- Card, Badge, Avatar
- Dialog, Sheet, Popover

### Form
- Form, Label, Select
- Checkbox, Radio, Switch

### Navigation
- Navigation Menu, Tabs
- Breadcrumb, Pagination

## Custom Theme Building

### Design Token Override

shadcn/ui is CSS variable-based, so customize themes in `globals.css`.

```css
/* globals.css */
@layer base {
  :root {
    /* ===== Colors ===== */
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 221.2 83.2% 53.3%;      /* Brand main color */
    --primary-foreground: 210 40% 98%;
    --secondary: 210 40% 96.1%;
    --accent: 210 40% 96.1%;
    --destructive: 0 84.2% 60.2%;
    --muted: 210 40% 96.1%;
    --muted-foreground: 215.4 16.3% 46.9%;

    /* ===== Typography ===== */
    --font-sans: 'Pretendard', sans-serif;
    --font-mono: 'JetBrains Mono', monospace;

    /* ===== Spacing (rem units) ===== */
    --spacing-xs: 0.25rem;   /* 4px */
    --spacing-sm: 0.5rem;    /* 8px */
    --spacing-md: 1rem;      /* 16px */
    --spacing-lg: 1.5rem;    /* 24px */
    --spacing-xl: 2rem;      /* 32px */

    /* ===== Border Radius ===== */
    --radius: 0.5rem;
    --radius-sm: 0.25rem;
    --radius-lg: 0.75rem;
    --radius-full: 9999px;

    /* ===== Shadows ===== */
    --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
    --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
    --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 217.2 91.2% 59.8%;
    /* ... dark mode overrides */
  }
}
```

### Tailwind Config Extension

```js
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          50: 'hsl(var(--brand-50))',
          500: 'hsl(var(--brand-500))',
          900: 'hsl(var(--brand-900))',
        },
      },
      fontFamily: {
        sans: ['var(--font-sans)', 'system-ui'],
        mono: ['var(--font-mono)', 'monospace'],
      },
      spacing: {
        'xs': 'var(--spacing-xs)',
        'sm': 'var(--spacing-sm)',
        'md': 'var(--spacing-md)',
        'lg': 'var(--spacing-lg)',
        'xl': 'var(--spacing-xl)',
      },
      borderRadius: {
        'sm': 'var(--radius-sm)',
        'DEFAULT': 'var(--radius)',
        'lg': 'var(--radius-lg)',
        'full': 'var(--radius-full)',
      },
    },
  },
}
```

### Design Token Documentation

Recommended to create `docs/02-design/design-tokens.md` per project:

| Token | Value | Purpose |
|-------|-------|---------|
| `--primary` | `221.2 83.2% 53.3%` | Brand main color |
| `--radius` | `0.5rem` | Default border-radius |
| `--font-sans` | `Pretendard` | Body font |

## Component Customization

```tsx
// Extend default button to project style
const Button = React.forwardRef<
  HTMLButtonElement,
  ButtonProps & { isLoading?: boolean }
>(({ isLoading, children, ...props }, ref) => {
  return (
    <ButtonPrimitive ref={ref} {...props}>
      {isLoading ? <Spinner /> : children}
    </ButtonPrimitive>
  );
});
```

---

## Mobile App Design System

### Flutter: Custom Theme Building

Flutter defines design tokens through `ThemeData`.

```dart
// lib/theme/app_theme.dart
import 'package:flutter/material.dart';

class AppTheme {
  // ===== Design Tokens =====

  // Colors
  static const Color primary = Color(0xFF3B82F6);
  static const Color secondary = Color(0xFF64748B);
  static const Color destructive = Color(0xFFEF4444);
  static const Color background = Color(0xFFFFFFFF);
  static const Color foreground = Color(0xFF0F172A);

  // Spacing
  static const double spacingXs = 4.0;
  static const double spacingSm = 8.0;
  static const double spacingMd = 16.0;
  static const double spacingLg = 24.0;
  static const double spacingXl = 32.0;

  // Border Radius
  static const double radiusSm = 4.0;
  static const double radiusMd = 8.0;
  static const double radiusLg = 12.0;
  static const double radiusFull = 9999.0;

  // ===== Theme Data =====

  static ThemeData get lightTheme => ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: primary,
      brightness: Brightness.light,
    ),
    fontFamily: 'Pretendard',

    // Button Theme
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        padding: EdgeInsets.symmetric(
          horizontal: spacingMd,
          vertical: spacingSm,
        ),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(radiusMd),
        ),
      ),
    ),

    // Card Theme
    cardTheme: CardTheme(
      elevation: 2,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(radiusLg),
      ),
    ),

    // Input Theme
    inputDecorationTheme: InputDecorationTheme(
      border: OutlineInputBorder(
        borderRadius: BorderRadius.circular(radiusMd),
      ),
      contentPadding: EdgeInsets.all(spacingSm),
    ),
  );

  static ThemeData get darkTheme => ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: primary,
      brightness: Brightness.dark,
    ),
    fontFamily: 'Pretendard',
    // ... dark theme overrides
  );
}
```

### Flutter: Reusable Components

```dart
// lib/components/app_button.dart
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';

enum AppButtonVariant { primary, secondary, destructive, outline }

class AppButton extends StatelessWidget {
  final String label;
  final VoidCallback? onPressed;
  final AppButtonVariant variant;
  final bool isLoading;

  const AppButton({
    required this.label,
    this.onPressed,
    this.variant = AppButtonVariant.primary,
    this.isLoading = false,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: isLoading ? null : onPressed,
      style: _getStyle(),
      child: isLoading
          ? SizedBox(
              width: 20,
              height: 20,
              child: CircularProgressIndicator(strokeWidth: 2),
            )
          : Text(label),
    );
  }

  ButtonStyle _getStyle() {
    switch (variant) {
      case AppButtonVariant.destructive:
        return ElevatedButton.styleFrom(
          backgroundColor: AppTheme.destructive,
        );
      case AppButtonVariant.outline:
        return ElevatedButton.styleFrom(
          backgroundColor: Colors.transparent,
          side: BorderSide(color: AppTheme.primary),
        );
      default:
        return ElevatedButton.styleFrom();
    }
  }
}
```

### Flutter: Project Structure

```
lib/
├── theme/
│   ├── app_theme.dart          # ThemeData + Design Tokens
│   ├── app_colors.dart         # Color constants
│   ├── app_typography.dart     # TextStyle definitions
│   └── app_spacing.dart        # Spacing constants
├── components/
│   ├── app_button.dart
│   ├── app_input.dart
│   ├── app_card.dart
│   └── app_dialog.dart
└── main.dart
```

---

## Cross-Platform Design Token Sharing

### Design Token JSON (Platform Independent)

Centrally manage tokens with Figma Tokens or Style Dictionary.

```json
// tokens/design-tokens.json
{
  "color": {
    "primary": { "value": "#3B82F6" },
    "secondary": { "value": "#64748B" },
    "destructive": { "value": "#EF4444" }
  },
  "spacing": {
    "xs": { "value": "4px" },
    "sm": { "value": "8px" },
    "md": { "value": "16px" },
    "lg": { "value": "24px" }
  },
  "radius": {
    "sm": { "value": "4px" },
    "md": { "value": "8px" },
    "lg": { "value": "12px" }
  },
  "font": {
    "family": { "value": "Pretendard" },
    "size": {
      "sm": { "value": "14px" },
      "md": { "value": "16px" },
      "lg": { "value": "18px" }
    }
  }
}
```

### Platform-specific Conversion

```bash
# Generate tokens for each platform with Style Dictionary
npx style-dictionary build

# Output:
# - build/css/variables.css      (Web)
# - build/dart/app_tokens.dart   (Flutter)
# - build/swift/AppTokens.swift  (iOS)
# - build/kt/AppTokens.kt        (Android)
```

---

## Design System Checklist (Platform Agnostic)

### Required Items

- [ ] **Design Tokens Definition**
  - [ ] Colors (Primary, Secondary, Semantic)
  - [ ] Typography (Font Family, Sizes, Weights)
  - [ ] Spacing (xs, sm, md, lg, xl)
  - [ ] Border Radius
  - [ ] Shadows/Elevation

- [ ] **Core Components**
  - [ ] Button (variants: primary, secondary, outline, destructive)
  - [ ] Input/TextField
  - [ ] Card
  - [ ] Dialog/Modal
  - [ ] Avatar
  - [ ] Badge

- [ ] **Composite Components**
  - [ ] Form (with validation)
  - [ ] Navigation (Header, Sidebar, Bottom Nav)
  - [ ] Data Display (Table, List)

- [ ] **Documentation**
  - [ ] Component catalog (Storybook / Widgetbook)
  - [ ] Usage guidelines
  - [ ] Do's and Don'ts

---

## Template

See `templates/pipeline/phase-5-design-system.template.md`

## Next Phase

Phase 6: UI Implementation + API Integration → Components are ready, now implement actual screens

Overview

This skill builds platform-independent design systems and reusable component libraries that work across web, mobile, and native platforms. It focuses on design tokens, core and composite components, and theme wiring so teams deliver consistent UI quickly. Use it to centralize visual rules and accelerate component-driven development.

How this skill works

The skill generates a component scaffold (base components, composites) and a token-first theme system that can be exported per platform. It inspects project needs, suggests required components, and produces CSS-variable themes, Style Dictionary token outputs, and example component implementations (React/shadcn, Flutter, iOS/Android). It also creates documentation stubs and a PDCA checklist to iterate on the system.

When to use it

  • You need a reusable component library across multiple UI frameworks
  • You want to centralize design tokens and export them to web/mobile
  • Onboard new designers and developers with a single source of truth
  • Preparing a project for scale or long-term maintenance
  • Migrating inconsistent UI into a unified design system

Best practices

  • Start with a small required component list (buttons, inputs, cards) and expand iteratively
  • Define tokens first (color, spacing, typography) and generate platform outputs via Style Dictionary
  • Keep core components framework-agnostic and provide thin platform adapters
  • Document usage, variants, and Do/Don't guidance alongside code examples
  • Use PDCA: plan tokens/components, implement, review consistency, then iterate

Example use cases

  • Create a CSS-variable theme and shadcn/ui component set for a React/Next.js product
  • Generate Flutter ThemeData and reusable widgets from centralized design tokens
  • Produce platform token outputs (CSS, Dart, Swift, Kotlin) using Style Dictionary
  • Extend a default button component with loading state and variant styles for a product
  • Set up a component catalog and checklist for enterprise-level design governance

FAQ

Is this skill suitable for single-page marketing sites?

No. It is designed for reusable systems. For one-off static pages, a lightweight styling approach is better.

How are tokens shared between platforms?

Define tokens in a JSON source and use Style Dictionary or Figma Tokens to generate platform-specific outputs (CSS vars, Dart, Swift, Kotlin).