Initial commit
This commit is contained in:
21
.claude-plugin/plugin.json
Normal file
21
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "frontend-nextjs-development",
|
||||
"description": "Next.js開発向けのツール群(Figmaデザイン抽出、コンポーネント生成など)",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "TOYOTA, Yoichi",
|
||||
"email": "y.toyota@xtone.co.jp"
|
||||
},
|
||||
"skills": [
|
||||
"./skills"
|
||||
],
|
||||
"agents": [
|
||||
"./agents"
|
||||
],
|
||||
"commands": [
|
||||
"./commands"
|
||||
],
|
||||
"hooks": [
|
||||
"./hooks"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# frontend-nextjs-development
|
||||
|
||||
Next.js開発向けのツール群(Figmaデザイン抽出、コンポーネント生成など)
|
||||
0
agents/.gitkeep
Normal file
0
agents/.gitkeep
Normal file
0
commands/.gitkeep
Normal file
0
commands/.gitkeep
Normal file
0
hooks/.gitkeep
Normal file
0
hooks/.gitkeep
Normal file
78
hooks/biome-format/biome_format.sh
Executable file
78
hooks/biome-format/biome_format.sh
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 対象ファイル拡張子のリスト
|
||||
TARGET_EXTENSIONS=("ts" "tsx" "js" "jsx")
|
||||
|
||||
# 標準入力からJSONデータを読み取り
|
||||
input_data=$(cat)
|
||||
|
||||
# ファイルパスを取得
|
||||
file_path=$(echo "$input_data" | jq -r '.tool_input.file_path')
|
||||
|
||||
# 対象ファイル拡張子かチェック
|
||||
is_target_file=false
|
||||
for ext in "${TARGET_EXTENSIONS[@]}"; do
|
||||
if [[ "$file_path" == *".$ext" ]]; then
|
||||
is_target_file=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$is_target_file" = false ]; then
|
||||
echo "Not a target file extension: $file_path"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ファイルパスを絶対パスに変換
|
||||
if [[ "$file_path" != /* ]]; then
|
||||
file_path="$(pwd)/$file_path"
|
||||
fi
|
||||
|
||||
# ファイルが存在するかチェック
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "File not found: $file_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ファイルのディレクトリから上位ディレクトリへ遡ってbiome.jsonを探す
|
||||
find_biome_config() {
|
||||
local current_dir="$1"
|
||||
|
||||
while [ "$current_dir" != "/" ]; do
|
||||
if [ -f "$current_dir/biome.json" ]; then
|
||||
echo "$current_dir"
|
||||
return 0
|
||||
fi
|
||||
current_dir=$(dirname "$current_dir")
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# ファイルのディレクトリを取得
|
||||
file_dir=$(dirname "$file_path")
|
||||
|
||||
# biome.jsonを探す
|
||||
config_dir=$(find_biome_config "$file_dir")
|
||||
|
||||
if [ -z "$config_dir" ]; then
|
||||
echo "biome.json not found, using default configuration"
|
||||
echo "Formatting $file_path with Biome (default config)"
|
||||
# デフォルト設定でbiome formatを実行
|
||||
if npx @biomejs/biome format --write "$file_path"; then
|
||||
echo "Successfully formatted: $file_path"
|
||||
else
|
||||
echo "Error: Failed to format $file_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Found biome.json in: $config_dir"
|
||||
echo "Formatting $file_path with Biome"
|
||||
# biome.jsonがあるディレクトリに移動してから実行
|
||||
if (cd "$config_dir" && npx @biomejs/biome format --write "$file_path"); then
|
||||
echo "Successfully formatted: $file_path"
|
||||
else
|
||||
echo "Error: Failed to format $file_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
15
hooks/biome-format/hooks.json
Normal file
15
hooks/biome-format/hooks.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit|MultiEdit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/biome-format/biome_format.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
101
plugin.lock.json
Normal file
101
plugin.lock.json
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:xtone/ai_development_tools:frontend_nextjs_development",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "a313d080117093ed3f0915c5436e3d49e8421a4d",
|
||||
"treeHash": "6da52c159f168a91d79211e089a6cea35fe15ba123afd5880d5605174c3fdcc7",
|
||||
"generatedAt": "2025-11-28T10:29:07.551763Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "frontend-nextjs-development",
|
||||
"description": "Next.js開発向けのツール群(Figmaデザイン抽出、コンポーネント生成など)",
|
||||
"version": null
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "37139ec3e65ca7200660a2ec71937053399bd471037991f0f0b55ce36fe01cbe"
|
||||
},
|
||||
{
|
||||
"path": "agents/.gitkeep",
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
{
|
||||
"path": "hooks/.gitkeep",
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
{
|
||||
"path": "hooks/biome-format/biome_format.sh",
|
||||
"sha256": "064108157ecb568b4df53d5f56cffea602ec6c5907fe54b21686faf40fecddb7"
|
||||
},
|
||||
{
|
||||
"path": "hooks/biome-format/hooks.json",
|
||||
"sha256": "0390affba95e1fe7b91ce819d916de8d94735483bdd33eee39b9d9a33fbe4ece"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "b82642e648ee77b5a7eeaf171401510729b5b774da1ace78fcf1c982dd2126d9"
|
||||
},
|
||||
{
|
||||
"path": "commands/.gitkeep",
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
{
|
||||
"path": "skills/nextjs-react-implementation/SKILL.md",
|
||||
"sha256": "08efc9ad2f1273c94e82c86cdfc7990fec404877e4f8b505777208f740d62ec1"
|
||||
},
|
||||
{
|
||||
"path": "skills/nextjs-react-implementation/assets/templates/test.tsx.template",
|
||||
"sha256": "47638d23b1eb08923a4bd11c7422314e30b22ccc9854e8c3d18a5e0253594bb7"
|
||||
},
|
||||
{
|
||||
"path": "skills/nextjs-react-implementation/assets/templates/storybook.tsx.template",
|
||||
"sha256": "3193dc582cf21b9f0c8ae6be68daab1fe8a747f4dd12789309caef744cc2e643"
|
||||
},
|
||||
{
|
||||
"path": "skills/nextjs-react-implementation/assets/templates/component.tsx.template",
|
||||
"sha256": "21f27ad6efff3c604408a5e948f90fb819b1ad700d88b7ac4cc6523b76f47f38"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/SKILL.md",
|
||||
"sha256": "7ef7f3778b1bee298696c206fbaf37fcb11417a3f3498f44f5c747f7cf58d328"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/references/typography-extraction-guide.md",
|
||||
"sha256": "b28d040a192271344889e623b7abaa0d92aea015582096b1497f072e0fbde21a"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/references/spacing-extraction-guide.md",
|
||||
"sha256": "1735da6037d870a75d7a5cc995e34f0a161b2828ba71b562002d26bbc63b0e4b"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/references/atomic-design-classification.md",
|
||||
"sha256": "b1a9e205f6881d2e9e7fdf332ea42c926141cd17416febdcbf2404c4295a9330"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/references/semantic-html-guide.md",
|
||||
"sha256": "fa49fe94cd118722a1467775f7bbe1258a9c46fa042a1ecd28fa74d8e0a63625"
|
||||
},
|
||||
{
|
||||
"path": "skills/figma-design-analyzer/references/layout-analysis-guide.md",
|
||||
"sha256": "a0911aef52cb0b26c462ae9238c16d7b9eae0295bbe8272141d35f76cadd453b"
|
||||
}
|
||||
],
|
||||
"dirSha256": "6da52c159f168a91d79211e089a6cea35fe15ba123afd5880d5605174c3fdcc7"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
543
skills/figma-design-analyzer/SKILL.md
Normal file
543
skills/figma-design-analyzer/SKILL.md
Normal file
@@ -0,0 +1,543 @@
|
||||
---
|
||||
name: figma-design-analyzer
|
||||
description: Extract and analyze Figma designs to create structured design specifications. Use this skill when you need to analyze Figma nodes, extract design properties (layout, spacing, typography), classify components using Atomic Design principles, and generate design specification documents that can be used for implementation.
|
||||
---
|
||||
|
||||
# Figma Design Analyzer
|
||||
|
||||
## Overview
|
||||
|
||||
Systematically analyze Figma designs and extract structured design specifications. This skill focuses on understanding design intent, extracting accurate properties, and creating comprehensive design specification documents that serve as blueprints for implementation.
|
||||
|
||||
**Use this skill when:**
|
||||
- Analyzing Figma designs to understand structure and properties
|
||||
- Extracting design tokens and component specifications
|
||||
- Classifying components according to Atomic Design principles
|
||||
- Creating design specification documents for developers
|
||||
- Comparing existing implementations with Figma designs
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Step 1: Extract Figma Design Information
|
||||
|
||||
When given a Figma URL or node ID, use Figma MCP tools to extract design data:
|
||||
|
||||
1. **Parse the Figma URL to extract node ID:**
|
||||
```
|
||||
URL: https://figma.com/design/fileKey/fileName?node-id=1-2
|
||||
Node ID: 1:2 (replace - with :)
|
||||
```
|
||||
|
||||
2. **Extract node design context:**
|
||||
```
|
||||
mcp__figma-dev__get_design_context(
|
||||
nodeId: "1:2",
|
||||
dirForAssetWrites: "/absolute/path/to/project/public/assets",
|
||||
clientLanguages: "typescript",
|
||||
clientFrameworks: "react,nextjs"
|
||||
)
|
||||
```
|
||||
This returns the design code, including HTML structure and CSS properties.
|
||||
|
||||
3. **Get component metadata for structure overview:**
|
||||
```
|
||||
mcp__figma-dev__get_metadata(
|
||||
nodeId: "1:2",
|
||||
clientLanguages: "typescript",
|
||||
clientFrameworks: "react,nextjs"
|
||||
)
|
||||
```
|
||||
Use this to understand the component hierarchy before detailed analysis.
|
||||
|
||||
4. **Check for Figma variables (design tokens):**
|
||||
```
|
||||
mcp__figma-dev__get_variable_defs(
|
||||
nodeId: "1:2",
|
||||
clientLanguages: "typescript",
|
||||
clientFrameworks: "react,nextjs"
|
||||
)
|
||||
```
|
||||
Extract design system tokens for colors, typography, spacing, etc.
|
||||
|
||||
5. **Verify Code Connect mappings:**
|
||||
```
|
||||
mcp__figma-dev__get_code_connect_map(
|
||||
nodeId: "1:2",
|
||||
clientLanguages: "typescript",
|
||||
clientFrameworks: "react,nextjs"
|
||||
)
|
||||
```
|
||||
Check if the component is already mapped to existing code.
|
||||
|
||||
### Step 2: Handle Component Instances and Variants
|
||||
|
||||
**Important:** When the node is a component instance:
|
||||
|
||||
1. **Identify if it's an instance:**
|
||||
- Check metadata for "component instance" type
|
||||
- Note the main component ID
|
||||
|
||||
2. **Get the main component:**
|
||||
- Use `get_design_context` on the main component node
|
||||
- Extract the base structure and properties
|
||||
|
||||
3. **Extract instance-specific properties:**
|
||||
- Get the instance's specific size, device, and variant settings
|
||||
- Note any overrides (text, images, colors, etc.)
|
||||
|
||||
4. **Handle variants:**
|
||||
- If the main component uses variants, identify the variant mode
|
||||
- Extract the correct variant values for the instance
|
||||
- Document variant properties for props mapping
|
||||
|
||||
### Step 3: Classify the Component
|
||||
|
||||
Use Atomic Design principles to classify the component:
|
||||
|
||||
1. **Read the classification guide:**
|
||||
```
|
||||
Read references/atomic-design-classification.md
|
||||
```
|
||||
|
||||
2. **Apply the decision tree:**
|
||||
- **Atom**: Indivisible, single purpose (button, input, icon, text label)
|
||||
- **Molecule**: 2-5 atoms, simple combination (search bar, form field)
|
||||
- **Organism**: Complex, multiple molecules/atoms (header, card, form)
|
||||
|
||||
3. **Determine the component category:**
|
||||
- Document: `atomicCategory: Atom | Molecule | Organism`
|
||||
|
||||
### Step 4: Analyze Layout and Spacing
|
||||
|
||||
Extract accurate layout information:
|
||||
|
||||
1. **Read layout analysis guide:**
|
||||
```
|
||||
Read references/layout-analysis-guide.md
|
||||
```
|
||||
|
||||
2. **Determine layout method:**
|
||||
- **Auto Layout** → Flexbox
|
||||
- Check: direction (row/column), justify-content, align-items
|
||||
- **Grid structure** → CSS Grid
|
||||
- Check: grid-template-columns, grid-template-rows, gap
|
||||
- **Overlapping elements** → Absolute positioning
|
||||
- Check: position, top, left, z-index
|
||||
|
||||
3. **Extract spacing values:**
|
||||
```
|
||||
Read references/spacing-extraction-guide.md
|
||||
```
|
||||
- **Padding**: Internal spacing (px, py, pt, pr, pb, pl)
|
||||
- **Gap**: Spacing between flex/grid items
|
||||
- **Margin**: External spacing (rarely used, prefer gap)
|
||||
|
||||
4. **Map to Tailwind classes:**
|
||||
- Use standard Tailwind scale when possible (p-4, gap-6, etc.)
|
||||
- Use arbitrary values `[value]` for custom sizes (p-[18px])
|
||||
|
||||
5. **Document in specification:**
|
||||
```markdown
|
||||
## Layout
|
||||
- Method: Flexbox
|
||||
- Direction: row
|
||||
- Justify: center
|
||||
- Align: center
|
||||
|
||||
## Spacing
|
||||
- Padding: px-6 py-3
|
||||
- Gap: gap-2
|
||||
- Border Radius: rounded-lg
|
||||
```
|
||||
|
||||
### Step 5: Extract Typography
|
||||
|
||||
Extract accurate text styling:
|
||||
|
||||
1. **Read typography guide:**
|
||||
```
|
||||
Read references/typography-extraction-guide.md
|
||||
```
|
||||
|
||||
2. **Extract font properties:**
|
||||
- Font family (font-sans, font-serif, custom)
|
||||
- Font size (text-sm, text-base, text-lg, etc.)
|
||||
- Font weight (font-normal, font-semibold, font-bold)
|
||||
- Line height (leading-tight, leading-normal, etc.)
|
||||
- Letter spacing (tracking-tight, tracking-wide, etc.)
|
||||
- Text color (text-gray-900, text-white, etc.)
|
||||
- Text alignment (text-left, text-center, text-right)
|
||||
- Text decoration (underline, line-through)
|
||||
- Text transform (uppercase, lowercase, capitalize)
|
||||
|
||||
3. **Map to Tailwind classes:**
|
||||
- Use standard Tailwind typography classes
|
||||
- Check for design tokens in Figma variables
|
||||
- Use arbitrary values for custom sizes
|
||||
|
||||
4. **Document in specification:**
|
||||
```markdown
|
||||
## Typography
|
||||
- Font: text-base font-semibold
|
||||
- Color: text-white
|
||||
- Line Height: leading-normal
|
||||
- Alignment: text-center
|
||||
```
|
||||
|
||||
### Step 6: Choose Semantic HTML
|
||||
|
||||
Select appropriate HTML elements:
|
||||
|
||||
1. **Read semantic HTML guide:**
|
||||
```
|
||||
Read references/semantic-html-guide.md
|
||||
```
|
||||
|
||||
2. **Apply semantic rules:**
|
||||
- **Sections**: `<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>`
|
||||
- **Headings**: `<h1>` to `<h6>` (respect hierarchy)
|
||||
- **Interactive**: `<button>` for actions, `<a>` for navigation
|
||||
- **Content**: `<article>`, `<section>` for grouping
|
||||
- **Forms**: `<form>`, `<input>`, `<label>`, `<select>`, `<textarea>`
|
||||
- **Lists**: `<ul>`, `<ol>`, `<li>` for lists
|
||||
- **Media**: `<img>`, `<video>`, `<audio>`, `<figure>`, `<figcaption>`
|
||||
|
||||
3. **Consider accessibility:**
|
||||
- Add ARIA attributes when semantic HTML is insufficient
|
||||
- Ensure keyboard accessibility
|
||||
- Verify color contrast ratios
|
||||
|
||||
4. **Document in specification:**
|
||||
```markdown
|
||||
## Semantic HTML
|
||||
- Root Element: button
|
||||
- ARIA: role="button" aria-label="Submit"
|
||||
```
|
||||
|
||||
### Step 7: Extract Colors and Visual Properties
|
||||
|
||||
Extract color and visual styling:
|
||||
|
||||
1. **Extract color properties:**
|
||||
- Background color (bg-blue-500, bg-gradient-to-r, etc.)
|
||||
- Text color (text-white, text-gray-900, etc.)
|
||||
- Border color (border-gray-300, etc.)
|
||||
|
||||
2. **Extract visual properties:**
|
||||
- Border radius (rounded, rounded-lg, rounded-full, etc.)
|
||||
- Border width (border, border-2, etc.)
|
||||
- Box shadow (shadow, shadow-md, shadow-lg, etc.)
|
||||
- Opacity (opacity-50, opacity-100, etc.)
|
||||
|
||||
3. **Check Figma variables:**
|
||||
- Look for design token mappings
|
||||
- Use semantic color names when available
|
||||
|
||||
4. **Document in specification:**
|
||||
```markdown
|
||||
## Colors
|
||||
- Background: bg-blue-500
|
||||
- Hover: hover:bg-blue-600
|
||||
- Text: text-white
|
||||
- Border: border-transparent
|
||||
|
||||
## Visual Properties
|
||||
- Border Radius: rounded-lg
|
||||
- Shadow: shadow-md
|
||||
```
|
||||
|
||||
### Step 8: Handle Responsive Designs
|
||||
|
||||
When multiple Figma nodes represent different device sizes:
|
||||
|
||||
1. **Extract all node IDs** from provided URLs
|
||||
- Desktop node
|
||||
- Tablet node
|
||||
- Mobile node
|
||||
|
||||
2. **Analyze each node:**
|
||||
- Layout changes (grid columns, flex direction)
|
||||
- Spacing changes
|
||||
- Typography changes (font size, line height)
|
||||
- Hidden/shown elements
|
||||
|
||||
3. **Document responsive variations:**
|
||||
```markdown
|
||||
## Responsive Behavior
|
||||
- Mobile (default): flex-col gap-4 text-sm
|
||||
- Tablet (md): md:flex-row md:gap-6 md:text-base
|
||||
- Desktop (lg): lg:gap-8 lg:text-lg
|
||||
```
|
||||
|
||||
### Step 9: Generate Design Specification Document
|
||||
|
||||
Create a comprehensive design specification:
|
||||
|
||||
1. **Use Markdown format with front matter:**
|
||||
```markdown
|
||||
---
|
||||
componentName: Button
|
||||
atomicCategory: Atom
|
||||
semanticElement: button
|
||||
figmaNodeId: "123:456"
|
||||
figmaUrl: "https://figma.com/design/..."
|
||||
---
|
||||
|
||||
# Button Component Specification
|
||||
|
||||
## Overview
|
||||
A primary action button component.
|
||||
|
||||
## Atomic Design Classification
|
||||
- Category: Atom
|
||||
- Reason: Single, indivisible interactive element
|
||||
|
||||
## Layout
|
||||
- Method: Flexbox
|
||||
- Direction: row
|
||||
- Justify: center
|
||||
- Align: center
|
||||
|
||||
## Spacing
|
||||
- Padding: px-6 py-3
|
||||
- Gap: gap-2
|
||||
- Border Radius: rounded-lg
|
||||
|
||||
## Typography
|
||||
- Font: text-base font-semibold
|
||||
- Color: text-white
|
||||
- Line Height: leading-normal
|
||||
- Alignment: text-center
|
||||
|
||||
## Colors
|
||||
- Background: bg-blue-500
|
||||
- Hover: hover:bg-blue-600
|
||||
- Active: active:bg-blue-700
|
||||
- Disabled: disabled:bg-gray-300
|
||||
|
||||
## Visual Properties
|
||||
- Border: border-transparent
|
||||
- Shadow: shadow-md
|
||||
- Transition: transition-colors duration-200
|
||||
|
||||
## Semantic HTML
|
||||
- Root Element: button
|
||||
- ARIA: aria-label when no text content
|
||||
|
||||
## Variants
|
||||
- variant: primary | secondary | tertiary
|
||||
- primary: bg-blue-500 text-white
|
||||
- secondary: bg-white text-blue-500 border-blue-500
|
||||
- tertiary: bg-transparent text-blue-500
|
||||
- size: small | medium | large
|
||||
- small: px-4 py-2 text-sm
|
||||
- medium: px-6 py-3 text-base
|
||||
- large: px-8 py-4 text-lg
|
||||
|
||||
## States
|
||||
- Default: As specified above
|
||||
- Hover: Darker background
|
||||
- Active: Even darker background
|
||||
- Disabled: Gray background, reduced opacity
|
||||
- Focus: Ring outline for keyboard navigation
|
||||
|
||||
## Responsive Behavior
|
||||
- Mobile: Full width, smaller padding
|
||||
- Tablet: Inline, medium padding
|
||||
- Desktop: Inline, larger padding
|
||||
|
||||
## Accessibility
|
||||
- Keyboard: Focusable, Enter/Space to activate
|
||||
- Screen Reader: Announced as "button"
|
||||
- Color Contrast: WCAG AA compliant
|
||||
|
||||
## Assets
|
||||
- Icons: /public/assets/icon-arrow.svg (if any)
|
||||
- Images: None
|
||||
|
||||
## Notes
|
||||
- Always use semantic <button> element
|
||||
- Avoid using <a> styled as button
|
||||
- Include loading state if used for async actions
|
||||
```
|
||||
|
||||
2. **Save the specification:**
|
||||
- Filename: `{ComponentName}.design.md`
|
||||
- Location: `/design-specs/` or project-specific location
|
||||
|
||||
## Special Workflows
|
||||
|
||||
### Comparing Design with Implementation
|
||||
|
||||
When asked to compare an existing component with Figma:
|
||||
|
||||
1. **Read the existing component code**
|
||||
2. **Extract Figma design properties** using MCP tools
|
||||
3. **Compare systematically:**
|
||||
- Layout method (Flexbox, Grid, etc.)
|
||||
- Spacing values (padding, gap, margin)
|
||||
- Typography (font size, weight, line height, color)
|
||||
- Colors and backgrounds
|
||||
- Border radius, shadows, etc.
|
||||
4. **Generate a diff report:**
|
||||
```markdown
|
||||
## Design Differences Report
|
||||
|
||||
### Component: Button
|
||||
|
||||
#### Spacing
|
||||
- Design: px-6 py-3 gap-2
|
||||
- Implementation: px-4 py-2 gap-3
|
||||
- Status: ❌ Mismatch
|
||||
- Impact: Button appears smaller and less comfortable
|
||||
|
||||
#### Typography
|
||||
- Design: text-base font-semibold
|
||||
- Implementation: text-base font-semibold
|
||||
- Status: ✅ Match
|
||||
|
||||
#### Colors
|
||||
- Design: bg-blue-500 hover:bg-blue-600
|
||||
- Implementation: bg-blue-600 hover:bg-blue-700
|
||||
- Status: ❌ Mismatch
|
||||
- Impact: Button is darker than intended
|
||||
|
||||
### Recommendations
|
||||
1. Update padding to px-6 py-3
|
||||
2. Update gap to gap-2
|
||||
3. Update background colors to match design
|
||||
```
|
||||
5. **Document required changes** in the specification
|
||||
|
||||
### Breaking Down a Full Page
|
||||
|
||||
When given a full page Figma node:
|
||||
|
||||
1. **Get page metadata** to understand structure
|
||||
2. **Identify major sections:**
|
||||
- Header
|
||||
- Hero
|
||||
- Content sections
|
||||
- Footer
|
||||
|
||||
3. **For each section:**
|
||||
- Classify as Organism
|
||||
- Identify child Molecules and Atoms
|
||||
- Extract design properties
|
||||
- Create individual specifications
|
||||
|
||||
4. **Create component tree:**
|
||||
```
|
||||
Page (Template)
|
||||
├─ Header (Organism)
|
||||
│ ├─ Logo (Atom)
|
||||
│ ├─ Navigation (Molecule)
|
||||
│ └─ UserMenu (Molecule)
|
||||
├─ Hero (Organism)
|
||||
│ ├─ Heading (Atom)
|
||||
│ ├─ Paragraph (Atom)
|
||||
│ └─ CTAButton (Atom)
|
||||
├─ Features (Organism)
|
||||
│ └─ FeatureCard (Molecule) × 3
|
||||
│ ├─ Icon (Atom)
|
||||
│ ├─ Title (Atom)
|
||||
│ └─ Description (Atom)
|
||||
└─ Footer (Organism)
|
||||
├─ Logo (Atom)
|
||||
└─ Links (Molecule)
|
||||
```
|
||||
|
||||
5. **Generate specifications from bottom-up:**
|
||||
- Create Atom specifications first
|
||||
- Build Molecule specifications
|
||||
- Assemble Organism specifications
|
||||
- Compose Page specification with assembly instructions
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always read guides before starting:**
|
||||
- Layout analysis guide for layout decisions
|
||||
- Spacing guide for accurate spacing extraction
|
||||
- Typography guide for text styling
|
||||
- Atomic Design guide for classification
|
||||
- Semantic HTML guide for element selection
|
||||
|
||||
2. **Prioritize pixel-perfect accuracy:**
|
||||
- Use exact spacing values from Figma
|
||||
- Match typography precisely
|
||||
- Verify colors match design tokens
|
||||
|
||||
3. **Document thoroughly:**
|
||||
- Include all variants and states
|
||||
- Document responsive behavior
|
||||
- Note accessibility considerations
|
||||
- Include designer notes if available
|
||||
|
||||
4. **Consider implementation:**
|
||||
- Map to Tailwind classes for easy implementation
|
||||
- Document component hierarchy
|
||||
- Note any complex interactions
|
||||
|
||||
5. **Maintain consistency:**
|
||||
- Use consistent naming conventions
|
||||
- Follow project-specific patterns
|
||||
- Align with design system when available
|
||||
|
||||
## Resources
|
||||
|
||||
This skill includes comprehensive guides:
|
||||
|
||||
### references/
|
||||
|
||||
- **layout-analysis-guide.md**: Criteria for choosing Flexbox, Grid, absolute positioning
|
||||
- **spacing-extraction-guide.md**: Methods for extracting padding, gap, margin values
|
||||
- **typography-extraction-guide.md**: Guide for extracting font properties
|
||||
- **atomic-design-classification.md**: Classification criteria for Atoms, Molecules, Organisms
|
||||
- **semantic-html-guide.md**: Recommendations for choosing appropriate HTML elements
|
||||
|
||||
**Usage:** Always read relevant guides before starting analysis to ensure accuracy.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Not handling component instances properly:**
|
||||
- Always get the main component when working with instances
|
||||
- Extract instance-specific properties separately
|
||||
|
||||
2. **Ignoring variants:**
|
||||
- Check for variant properties in Figma
|
||||
- Document all variant options
|
||||
|
||||
3. **Using wrong layout method:**
|
||||
- Read the layout guide
|
||||
- Don't default to Flexbox for everything
|
||||
|
||||
4. **Skipping semantic HTML:**
|
||||
- Don't use `<div>` for everything
|
||||
- Consider accessibility and SEO
|
||||
|
||||
5. **Forgetting responsive behavior:**
|
||||
- Check for responsive variants in Figma
|
||||
- Document breakpoint changes
|
||||
|
||||
6. **Not checking existing code:**
|
||||
- Always check Code Connect mappings
|
||||
- Avoid duplicating existing specifications
|
||||
|
||||
## Output Format
|
||||
|
||||
The final output should be a Markdown document with:
|
||||
|
||||
1. **Front matter** with metadata
|
||||
2. **Overview** section
|
||||
3. **Design properties** organized by category
|
||||
4. **Variants and states** documentation
|
||||
5. **Responsive behavior** notes
|
||||
6. **Accessibility** considerations
|
||||
7. **Assets** references
|
||||
8. **Implementation notes**
|
||||
|
||||
This specification document will be used by the `nextjs-react-implementation` skill to generate actual code.
|
||||
|
||||
---
|
||||
|
||||
**This skill systematically analyzes Figma designs and creates structured specifications for accurate implementation.**
|
||||
@@ -0,0 +1,396 @@
|
||||
# Atomic Design Classification Guide
|
||||
|
||||
This guide provides criteria for classifying React components according to Atomic Design principles when extracting from Figma designs.
|
||||
|
||||
## Atomic Design Overview
|
||||
|
||||
Atomic Design is a methodology for creating design systems with five distinct levels:
|
||||
|
||||
1. **Atoms** - Basic building blocks
|
||||
2. **Molecules** - Simple combinations of atoms
|
||||
3. **Organisms** - Complex combinations of molecules and atoms
|
||||
4. **Templates** - Page-level layouts (wireframes)
|
||||
5. **Pages** - Specific instances of templates with real content
|
||||
|
||||
For component libraries, focus primarily on Atoms, Molecules, and Organisms.
|
||||
|
||||
## Classification Criteria
|
||||
|
||||
### Atoms
|
||||
|
||||
**Definition:** The smallest, indivisible UI components that cannot be broken down further without losing meaning.
|
||||
|
||||
**Characteristics:**
|
||||
- Single responsibility
|
||||
- No internal state (usually)
|
||||
- Highly reusable
|
||||
- Self-contained
|
||||
- Cannot be broken down further
|
||||
|
||||
**Examples:**
|
||||
- Button
|
||||
- Input field
|
||||
- Label
|
||||
- Icon
|
||||
- Image
|
||||
- Heading (h1, h2, etc.)
|
||||
- Paragraph
|
||||
- Link
|
||||
- Checkbox
|
||||
- Radio button
|
||||
- Badge
|
||||
- Avatar
|
||||
- Spinner/Loader
|
||||
|
||||
**Figma Indicators:**
|
||||
- Figma components with no nested components
|
||||
- Simple, single-purpose elements
|
||||
- Elements that appear repeatedly across designs
|
||||
- Base design tokens (colors, typography, spacing)
|
||||
|
||||
**React Example:**
|
||||
```tsx
|
||||
// Button Atom
|
||||
export const Button = ({ children, onClick, variant = 'primary' }: Props) => (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className={`px-4 py-2 rounded ${variant === 'primary' ? 'bg-blue-500 text-white' : 'bg-gray-200'}`}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
```
|
||||
|
||||
### Molecules
|
||||
|
||||
**Definition:** Simple combinations of atoms that work together as a unit.
|
||||
|
||||
**Characteristics:**
|
||||
- Composed of 2-5 atoms
|
||||
- Has a single, clear purpose
|
||||
- Still relatively simple
|
||||
- Reusable across contexts
|
||||
- May have simple internal logic
|
||||
|
||||
**Examples:**
|
||||
- Search bar (Input + Button)
|
||||
- Form field (Label + Input + Error message)
|
||||
- Card header (Heading + Badge)
|
||||
- Social share buttons (Multiple icon buttons)
|
||||
- Breadcrumb navigation (Multiple links + separators)
|
||||
- Input with icon
|
||||
- Select dropdown with label
|
||||
- Toast notification (Icon + Text + Close button)
|
||||
|
||||
**Figma Indicators:**
|
||||
- Figma components containing 2-5 child components
|
||||
- Grouped elements that always appear together
|
||||
- Repeated patterns across different pages
|
||||
|
||||
**React Example:**
|
||||
```tsx
|
||||
// SearchBar Molecule
|
||||
export const SearchBar = ({ onSearch, placeholder }: Props) => (
|
||||
<div className="flex gap-2">
|
||||
<Input placeholder={placeholder} onChange={handleChange} />
|
||||
<Button onClick={onSearch}>Search</Button>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
### Organisms
|
||||
|
||||
**Definition:** Complex UI components composed of molecules and atoms, forming distinct sections of an interface.
|
||||
|
||||
**Characteristics:**
|
||||
- Composed of multiple molecules and/or atoms
|
||||
- Complex structure
|
||||
- May have significant internal logic and state
|
||||
- Represents a distinct section of the UI
|
||||
- Often context-specific
|
||||
|
||||
**Examples:**
|
||||
- Header (Logo + Navigation + Search bar + User menu)
|
||||
- Footer (Multiple link groups + Social icons + Copyright)
|
||||
- Product card (Image + Title + Description + Price + Button)
|
||||
- Comment section (Avatar + Name + Timestamp + Text + Action buttons)
|
||||
- Navigation menu (Multiple links + dropdown menus)
|
||||
- Form (Multiple form fields + Submit button)
|
||||
- Modal dialog (Header + Content + Footer with buttons)
|
||||
- Table with pagination (Table + Pagination controls)
|
||||
- Sidebar (Logo + Navigation links + User profile)
|
||||
|
||||
**Figma Indicators:**
|
||||
- Figma components with multiple nested components
|
||||
- Large, complex frames
|
||||
- Represents a complete UI section
|
||||
- Contains both structure and content
|
||||
|
||||
**React Example:**
|
||||
```tsx
|
||||
// ProductCard Organism
|
||||
export const ProductCard = ({ product }: Props) => (
|
||||
<div className="flex flex-col gap-4 p-6 border rounded">
|
||||
<Image src={product.image} alt={product.name} />
|
||||
<Heading level={3}>{product.name}</Heading>
|
||||
<Paragraph>{product.description}</Paragraph>
|
||||
<div className="flex items-center justify-between">
|
||||
<Badge>{product.price}</Badge>
|
||||
<Button onClick={() => addToCart(product)}>Add to Cart</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
### Templates (Optional)
|
||||
|
||||
**Definition:** Page-level layouts that define content structure without actual content.
|
||||
|
||||
**Characteristics:**
|
||||
- Arranges organisms into page layouts
|
||||
- Uses placeholder content
|
||||
- Defines grid and spacing
|
||||
- Reusable across multiple pages
|
||||
|
||||
**Examples:**
|
||||
- Blog post layout template
|
||||
- Dashboard layout template
|
||||
- Product page layout template
|
||||
|
||||
**Figma Indicators:**
|
||||
- Full-page frames
|
||||
- Uses placeholder content (Lorem ipsum, sample images)
|
||||
- Defines overall page structure
|
||||
|
||||
**React Example:**
|
||||
```tsx
|
||||
// BlogPostTemplate
|
||||
export const BlogPostTemplate = ({ header, content, sidebar }: Props) => (
|
||||
<div className="grid grid-cols-12 gap-6">
|
||||
<header className="col-span-12">{header}</header>
|
||||
<main className="col-span-8">{content}</main>
|
||||
<aside className="col-span-4">{sidebar}</aside>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
### Pages (Optional)
|
||||
|
||||
**Definition:** Specific instances of templates with real content.
|
||||
|
||||
**Characteristics:**
|
||||
- Uses actual content
|
||||
- Represents a specific page in the application
|
||||
- May include page-specific logic (data fetching, etc.)
|
||||
|
||||
**Note:** Pages are typically not part of a component library. They are application-specific implementations.
|
||||
|
||||
## Classification Decision Tree
|
||||
|
||||
When analyzing a Figma component, ask these questions:
|
||||
|
||||
### Is it an Atom?
|
||||
|
||||
1. ✅ Can it be broken down further?
|
||||
- **NO** → It's an Atom
|
||||
- **YES** → Continue
|
||||
|
||||
2. ✅ Does it have a single, indivisible purpose?
|
||||
- **YES** → It's an Atom
|
||||
- **NO** → Continue
|
||||
|
||||
### Is it a Molecule?
|
||||
|
||||
3. ✅ Is it composed of 2-5 atoms?
|
||||
- **YES** → Likely a Molecule
|
||||
- **NO** → Continue
|
||||
|
||||
4. ✅ Does it serve a single, simple purpose?
|
||||
- **YES** → It's a Molecule
|
||||
- **NO** → Continue
|
||||
|
||||
### Is it an Organism?
|
||||
|
||||
5. ✅ Is it composed of multiple molecules and/or atoms?
|
||||
- **YES** → It's an Organism
|
||||
|
||||
6. ✅ Does it represent a distinct section of the interface?
|
||||
- **YES** → It's an Organism
|
||||
|
||||
### Special Cases
|
||||
|
||||
**Ambiguous cases:**
|
||||
- If a component could be either an Atom or Molecule, prefer **Atom** if it's highly reusable
|
||||
- If a component could be either a Molecule or Organism, prefer **Molecule** if it's simple
|
||||
|
||||
**Context matters:**
|
||||
- Classification can vary based on project scope
|
||||
- What's an Organism in one project might be a Molecule in another (with larger scale)
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
Follow consistent naming patterns for each category:
|
||||
|
||||
### Atoms
|
||||
```
|
||||
Button
|
||||
Input
|
||||
Label
|
||||
Icon
|
||||
Badge
|
||||
Avatar
|
||||
Heading
|
||||
Paragraph
|
||||
```
|
||||
|
||||
### Molecules
|
||||
```
|
||||
SearchBar
|
||||
FormField
|
||||
InputWithIcon
|
||||
SocialShareButtons
|
||||
Breadcrumb
|
||||
```
|
||||
|
||||
### Organisms
|
||||
```
|
||||
Header
|
||||
Footer
|
||||
ProductCard
|
||||
CommentSection
|
||||
NavigationMenu
|
||||
Sidebar
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
Organize components by Atomic Design category:
|
||||
|
||||
```
|
||||
src/
|
||||
components/
|
||||
atoms/
|
||||
Button/
|
||||
Button.tsx
|
||||
Button.test.tsx
|
||||
Button.stories.tsx
|
||||
molecules/
|
||||
SearchBar/
|
||||
SearchBar.tsx
|
||||
SearchBar.test.tsx
|
||||
SearchBar.stories.tsx
|
||||
organisms/
|
||||
Header/
|
||||
Header.tsx
|
||||
Header.test.tsx
|
||||
Header.stories.tsx
|
||||
```
|
||||
|
||||
## Analysis Workflow
|
||||
|
||||
When extracting components from Figma:
|
||||
|
||||
1. **Identify component boundaries**
|
||||
- Look for logical groupings
|
||||
- Check Figma component instances
|
||||
- Identify repeated patterns
|
||||
|
||||
2. **Count the atoms**
|
||||
- How many basic elements does it contain?
|
||||
- 1 atom → Atom
|
||||
- 2-5 atoms → Molecule candidate
|
||||
- 6+ atoms → Organism candidate
|
||||
|
||||
3. **Assess complexity**
|
||||
- Simple structure → Atom or Molecule
|
||||
- Complex structure → Organism
|
||||
|
||||
4. **Check purpose**
|
||||
- Single, simple purpose → Atom or Molecule
|
||||
- Multiple purposes or section of UI → Organism
|
||||
|
||||
5. **Verify reusability**
|
||||
- Highly reusable across contexts → Atom or Molecule
|
||||
- Context-specific → Organism
|
||||
|
||||
6. **Make classification decision**
|
||||
- Use the decision tree above
|
||||
- Document reasoning if ambiguous
|
||||
|
||||
## Common Patterns and Classifications
|
||||
|
||||
### Forms
|
||||
|
||||
- **Atoms**: Input, Label, Checkbox, Radio, Button
|
||||
- **Molecules**: FormField (Label + Input + Error)
|
||||
- **Organisms**: LoginForm (Multiple FormFields + Button)
|
||||
|
||||
### Navigation
|
||||
|
||||
- **Atoms**: Link, Icon
|
||||
- **Molecules**: NavItem (Link + Icon)
|
||||
- **Organisms**: NavigationMenu (Multiple NavItems + Dropdown)
|
||||
|
||||
### Cards
|
||||
|
||||
- **Atoms**: Image, Heading, Paragraph, Button, Badge
|
||||
- **Molecules**: CardHeader (Image + Badge), CardFooter (Button)
|
||||
- **Organisms**: ProductCard (CardHeader + Content + CardFooter)
|
||||
|
||||
### Lists
|
||||
|
||||
- **Atoms**: ListItem (single item)
|
||||
- **Molecules**: ListItemWithIcon (Icon + ListItem)
|
||||
- **Organisms**: UserList (Multiple ListItemWithIcon + Header + Pagination)
|
||||
|
||||
## Edge Cases and Guidelines
|
||||
|
||||
### When a component feels too simple for Molecule
|
||||
|
||||
If a "Molecule" only combines 2 atoms without adding meaningful functionality:
|
||||
- Consider if it should be an Atom
|
||||
- Or, accept it as a simple Molecule for consistency
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
// This might feel too simple for a Molecule, but it's valid
|
||||
const IconButton = ({ icon, onClick }: Props) => (
|
||||
<Button onClick={onClick}>
|
||||
<Icon name={icon} />
|
||||
</Button>
|
||||
);
|
||||
```
|
||||
|
||||
### When a component feels too complex for Organism
|
||||
|
||||
If an "Organism" is extremely complex with many nested components:
|
||||
- Consider breaking it down into smaller Organisms
|
||||
- Or, accept it as a complex Organism if it represents a single, cohesive UI section
|
||||
|
||||
### Reusing components across categories
|
||||
|
||||
It's normal for:
|
||||
- Organisms to use Molecules
|
||||
- Molecules to use Atoms
|
||||
- Organisms to use Atoms directly (skip Molecules if simpler)
|
||||
|
||||
**Don't force categorization** - the goal is organization and reusability, not rigid adherence.
|
||||
|
||||
## Benefits of Proper Classification
|
||||
|
||||
1. **Better organization**: Easy to find components
|
||||
2. **Improved reusability**: Atoms and Molecules are highly reusable
|
||||
3. **Easier testing**: Smaller components are easier to test
|
||||
4. **Consistent design**: Enforces design system patterns
|
||||
5. **Team communication**: Shared vocabulary for discussing components
|
||||
6. **Scalability**: Easier to maintain as the system grows
|
||||
|
||||
## Tips
|
||||
|
||||
- **Start small**: Begin with Atoms, then build up to Molecules and Organisms
|
||||
- **Be consistent**: Once you classify a pattern, stick with it
|
||||
- **Document decisions**: If classification is ambiguous, document why you chose a category
|
||||
- **Iterate**: It's okay to reclassify components as you learn more about the system
|
||||
- **Prioritize reusability**: When in doubt, prefer smaller, more reusable components
|
||||
- **Don't over-engineer**: Not every UI element needs to be a separate Atom
|
||||
- **Use Figma components as hints**: Figma component structure often maps to Atomic Design
|
||||
195
skills/figma-design-analyzer/references/layout-analysis-guide.md
Normal file
195
skills/figma-design-analyzer/references/layout-analysis-guide.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Layout Analysis Guide
|
||||
|
||||
This guide provides criteria for determining the appropriate CSS layout method when converting Figma designs to React components.
|
||||
|
||||
## Layout Method Decision Tree
|
||||
|
||||
### 1. Flexbox (Most Common)
|
||||
|
||||
Use Flexbox when:
|
||||
- Elements are arranged in a single direction (row or column)
|
||||
- Elements have consistent spacing (gap)
|
||||
- Elements need to wrap
|
||||
- Elements need dynamic sizing (flex-grow, flex-shrink)
|
||||
- Vertical or horizontal centering is required
|
||||
|
||||
**Figma Indicators:**
|
||||
- Auto Layout with single direction
|
||||
- Consistent spacing between items
|
||||
- "Hug contents" or "Fill container" settings
|
||||
- Alignment properties (top, center, bottom, left, right)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>Item 1</div>
|
||||
<div>Item 2</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2. CSS Grid
|
||||
|
||||
Use Grid when:
|
||||
- Elements are arranged in a two-dimensional layout (rows AND columns)
|
||||
- Complex alignment is needed across multiple axes
|
||||
- Explicit row/column sizing is required
|
||||
- Elements span multiple rows or columns
|
||||
|
||||
**Figma Indicators:**
|
||||
- Grid layout visible in design
|
||||
- Elements aligned to both rows and columns
|
||||
- Consistent grid structure across the design
|
||||
- Elements with specific row/column positioning
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>Item 1</div>
|
||||
<div>Item 2</div>
|
||||
<div>Item 3</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 3. Absolute Positioning
|
||||
|
||||
Use absolute positioning when:
|
||||
- Elements overlap each other
|
||||
- Elements have fixed positions relative to a container
|
||||
- Elements need to be positioned independently of document flow
|
||||
|
||||
**Figma Indicators:**
|
||||
- Overlapping layers
|
||||
- Constraints set to specific distances from edges
|
||||
- Elements floating above other content
|
||||
- Fixed positioning relative to parent frame
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<div className="relative">
|
||||
<div className="absolute top-4 right-4">
|
||||
Overlay content
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 4. Float (Rare, Legacy)
|
||||
|
||||
Generally avoid float in modern React development. Use Flexbox instead.
|
||||
|
||||
Only consider float for:
|
||||
- Text wrapping around images (though even this can be done with Grid)
|
||||
|
||||
### 5. Table (Rare, Semantic Only)
|
||||
|
||||
Use table layout only for actual tabular data, not for layout purposes.
|
||||
|
||||
**When to use:**
|
||||
- Displaying data in rows and columns with headers
|
||||
- Semantic table markup is needed for accessibility
|
||||
|
||||
## Component Layout Patterns
|
||||
|
||||
### Auto Layout → Flexbox Mapping
|
||||
|
||||
| Figma Auto Layout | Tailwind CSS |
|
||||
|------------------|--------------|
|
||||
| Horizontal direction | `flex-row` |
|
||||
| Vertical direction | `flex-col` |
|
||||
| Spacing between items | `gap-{size}` |
|
||||
| Padding | `p-{size}` or `px-{size} py-{size}` |
|
||||
| Hug contents | (no specific class, use content-based sizing) |
|
||||
| Fill container | `flex-1` or `w-full h-full` |
|
||||
| Align items (cross-axis) | `items-{start\|center\|end\|stretch}` |
|
||||
| Justify content (main-axis) | `justify-{start\|center\|end\|between\|around}` |
|
||||
|
||||
### Constraints → Positioning Mapping
|
||||
|
||||
| Figma Constraint | CSS Approach |
|
||||
|-----------------|--------------|
|
||||
| Left + Right | `w-full` or specific width with margins |
|
||||
| Top + Bottom | `h-full` or specific height with margins |
|
||||
| Left + Top | Default (top-left aligned) |
|
||||
| Center | `mx-auto` (horizontal) or flexbox centering |
|
||||
| Scale | `w-full h-full object-contain` or responsive units |
|
||||
|
||||
## Analysis Workflow
|
||||
|
||||
When analyzing a Figma node's layout:
|
||||
|
||||
1. **Check for Auto Layout**
|
||||
- If present: Use Flexbox
|
||||
- Direction → `flex-row` or `flex-col`
|
||||
- Spacing → `gap-{size}`
|
||||
- Alignment → `items-{align}` and `justify-{justify}`
|
||||
|
||||
2. **Check for Grid Structure**
|
||||
- If elements align to both rows and columns: Use CSS Grid
|
||||
- Count columns and rows
|
||||
- Measure gaps
|
||||
|
||||
3. **Check for Overlapping Elements**
|
||||
- If elements overlap: Use `relative` + `absolute` positioning
|
||||
- Measure distances from edges
|
||||
|
||||
4. **Check for Responsive Behavior**
|
||||
- Analyze constraints
|
||||
- Determine if width/height should be fixed or flexible
|
||||
- Consider breakpoints for responsive design
|
||||
|
||||
5. **Nested Layouts**
|
||||
- Analyze each nesting level separately
|
||||
- Parent might be Grid, children might be Flexbox
|
||||
- Apply layout methods independently at each level
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Card Component
|
||||
```tsx
|
||||
// Typically Flexbox with column direction
|
||||
<div className="flex flex-col gap-4 p-6 rounded-lg shadow">
|
||||
<h2>Title</h2>
|
||||
<p>Description</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Header with Logo and Navigation
|
||||
```tsx
|
||||
// Flexbox with space-between
|
||||
<header className="flex items-center justify-between px-8 py-4">
|
||||
<img src="logo.png" alt="Logo" />
|
||||
<nav className="flex gap-6">
|
||||
<a href="#">Link 1</a>
|
||||
<a href="#">Link 2</a>
|
||||
</nav>
|
||||
</header>
|
||||
```
|
||||
|
||||
### Image Gallery
|
||||
```tsx
|
||||
// CSS Grid for consistent layout
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<img src="1.jpg" />
|
||||
<img src="2.jpg" />
|
||||
<img src="3.jpg" />
|
||||
</div>
|
||||
```
|
||||
|
||||
### Overlay Modal
|
||||
```tsx
|
||||
// Absolute positioning for overlay
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-black/50">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
Modal content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
- **Start with Flexbox**: When in doubt, start with Flexbox. It's the most flexible and commonly used.
|
||||
- **Prefer Semantic Layout**: Use Grid for grid-like structures, not Flexbox workarounds.
|
||||
- **Minimize Absolute Positioning**: Use it only when necessary. It breaks document flow and makes responsive design harder.
|
||||
- **Analyze Nesting**: Each nesting level can use a different layout method. Don't force a single method for the entire component.
|
||||
- **Consider Responsiveness**: Think about how the layout should adapt to different screen sizes. Use Tailwind's responsive prefixes (`sm:`, `md:`, `lg:`, etc.) when needed.
|
||||
726
skills/figma-design-analyzer/references/semantic-html-guide.md
Normal file
726
skills/figma-design-analyzer/references/semantic-html-guide.md
Normal file
@@ -0,0 +1,726 @@
|
||||
# Semantic HTML Guide
|
||||
|
||||
This guide provides recommendations for choosing appropriate HTML tags when converting Figma designs to React components, ensuring accessibility and semantic correctness.
|
||||
|
||||
## Why Semantic HTML Matters
|
||||
|
||||
1. **Accessibility**: Screen readers and assistive technologies rely on semantic HTML
|
||||
2. **SEO**: Search engines understand content structure better
|
||||
3. **Maintainability**: Code is more readable and self-documenting
|
||||
4. **Styling**: Easier to style with CSS selectors
|
||||
5. **Future-proofing**: Standards-compliant code ages better
|
||||
|
||||
## Semantic HTML Elements
|
||||
|
||||
### Document Structure
|
||||
|
||||
#### `<header>`
|
||||
|
||||
**Use for:**
|
||||
- Site header
|
||||
- Page header
|
||||
- Section header
|
||||
- Article header
|
||||
|
||||
**Don't use for:**
|
||||
- Every heading (use h1-h6 instead)
|
||||
- Random containers
|
||||
|
||||
**Figma Indicators:**
|
||||
- Top section of a page or component
|
||||
- Contains logo, navigation, or title
|
||||
- Labeled "Header" in Figma
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<header className="flex items-center justify-between p-4">
|
||||
<img src="logo.png" alt="Company Logo" />
|
||||
<nav>...</nav>
|
||||
</header>
|
||||
```
|
||||
|
||||
#### `<nav>`
|
||||
|
||||
**Use for:**
|
||||
- Primary navigation
|
||||
- Breadcrumb navigation
|
||||
- Table of contents
|
||||
- Pagination
|
||||
|
||||
**Don't use for:**
|
||||
- Social media links (use `<ul>` instead)
|
||||
- Footer links (unless it's primary navigation)
|
||||
|
||||
**Figma Indicators:**
|
||||
- Navigation menu
|
||||
- Labeled "Navigation" or "Nav" in Figma
|
||||
- Contains multiple links to different sections
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<nav className="flex gap-4">
|
||||
<a href="/">Home</a>
|
||||
<a href="/about">About</a>
|
||||
<a href="/contact">Contact</a>
|
||||
</nav>
|
||||
```
|
||||
|
||||
#### `<main>`
|
||||
|
||||
**Use for:**
|
||||
- Main content of the page
|
||||
- The primary content area
|
||||
|
||||
**Don't use for:**
|
||||
- Sidebars
|
||||
- Headers or footers
|
||||
- Navigation
|
||||
|
||||
**Rules:**
|
||||
- Only one `<main>` per page
|
||||
- Should not be inside `<article>`, `<aside>`, `<footer>`, `<header>`, or `<nav>`
|
||||
|
||||
**Figma Indicators:**
|
||||
- Central content area of a page
|
||||
- Labeled "Main Content" or "Content" in Figma
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<main className="container mx-auto p-8">
|
||||
{/* Primary page content */}
|
||||
</main>
|
||||
```
|
||||
|
||||
#### `<aside>`
|
||||
|
||||
**Use for:**
|
||||
- Sidebars
|
||||
- Related content
|
||||
- Callout boxes
|
||||
- Pull quotes
|
||||
- Advertising
|
||||
|
||||
**Don't use for:**
|
||||
- Main content
|
||||
|
||||
**Figma Indicators:**
|
||||
- Sidebar sections
|
||||
- "Related articles" sections
|
||||
- Callout boxes
|
||||
- Labeled "Sidebar" or "Aside" in Figma
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<aside className="w-64 bg-gray-100 p-4">
|
||||
<h3>Related Articles</h3>
|
||||
<ul>...</ul>
|
||||
</aside>
|
||||
```
|
||||
|
||||
#### `<footer>`
|
||||
|
||||
**Use for:**
|
||||
- Site footer
|
||||
- Page footer
|
||||
- Section footer
|
||||
- Article footer
|
||||
|
||||
**Don't use for:**
|
||||
- Every bottom section (assess if it's truly footer content)
|
||||
|
||||
**Figma Indicators:**
|
||||
- Bottom section of a page or component
|
||||
- Contains copyright, links, contact info
|
||||
- Labeled "Footer" in Figma
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<footer className="bg-gray-900 text-white p-8">
|
||||
<p>© 2024 Company Name</p>
|
||||
</footer>
|
||||
```
|
||||
|
||||
#### `<section>`
|
||||
|
||||
**Use for:**
|
||||
- Thematic groupings of content
|
||||
- Chapters or sections of a page
|
||||
- Tabbed content areas
|
||||
|
||||
**Don't use for:**
|
||||
- Generic containers (use `<div>` instead)
|
||||
|
||||
**Rule:** Each `<section>` should have a heading (h1-h6)
|
||||
|
||||
**Figma Indicators:**
|
||||
- Distinct content sections on a page
|
||||
- Sections with headings
|
||||
- Labeled "Section" in Figma
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<section className="py-16">
|
||||
<h2>Our Services</h2>
|
||||
<p>...</p>
|
||||
</section>
|
||||
```
|
||||
|
||||
#### `<article>`
|
||||
|
||||
**Use for:**
|
||||
- Blog posts
|
||||
- News articles
|
||||
- Forum posts
|
||||
- Comments
|
||||
- Product cards (in some contexts)
|
||||
- Independent, self-contained content
|
||||
|
||||
**Don't use for:**
|
||||
- Generic content containers
|
||||
|
||||
**Rule:** Content inside `<article>` should make sense independently
|
||||
|
||||
**Figma Indicators:**
|
||||
- Blog post layouts
|
||||
- News article cards
|
||||
- Comment sections
|
||||
- Product cards
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<article className="border rounded p-6">
|
||||
<h2>Article Title</h2>
|
||||
<p className="text-gray-600">Published on ...</p>
|
||||
<p>Article content...</p>
|
||||
</article>
|
||||
```
|
||||
|
||||
### Content
|
||||
|
||||
#### Headings: `<h1>` to `<h6>`
|
||||
|
||||
**Use for:**
|
||||
- Section titles
|
||||
- Content hierarchy
|
||||
|
||||
**Don't use for:**
|
||||
- Styling purposes (use CSS instead)
|
||||
|
||||
**Rules:**
|
||||
- Only one `<h1>` per page (page title)
|
||||
- Don't skip levels (h1 → h2 → h3, not h1 → h3)
|
||||
- Use in descending order
|
||||
|
||||
**Figma Indicators:**
|
||||
- Text labeled "Heading", "Title", "H1", "H2", etc.
|
||||
- Large, bold text at the start of sections
|
||||
- Text styles named "Heading 1", "Heading 2", etc.
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<h1 className="text-4xl font-bold">Page Title</h1>
|
||||
<section>
|
||||
<h2 className="text-3xl font-semibold">Section Title</h2>
|
||||
<h3 className="text-2xl font-medium">Subsection Title</h3>
|
||||
</section>
|
||||
```
|
||||
|
||||
#### `<p>`
|
||||
|
||||
**Use for:**
|
||||
- Paragraphs of text
|
||||
- Body content
|
||||
|
||||
**Don't use for:**
|
||||
- Headings
|
||||
- Lists
|
||||
- Single words or short phrases (use `<span>` instead)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<p className="text-base leading-relaxed">
|
||||
This is a paragraph of text...
|
||||
</p>
|
||||
```
|
||||
|
||||
#### `<a>`
|
||||
|
||||
**Use for:**
|
||||
- Hyperlinks
|
||||
- Navigation links
|
||||
|
||||
**Don't use for:**
|
||||
- Buttons (use `<button>` instead)
|
||||
|
||||
**Rule:** Always include `href` attribute
|
||||
|
||||
**Accessibility:**
|
||||
- Use descriptive link text (not "click here")
|
||||
- Add `rel="noopener noreferrer"` for external links with `target="_blank"`
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<a href="/about" className="text-blue-600 hover:underline">
|
||||
Learn more about our company
|
||||
</a>
|
||||
|
||||
{/* External link */}
|
||||
<a
|
||||
href="https://example.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600"
|
||||
>
|
||||
Visit example.com
|
||||
</a>
|
||||
```
|
||||
|
||||
#### `<button>`
|
||||
|
||||
**Use for:**
|
||||
- Interactive buttons
|
||||
- Form submissions
|
||||
- Actions that don't navigate
|
||||
|
||||
**Don't use for:**
|
||||
- Links (use `<a>` instead)
|
||||
|
||||
**Rule:** Always include `type` attribute (`button`, `submit`, or `reset`)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded"
|
||||
>
|
||||
Click Me
|
||||
</button>
|
||||
```
|
||||
|
||||
### Lists
|
||||
|
||||
#### `<ul>` (Unordered List)
|
||||
|
||||
**Use for:**
|
||||
- Lists without order
|
||||
- Navigation menus (within `<nav>`)
|
||||
- Feature lists
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<ul className="list-disc list-inside">
|
||||
<li>First item</li>
|
||||
<li>Second item</li>
|
||||
<li>Third item</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
#### `<ol>` (Ordered List)
|
||||
|
||||
**Use for:**
|
||||
- Lists with order/sequence
|
||||
- Step-by-step instructions
|
||||
- Rankings
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<ol className="list-decimal list-inside">
|
||||
<li>First step</li>
|
||||
<li>Second step</li>
|
||||
<li>Third step</li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
#### `<dl>`, `<dt>`, `<dd>` (Definition List)
|
||||
|
||||
**Use for:**
|
||||
- Term-definition pairs
|
||||
- Metadata
|
||||
- Key-value pairs
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<dl>
|
||||
<dt className="font-semibold">Name</dt>
|
||||
<dd className="ml-4">John Doe</dd>
|
||||
|
||||
<dt className="font-semibold">Email</dt>
|
||||
<dd className="ml-4">john@example.com</dd>
|
||||
</dl>
|
||||
```
|
||||
|
||||
### Forms
|
||||
|
||||
#### `<form>`
|
||||
|
||||
**Use for:**
|
||||
- All form inputs
|
||||
- Search bars
|
||||
- Login forms
|
||||
|
||||
**Rule:** Always include `action` or handle submit with JavaScript
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
||||
{/* form fields */}
|
||||
</form>
|
||||
```
|
||||
|
||||
#### `<label>`
|
||||
|
||||
**Use for:**
|
||||
- Input labels
|
||||
|
||||
**Rule:** Always associate with an input using `htmlFor` or by wrapping
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
{/* Using htmlFor */}
|
||||
<label htmlFor="email" className="font-medium">
|
||||
Email
|
||||
</label>
|
||||
<input id="email" type="email" />
|
||||
|
||||
{/* Wrapping */}
|
||||
<label className="flex flex-col gap-1">
|
||||
<span className="font-medium">Email</span>
|
||||
<input type="email" />
|
||||
</label>
|
||||
```
|
||||
|
||||
#### `<input>`
|
||||
|
||||
**Use for:**
|
||||
- Text input
|
||||
- Checkboxes
|
||||
- Radio buttons
|
||||
- File uploads
|
||||
- Dates
|
||||
- Many other input types
|
||||
|
||||
**Rule:** Always include `type` attribute
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Enter your name"
|
||||
className="border rounded px-3 py-2"
|
||||
/>
|
||||
```
|
||||
|
||||
#### `<textarea>`
|
||||
|
||||
**Use for:**
|
||||
- Multi-line text input
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<textarea
|
||||
rows={4}
|
||||
placeholder="Enter your message"
|
||||
className="border rounded px-3 py-2"
|
||||
/>
|
||||
```
|
||||
|
||||
#### `<select>`
|
||||
|
||||
**Use for:**
|
||||
- Dropdown menus
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<select className="border rounded px-3 py-2">
|
||||
<option value="">Choose an option</option>
|
||||
<option value="1">Option 1</option>
|
||||
<option value="2">Option 2</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
#### `<fieldset>` and `<legend>`
|
||||
|
||||
**Use for:**
|
||||
- Grouping related form fields
|
||||
- Radio button groups
|
||||
- Checkbox groups
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<fieldset className="border rounded p-4">
|
||||
<legend className="font-semibold px-2">Choose a size</legend>
|
||||
<label>
|
||||
<input type="radio" name="size" value="small" /> Small
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="size" value="large" /> Large
|
||||
</label>
|
||||
</fieldset>
|
||||
```
|
||||
|
||||
### Media
|
||||
|
||||
#### `<img>`
|
||||
|
||||
**Use for:**
|
||||
- Images
|
||||
|
||||
**Rules:**
|
||||
- Always include `alt` attribute (describe the image or use empty string for decorative)
|
||||
- Always include `src` attribute
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
{/* Content image */}
|
||||
<img
|
||||
src="/photo.jpg"
|
||||
alt="A scenic mountain landscape"
|
||||
className="w-full rounded"
|
||||
/>
|
||||
|
||||
{/* Decorative image */}
|
||||
<img
|
||||
src="/decoration.png"
|
||||
alt=""
|
||||
className="w-8 h-8"
|
||||
/>
|
||||
```
|
||||
|
||||
#### `<figure>` and `<figcaption>`
|
||||
|
||||
**Use for:**
|
||||
- Images with captions
|
||||
- Code snippets with descriptions
|
||||
- Diagrams
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<figure>
|
||||
<img src="/chart.png" alt="Sales data chart" />
|
||||
<figcaption className="text-sm text-gray-600">
|
||||
Figure 1: Sales data for Q4 2024
|
||||
</figcaption>
|
||||
</figure>
|
||||
```
|
||||
|
||||
#### `<video>` and `<audio>`
|
||||
|
||||
**Use for:**
|
||||
- Video and audio content
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<video controls className="w-full">
|
||||
<source src="/video.mp4" type="video/mp4" />
|
||||
Your browser does not support video.
|
||||
</video>
|
||||
```
|
||||
|
||||
### Text-level Semantics
|
||||
|
||||
#### `<strong>` vs `<b>`
|
||||
|
||||
- `<strong>`: Use for **important** text (semantic)
|
||||
- `<b>`: Use for **stylistic** bold text (rare, prefer CSS)
|
||||
|
||||
**Prefer `<strong>`** in most cases.
|
||||
|
||||
#### `<em>` vs `<i>`
|
||||
|
||||
- `<em>`: Use for **emphasized** text (semantic)
|
||||
- `<i>`: Use for **stylistic** italic text (rare, prefer CSS)
|
||||
|
||||
**Prefer `<em>`** in most cases.
|
||||
|
||||
#### `<span>`
|
||||
|
||||
**Use for:**
|
||||
- Inline text that needs styling
|
||||
- Wrapping text for JavaScript manipulation
|
||||
|
||||
**Don't use for:**
|
||||
- Semantic meaning (use `<strong>`, `<em>`, etc.)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<p>
|
||||
This is <span className="text-blue-600">highlighted</span> text.
|
||||
</p>
|
||||
```
|
||||
|
||||
#### `<div>`
|
||||
|
||||
**Use for:**
|
||||
- Generic containers
|
||||
- Layout purposes
|
||||
|
||||
**Don't use for:**
|
||||
- Semantic meaning (use `<section>`, `<article>`, etc. instead)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<div className="flex gap-4">
|
||||
{/* content */}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Decision Tree: Choosing the Right Tag
|
||||
|
||||
### For Content Sections
|
||||
|
||||
```
|
||||
Is it the main content of the page?
|
||||
├─ YES → <main>
|
||||
└─ NO
|
||||
├─ Is it a navigation menu?
|
||||
│ └─ YES → <nav>
|
||||
└─ NO
|
||||
├─ Is it a sidebar or related content?
|
||||
│ └─ YES → <aside>
|
||||
└─ NO
|
||||
├─ Is it a header section?
|
||||
│ └─ YES → <header>
|
||||
└─ NO
|
||||
├─ Is it a footer section?
|
||||
│ └─ YES → <footer>
|
||||
└─ NO
|
||||
├─ Is it a self-contained article or post?
|
||||
│ └─ YES → <article>
|
||||
└─ NO
|
||||
├─ Is it a thematic section with a heading?
|
||||
│ └─ YES → <section>
|
||||
└─ NO → <div>
|
||||
```
|
||||
|
||||
### For Interactive Elements
|
||||
|
||||
```
|
||||
Is it a link that navigates somewhere?
|
||||
├─ YES → <a href="...">
|
||||
└─ NO
|
||||
└─ Is it a button that performs an action?
|
||||
└─ YES → <button type="button">
|
||||
```
|
||||
|
||||
### For Text
|
||||
|
||||
```
|
||||
Is it a heading?
|
||||
├─ YES → <h1> to <h6> (based on hierarchy)
|
||||
└─ NO
|
||||
├─ Is it a paragraph?
|
||||
│ └─ YES → <p>
|
||||
└─ NO
|
||||
├─ Is it emphasized/important?
|
||||
│ ├─ Important → <strong>
|
||||
│ └─ Emphasized → <em>
|
||||
└─ NO → <span>
|
||||
```
|
||||
|
||||
## Common Figma → HTML Mappings
|
||||
|
||||
| Figma Element | Semantic HTML | Notes |
|
||||
|--------------|---------------|-------|
|
||||
| Frame labeled "Header" | `<header>` | Site/page header |
|
||||
| Frame labeled "Nav" | `<nav>` | Navigation menu |
|
||||
| Frame labeled "Main" | `<main>` | Primary content |
|
||||
| Frame labeled "Sidebar" | `<aside>` | Sidebar content |
|
||||
| Frame labeled "Footer" | `<footer>` | Site/page footer |
|
||||
| Frame labeled "Section" | `<section>` | Content section |
|
||||
| Frame labeled "Card" | `<article>` or `<div>` | Depends on content |
|
||||
| Text layer "Heading" | `<h1>` to `<h6>` | Based on hierarchy |
|
||||
| Text layer "Body" | `<p>` | Paragraph text |
|
||||
| Button component | `<button>` | Interactive button |
|
||||
| Link component | `<a>` | Hyperlink |
|
||||
| Image layer | `<img>` | Image element |
|
||||
| Auto Layout (vertical) | `<div className="flex flex-col">` | Layout container |
|
||||
| Form | `<form>` | Form container |
|
||||
| Input field | `<input>` | Form input |
|
||||
|
||||
## Accessibility Considerations
|
||||
|
||||
### ARIA Attributes
|
||||
|
||||
When semantic HTML is not enough, use ARIA attributes:
|
||||
|
||||
```tsx
|
||||
{/* Button that controls a menu */}
|
||||
<button
|
||||
type="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
Menu
|
||||
</button>
|
||||
|
||||
{/* Navigation landmark */}
|
||||
<nav aria-label="Primary navigation">
|
||||
{/* links */}
|
||||
</nav>
|
||||
|
||||
{/* Region landmark */}
|
||||
<section aria-labelledby="section-title">
|
||||
<h2 id="section-title">Section Title</h2>
|
||||
</section>
|
||||
```
|
||||
|
||||
### Focus Management
|
||||
|
||||
Ensure interactive elements are keyboard accessible:
|
||||
|
||||
```tsx
|
||||
{/* Custom clickable div (avoid if possible) */}
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={handleClick}
|
||||
onKeyPress={handleKeyPress}
|
||||
>
|
||||
Click me
|
||||
</div>
|
||||
|
||||
{/* Better: use semantic button */}
|
||||
<button type="button" onClick={handleClick}>
|
||||
Click me
|
||||
</button>
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Using `<div>` for everything**
|
||||
- ❌ `<div className="header">...</div>`
|
||||
- ✅ `<header>...</header>`
|
||||
|
||||
2. **Using `<a>` for buttons**
|
||||
- ❌ `<a onClick={handleClick}>Submit</a>`
|
||||
- ✅ `<button type="button" onClick={handleClick}>Submit</button>`
|
||||
|
||||
3. **Using `<button>` for links**
|
||||
- ❌ `<button onClick={() => navigate('/about')}>About</button>`
|
||||
- ✅ `<a href="/about">About</a>`
|
||||
|
||||
4. **Skipping heading levels**
|
||||
- ❌ `<h1>Title</h1><h3>Subtitle</h3>`
|
||||
- ✅ `<h1>Title</h1><h2>Subtitle</h2>`
|
||||
|
||||
5. **Multiple `<main>` elements**
|
||||
- ❌ Two `<main>` on the same page
|
||||
- ✅ Only one `<main>` per page
|
||||
|
||||
6. **Empty `alt` attributes on content images**
|
||||
- ❌ `<img src="chart.jpg" alt="" />`
|
||||
- ✅ `<img src="chart.jpg" alt="Sales chart showing growth" />`
|
||||
|
||||
7. **Using `<br>` for spacing**
|
||||
- ❌ `<p>Text<br><br><br>More text</p>`
|
||||
- ✅ Use CSS margin/padding instead
|
||||
|
||||
## Tips
|
||||
|
||||
- **Use semantic HTML first**: Before adding ARIA, check if semantic HTML solves the problem
|
||||
- **Test with screen readers**: Use tools like VoiceOver (Mac) or NVDA (Windows)
|
||||
- **Validate HTML**: Use W3C validator to check for errors
|
||||
- **Think about structure**: How would this content be read aloud?
|
||||
- **Consult ARIA authoring practices**: https://www.w3.org/WAI/ARIA/apg/
|
||||
- **When in doubt, use `<div>` or `<span>`**: Don't force semantic meaning where it doesn't exist
|
||||
@@ -0,0 +1,255 @@
|
||||
# Spacing Extraction Guide
|
||||
|
||||
This guide provides methods for extracting and translating spacing values from Figma to Tailwind CSS.
|
||||
|
||||
## Spacing Types
|
||||
|
||||
### 1. Padding (Internal Spacing)
|
||||
|
||||
Padding is the space between a container's edge and its content.
|
||||
|
||||
**Figma Indicators:**
|
||||
- Auto Layout padding values
|
||||
- Distance from frame edge to first child element
|
||||
- Uniform or directional padding (top, right, bottom, left)
|
||||
|
||||
**Extraction Method:**
|
||||
1. Select the container frame
|
||||
2. Check Auto Layout panel for padding values
|
||||
3. Note if padding is uniform or differs by direction
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Uniform padding
|
||||
padding: 16px → className="p-4"
|
||||
|
||||
// Directional padding
|
||||
paddingX: 16px, paddingY: 8px → className="px-4 py-2"
|
||||
|
||||
// Individual sides
|
||||
paddingTop: 16px → className="pt-4"
|
||||
paddingRight: 16px → className="pr-4"
|
||||
paddingBottom: 16px → className="pb-4"
|
||||
paddingLeft: 16px → className="pl-4"
|
||||
```
|
||||
|
||||
### 2. Margin (External Spacing)
|
||||
|
||||
Margin is the space around an element, separating it from adjacent elements.
|
||||
|
||||
**Figma Indicators:**
|
||||
- Space between sibling elements (when not using Auto Layout gap)
|
||||
- Constraints-based positioning with specific distances
|
||||
|
||||
**Important:** In modern Figma and React development, **margin is rarely used**. Use `gap` in Flexbox/Grid layouts instead.
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Top margin
|
||||
marginTop: 16px → className="mt-4"
|
||||
|
||||
// Horizontal centering
|
||||
marginX: auto → className="mx-auto"
|
||||
```
|
||||
|
||||
### 3. Gap (Spacing Between Items)
|
||||
|
||||
Gap is the space between flex or grid items.
|
||||
|
||||
**Figma Indicators:**
|
||||
- Auto Layout "Spacing between items" value
|
||||
- Consistent distance between sibling elements in Auto Layout
|
||||
|
||||
**Extraction Method:**
|
||||
1. Select the container with Auto Layout
|
||||
2. Check "Spacing between items" value
|
||||
3. For grid layouts, check both row and column gaps
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Uniform gap
|
||||
gap: 16px → className="gap-4"
|
||||
|
||||
// Directional gap (Flexbox column)
|
||||
gap: 16px → className="gap-y-4" (vertical gap in column layout)
|
||||
|
||||
// Grid with different row/column gaps
|
||||
rowGap: 16px, columnGap: 8px → className="gap-y-4 gap-x-2"
|
||||
```
|
||||
|
||||
## Tailwind Spacing Scale
|
||||
|
||||
Understand the Tailwind spacing scale for accurate conversion:
|
||||
|
||||
| Tailwind | rem | px (default) |
|
||||
|----------|-----|--------------|
|
||||
| 0 | 0 | 0 |
|
||||
| px | 1px | 1px |
|
||||
| 0.5 | 0.125rem | 2px |
|
||||
| 1 | 0.25rem | 4px |
|
||||
| 1.5 | 0.375rem | 6px |
|
||||
| 2 | 0.5rem | 8px |
|
||||
| 2.5 | 0.625rem | 10px |
|
||||
| 3 | 0.75rem | 12px |
|
||||
| 3.5 | 0.875rem | 14px |
|
||||
| 4 | 1rem | 16px |
|
||||
| 5 | 1.25rem | 20px |
|
||||
| 6 | 1.5rem | 24px |
|
||||
| 7 | 1.75rem | 28px |
|
||||
| 8 | 2rem | 32px |
|
||||
| 9 | 2.25rem | 36px |
|
||||
| 10 | 2.5rem | 40px |
|
||||
| 11 | 2.75rem | 44px |
|
||||
| 12 | 3rem | 48px |
|
||||
| 14 | 3.5rem | 56px |
|
||||
| 16 | 4rem | 64px |
|
||||
| 20 | 5rem | 80px |
|
||||
| 24 | 6rem | 96px |
|
||||
| 28 | 7rem | 112px |
|
||||
| 32 | 8rem | 128px |
|
||||
|
||||
## Conversion Process
|
||||
|
||||
### Step 1: Extract Pixel Values from Figma
|
||||
|
||||
Use Figma MCP tools to get the design context:
|
||||
```
|
||||
get_design_context → Returns spacing values in the design
|
||||
```
|
||||
|
||||
### Step 2: Convert to Tailwind Classes
|
||||
|
||||
1. **Exact Match**: If the pixel value matches Tailwind scale exactly, use that class
|
||||
- Example: 16px → `p-4`, 24px → `p-6`
|
||||
|
||||
2. **Close Match**: If within 1-2px, round to nearest Tailwind value
|
||||
- Example: 15px → `p-4` (16px), 23px → `p-6` (24px)
|
||||
|
||||
3. **Custom Value**: If no close match and pixel-perfect accuracy is required
|
||||
- Example: 18px → `p-[18px]`
|
||||
|
||||
4. **Design System**: If the project has a custom spacing scale, use that
|
||||
- Check tailwind.config.js for custom spacing values
|
||||
|
||||
### Step 3: Verify Consistency
|
||||
|
||||
Check if spacing is consistent across the design:
|
||||
- If a spacing value (e.g., 16px) is used frequently, prefer Tailwind's standard scale
|
||||
- If a spacing value is unique to one component, consider if it's intentional or a design inconsistency
|
||||
|
||||
## Auto Layout Analysis
|
||||
|
||||
### Reading Auto Layout Properties
|
||||
|
||||
When analyzing a Figma frame with Auto Layout:
|
||||
|
||||
1. **Direction**: Horizontal or Vertical
|
||||
- Determines `flex-row` or `flex-col`
|
||||
|
||||
2. **Spacing Between Items**: Gap value
|
||||
- Maps to `gap-{size}`
|
||||
|
||||
3. **Padding**: Top, Right, Bottom, Left
|
||||
- Maps to `p-{size}`, `px-{size}`, `py-{size}`, or individual `pt-/pr-/pb-/pl-`
|
||||
|
||||
4. **Alignment**:
|
||||
- Primary (main) axis: Maps to `justify-{align}`
|
||||
- Counter (cross) axis: Maps to `items-{align}`
|
||||
|
||||
### Example Auto Layout Translation
|
||||
|
||||
**Figma:**
|
||||
```
|
||||
Auto Layout: Vertical
|
||||
Spacing: 16px
|
||||
Padding: 24px (all sides)
|
||||
Alignment: Center (counter axis)
|
||||
```
|
||||
|
||||
**React + Tailwind:**
|
||||
```tsx
|
||||
<div className="flex flex-col gap-4 p-6 items-center">
|
||||
{/* children */}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Nested Spacing
|
||||
|
||||
When dealing with nested components:
|
||||
|
||||
1. **Outer Container**: Typically has padding
|
||||
2. **Inner Container**: Typically has gap between children
|
||||
3. **Individual Items**: Typically have no margin (gap handles spacing)
|
||||
|
||||
### Example:
|
||||
|
||||
```tsx
|
||||
{/* Outer container with padding */}
|
||||
<div className="p-6">
|
||||
{/* Inner container with gap */}
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Individual items - no margin needed */}
|
||||
<div>Item 1</div>
|
||||
<div>Item 2</div>
|
||||
<div>Item 3</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Responsive Spacing
|
||||
|
||||
Consider how spacing should adapt to different screen sizes:
|
||||
|
||||
```tsx
|
||||
{/* Responsive padding: smaller on mobile, larger on desktop */}
|
||||
<div className="p-4 md:p-6 lg:p-8">
|
||||
{/* Responsive gap */}
|
||||
<div className="flex flex-col gap-2 md:gap-4 lg:gap-6">
|
||||
{/* children */}
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Card Spacing
|
||||
```tsx
|
||||
// Typically: padding + gap for internal elements
|
||||
<div className="p-6 flex flex-col gap-4">
|
||||
<h2>Title</h2>
|
||||
<p>Content</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
### List Spacing
|
||||
```tsx
|
||||
// Typically: gap between items, no margin on items
|
||||
<ul className="flex flex-col gap-2">
|
||||
<li>Item 1</li>
|
||||
<li>Item 2</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
### Section Spacing
|
||||
```tsx
|
||||
// Typically: large padding on sections
|
||||
<section className="py-16 px-8">
|
||||
{/* content */}
|
||||
</section>
|
||||
```
|
||||
|
||||
## Pitfalls to Avoid
|
||||
|
||||
1. **Don't use margin when gap is available**: In Flexbox/Grid, use `gap` instead of margin on children
|
||||
2. **Don't mix spacing methods**: Stick to one approach (gap vs margin) within a container
|
||||
3. **Don't use arbitrary values unnecessarily**: Prefer Tailwind's scale when possible for consistency
|
||||
4. **Don't forget responsive spacing**: Consider how spacing should change across breakpoints
|
||||
5. **Don't ignore design system**: If the project has custom spacing, use it consistently
|
||||
|
||||
## Tips
|
||||
|
||||
- **Inspect carefully**: Always check both padding and gap values in Figma
|
||||
- **Use gap by default**: Modern Flexbox/Grid layouts should use gap, not margin
|
||||
- **Round to Tailwind scale**: Unless pixel-perfect accuracy is required, use standard Tailwind values
|
||||
- **Document custom values**: If using arbitrary values like `p-[18px]`, document why
|
||||
- **Check design system**: Verify if the project has custom spacing tokens in tailwind.config.js
|
||||
@@ -0,0 +1,456 @@
|
||||
# Typography Extraction Guide
|
||||
|
||||
This guide provides methods for extracting and translating typography properties from Figma to React + Tailwind CSS.
|
||||
|
||||
## Typography Properties
|
||||
|
||||
### 1. Font Family
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Font family dropdown
|
||||
|
||||
**Extraction:**
|
||||
- Note the exact font family name
|
||||
- Check if it's a system font, web font, or custom font
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Default Tailwind fonts
|
||||
font-sans → font-family: ui-sans-serif, system-ui, sans-serif...
|
||||
font-serif → font-family: ui-serif, Georgia, serif...
|
||||
font-mono → font-family: ui-monospace, monospace...
|
||||
|
||||
// Custom fonts (defined in tailwind.config.js)
|
||||
font-custom → font-family: 'CustomFont', sans-serif
|
||||
```
|
||||
|
||||
**Important:** Check the project's tailwind.config.js for custom font definitions:
|
||||
```js
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
'custom': ['CustomFont', 'sans-serif'],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Font Size
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Font size value (px)
|
||||
|
||||
**Extraction:**
|
||||
- Read the pixel value directly
|
||||
|
||||
**Tailwind Mapping:**
|
||||
|
||||
| Figma (px) | Tailwind Class | rem | Notes |
|
||||
|------------|---------------|-----|-------|
|
||||
| 12px | text-xs | 0.75rem | Extra small |
|
||||
| 14px | text-sm | 0.875rem | Small |
|
||||
| 16px | text-base | 1rem | Base size |
|
||||
| 18px | text-lg | 1.125rem | Large |
|
||||
| 20px | text-xl | 1.25rem | Extra large |
|
||||
| 24px | text-2xl | 1.5rem | 2x large |
|
||||
| 30px | text-3xl | 1.875rem | 3x large |
|
||||
| 36px | text-4xl | 2.25rem | 4x large |
|
||||
| 48px | text-5xl | 3rem | 5x large |
|
||||
| 60px | text-6xl | 3.75rem | 6x large |
|
||||
| 72px | text-7xl | 4.5rem | 7x large |
|
||||
| 96px | text-8xl | 6rem | 8x large |
|
||||
| 128px | text-9xl | 8rem | 9x large |
|
||||
|
||||
**Custom sizes:**
|
||||
```tsx
|
||||
// If exact match not available
|
||||
fontSize: 22px → className="text-[22px]"
|
||||
```
|
||||
|
||||
### 3. Font Weight
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Font weight dropdown (Thin, Light, Regular, Medium, Bold, etc.)
|
||||
|
||||
**Extraction:**
|
||||
- Note the weight name or numeric value
|
||||
|
||||
**Tailwind Mapping:**
|
||||
|
||||
| Figma Weight | Numeric | Tailwind Class |
|
||||
|--------------|---------|---------------|
|
||||
| Thin | 100 | font-thin |
|
||||
| Extra Light | 200 | font-extralight |
|
||||
| Light | 300 | font-light |
|
||||
| Regular/Normal | 400 | font-normal |
|
||||
| Medium | 500 | font-medium |
|
||||
| Semi Bold | 600 | font-semibold |
|
||||
| Bold | 700 | font-bold |
|
||||
| Extra Bold | 800 | font-extrabold |
|
||||
| Black | 900 | font-black |
|
||||
|
||||
### 4. Line Height (Leading)
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Line height value
|
||||
|
||||
**Types:**
|
||||
- **Auto**: Figma calculates automatically
|
||||
- **Pixel value**: Fixed line height (e.g., 24px)
|
||||
- **Percentage**: Relative to font size (e.g., 150%)
|
||||
|
||||
**Extraction:**
|
||||
1. Note the line height type
|
||||
2. For pixel values: Read directly
|
||||
3. For percentage: Calculate pixel value = font-size × percentage
|
||||
|
||||
**Tailwind Mapping:**
|
||||
|
||||
| Line Height | Tailwind Class | Value |
|
||||
|------------|---------------|-------|
|
||||
| Tight | leading-tight | 1.25 |
|
||||
| Snug | leading-snug | 1.375 |
|
||||
| Normal | leading-normal | 1.5 |
|
||||
| Relaxed | leading-relaxed | 1.625 |
|
||||
| Loose | leading-loose | 2 |
|
||||
| No line height | leading-none | 1 |
|
||||
|
||||
**Pixel-specific values:**
|
||||
```tsx
|
||||
// Fixed pixel line height
|
||||
lineHeight: 24px → className="leading-[24px]"
|
||||
```
|
||||
|
||||
**Relative values:**
|
||||
```tsx
|
||||
// When line height is 1.5x font size
|
||||
className="leading-normal"
|
||||
|
||||
// Custom relative value
|
||||
lineHeight: 1.75 → className="leading-[1.75]"
|
||||
```
|
||||
|
||||
### 5. Letter Spacing (Tracking)
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Letter spacing value
|
||||
|
||||
**Types:**
|
||||
- **Pixel value**: Fixed spacing (e.g., 0.5px)
|
||||
- **Percentage**: Relative to font size (e.g., 5%)
|
||||
|
||||
**Extraction:**
|
||||
1. Note the value and type
|
||||
2. For percentage: Convert to em units (5% = 0.05em)
|
||||
|
||||
**Tailwind Mapping:**
|
||||
|
||||
| Letter Spacing | Tailwind Class | Value |
|
||||
|---------------|---------------|-------|
|
||||
| Very tight | tracking-tighter | -0.05em |
|
||||
| Tight | tracking-tight | -0.025em |
|
||||
| Normal | tracking-normal | 0 |
|
||||
| Wide | tracking-wide | 0.025em |
|
||||
| Wider | tracking-wider | 0.05em |
|
||||
| Widest | tracking-widest | 0.1em |
|
||||
|
||||
**Custom values:**
|
||||
```tsx
|
||||
// Pixel value
|
||||
letterSpacing: 0.5px → className="tracking-[0.5px]"
|
||||
|
||||
// Em value
|
||||
letterSpacing: 0.03em → className="tracking-[0.03em]"
|
||||
```
|
||||
|
||||
### 6. Text Alignment
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Alignment buttons (left, center, right, justified)
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Horizontal alignment
|
||||
Left → className="text-left"
|
||||
Center → className="text-center"
|
||||
Right → className="text-right"
|
||||
Justified → className="text-justify"
|
||||
```
|
||||
|
||||
### 7. Text Color
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Fill color
|
||||
|
||||
**Extraction:**
|
||||
1. Get the color value (hex, RGB, or variable)
|
||||
2. Check if it's a Figma variable (design token)
|
||||
3. Note opacity if present
|
||||
|
||||
**Tailwind Mapping:**
|
||||
|
||||
**Using Tailwind colors:**
|
||||
```tsx
|
||||
// Named colors
|
||||
#000000 → className="text-black"
|
||||
#FFFFFF → className="text-white"
|
||||
#EF4444 → className="text-red-500"
|
||||
#3B82F6 → className="text-blue-500"
|
||||
```
|
||||
|
||||
**Using arbitrary colors:**
|
||||
```tsx
|
||||
// Hex color
|
||||
#1A202C → className="text-[#1A202C]"
|
||||
|
||||
// RGB color
|
||||
rgb(26, 32, 44) → className="text-[rgb(26,32,44)]"
|
||||
```
|
||||
|
||||
**Using design tokens (Figma variables):**
|
||||
```tsx
|
||||
// If Figma variable: "text/primary"
|
||||
// Should map to CSS variable or Tailwind custom color
|
||||
className="text-primary"
|
||||
```
|
||||
|
||||
**With opacity:**
|
||||
```tsx
|
||||
// 50% opacity
|
||||
className="text-black/50"
|
||||
className="text-blue-500/50"
|
||||
```
|
||||
|
||||
### 8. Text Decoration
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Decoration buttons (underline, strikethrough)
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
Underline → className="underline"
|
||||
Strikethrough → className="line-through"
|
||||
None → className="no-underline"
|
||||
```
|
||||
|
||||
### 9. Text Transform
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Text case dropdown
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
Uppercase → className="uppercase"
|
||||
Lowercase → className="lowercase"
|
||||
Capitalize → className="capitalize"
|
||||
None → className="normal-case"
|
||||
```
|
||||
|
||||
### 10. Text Overflow
|
||||
|
||||
**Figma Location:**
|
||||
- Text properties panel → Truncate option (...)
|
||||
|
||||
**Tailwind Mapping:**
|
||||
```tsx
|
||||
// Single line truncate
|
||||
className="truncate"
|
||||
|
||||
// Multi-line clamp (2 lines)
|
||||
className="line-clamp-2"
|
||||
|
||||
// Multi-line clamp (3 lines)
|
||||
className="line-clamp-3"
|
||||
```
|
||||
|
||||
## Figma Text Styles vs. React Implementation
|
||||
|
||||
### Extracting Text Styles
|
||||
|
||||
Figma allows designers to create reusable "Text Styles." When analyzing text:
|
||||
|
||||
1. **Check if a Text Style is applied**
|
||||
- If yes: Note the style name (e.g., "Heading 1", "Body Regular")
|
||||
- This indicates a reusable pattern
|
||||
|
||||
2. **Extract individual properties**
|
||||
- Even if a style is applied, extract individual properties
|
||||
- This helps create consistent React components
|
||||
|
||||
### Creating Reusable Typography Components
|
||||
|
||||
If the same text style is used multiple times, consider creating a reusable component:
|
||||
|
||||
```tsx
|
||||
// Typography.tsx
|
||||
export const Heading1 = ({ children, className = '' }: Props) => (
|
||||
<h1 className={`text-4xl font-bold leading-tight ${className}`}>
|
||||
{children}
|
||||
</h1>
|
||||
);
|
||||
|
||||
export const BodyText = ({ children, className = '' }: Props) => (
|
||||
<p className={`text-base font-normal leading-normal ${className}`}>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
```
|
||||
|
||||
## Complete Typography Analysis Workflow
|
||||
|
||||
When analyzing text in Figma:
|
||||
|
||||
1. **Identify the text element**
|
||||
- Note its semantic meaning (heading, paragraph, label, etc.)
|
||||
|
||||
2. **Extract font properties**
|
||||
- Font family
|
||||
- Font size
|
||||
- Font weight
|
||||
- Line height
|
||||
- Letter spacing
|
||||
|
||||
3. **Extract color and decoration**
|
||||
- Text color
|
||||
- Text decoration (underline, strikethrough)
|
||||
- Text transform (uppercase, lowercase)
|
||||
|
||||
4. **Extract alignment and overflow**
|
||||
- Text alignment
|
||||
- Truncation behavior
|
||||
|
||||
5. **Map to Tailwind classes**
|
||||
- Use standard Tailwind classes when possible
|
||||
- Use arbitrary values `[]` for custom values
|
||||
|
||||
6. **Choose appropriate HTML tag**
|
||||
- h1-h6 for headings
|
||||
- p for paragraphs
|
||||
- span for inline text
|
||||
- label for form labels
|
||||
|
||||
## Common Typography Patterns
|
||||
|
||||
### Headings
|
||||
|
||||
```tsx
|
||||
// Heading 1
|
||||
<h1 className="text-4xl font-bold leading-tight text-gray-900">
|
||||
Main Heading
|
||||
</h1>
|
||||
|
||||
// Heading 2
|
||||
<h2 className="text-3xl font-semibold leading-snug text-gray-800">
|
||||
Section Heading
|
||||
</h2>
|
||||
|
||||
// Heading 3
|
||||
<h3 className="text-2xl font-medium leading-normal text-gray-700">
|
||||
Subsection Heading
|
||||
</h3>
|
||||
```
|
||||
|
||||
### Body Text
|
||||
|
||||
```tsx
|
||||
// Regular body text
|
||||
<p className="text-base font-normal leading-relaxed text-gray-700">
|
||||
Lorem ipsum dolor sit amet...
|
||||
</p>
|
||||
|
||||
// Small text
|
||||
<p className="text-sm font-normal leading-normal text-gray-600">
|
||||
Small description text
|
||||
</p>
|
||||
|
||||
// Large text
|
||||
<p className="text-lg font-normal leading-relaxed text-gray-800">
|
||||
Emphasized body text
|
||||
</p>
|
||||
```
|
||||
|
||||
### Labels and Captions
|
||||
|
||||
```tsx
|
||||
// Form label
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
Input Label
|
||||
</label>
|
||||
|
||||
// Caption
|
||||
<span className="text-xs font-normal text-gray-500">
|
||||
Image caption or helper text
|
||||
</span>
|
||||
```
|
||||
|
||||
### Links
|
||||
|
||||
```tsx
|
||||
// Default link
|
||||
<a href="#" className="text-blue-600 underline hover:text-blue-800">
|
||||
Link text
|
||||
</a>
|
||||
|
||||
// Link without underline
|
||||
<a href="#" className="text-blue-600 hover:underline">
|
||||
Link text
|
||||
</a>
|
||||
```
|
||||
|
||||
## Responsive Typography
|
||||
|
||||
Consider how typography should adapt to different screen sizes:
|
||||
|
||||
```tsx
|
||||
{/* Responsive font size */}
|
||||
<h1 className="text-2xl md:text-3xl lg:text-4xl font-bold">
|
||||
Responsive Heading
|
||||
</h1>
|
||||
|
||||
{/* Responsive line height */}
|
||||
<p className="leading-normal md:leading-relaxed lg:leading-loose">
|
||||
Responsive paragraph
|
||||
</p>
|
||||
```
|
||||
|
||||
## Design Tokens and Figma Variables
|
||||
|
||||
If the design uses Figma variables for typography:
|
||||
|
||||
1. **Extract variable names**
|
||||
- e.g., "fontSize.heading.large", "color.text.primary"
|
||||
|
||||
2. **Map to CSS variables or Tailwind config**
|
||||
- Check tailwind.config.js for custom tokens
|
||||
- Use semantic class names
|
||||
|
||||
3. **Example:**
|
||||
```tsx
|
||||
// Figma variable: "text/heading/large"
|
||||
// Maps to: text-heading-lg (defined in tailwind.config.js)
|
||||
<h1 className="text-heading-lg font-bold">
|
||||
Heading
|
||||
</h1>
|
||||
```
|
||||
|
||||
## Pitfalls to Avoid
|
||||
|
||||
1. **Don't hardcode colors**: Use design tokens when available
|
||||
2. **Don't use arbitrary values unnecessarily**: Prefer Tailwind's scale for consistency
|
||||
3. **Don't forget line height**: It affects vertical rhythm significantly
|
||||
4. **Don't ignore font loading**: Ensure custom fonts are properly loaded
|
||||
5. **Don't skip semantic HTML**: Use h1-h6, p, etc. appropriately for accessibility
|
||||
6. **Don't forget responsive typography**: Typography should adapt to screen size
|
||||
|
||||
## Tips
|
||||
|
||||
- **Use Figma's Inspect Panel**: Hover over text to see all properties at once
|
||||
- **Check for Text Styles**: Reusable styles indicate design system patterns
|
||||
- **Verify font availability**: Ensure custom fonts are available in the project
|
||||
- **Consider accessibility**: Ensure sufficient color contrast (WCAG AA: 4.5:1 for normal text)
|
||||
- **Use semantic HTML**: Choose the right tag for the content's meaning, not just appearance
|
||||
- **Document custom values**: If using arbitrary values like `text-[17px]`, document why
|
||||
- **Test on real devices**: Typography can look different on various screens
|
||||
611
skills/nextjs-react-implementation/SKILL.md
Normal file
611
skills/nextjs-react-implementation/SKILL.md
Normal file
@@ -0,0 +1,611 @@
|
||||
---
|
||||
name: nextjs-react-implementation
|
||||
description: Generate production-ready Next.js/React components from design specifications. Use this skill when you have a design specification document and need to create React/TypeScript components with Tailwind CSS styling, Vitest tests, and Storybook documentation.
|
||||
---
|
||||
|
||||
# Next.js React Implementation Generator
|
||||
|
||||
## Overview
|
||||
|
||||
Transform design specification documents into production-ready Next.js/React components with complete TypeScript types, Tailwind CSS styling, comprehensive tests, and Storybook documentation. This skill focuses on accurate implementation following modern React patterns and best practices.
|
||||
|
||||
**Use this skill when:**
|
||||
- Implementing components from design specifications
|
||||
- Creating React components with TypeScript
|
||||
- Generating Tailwind CSS styled components
|
||||
- Writing Vitest browser mode tests
|
||||
- Creating Storybook documentation
|
||||
- Building component libraries
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This skill expects a design specification document created by the `figma-design-analyzer` skill or a similar structured specification. The specification should include:
|
||||
|
||||
- Component name and atomic category
|
||||
- Semantic HTML element
|
||||
- Layout and spacing details
|
||||
- Typography specifications
|
||||
- Color and visual properties
|
||||
- Variants and states
|
||||
- Responsive behavior
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Step 1: Parse Design Specification
|
||||
|
||||
Read and understand the design specification document:
|
||||
|
||||
1. **Load the specification file:**
|
||||
- Read the `.design.md` file
|
||||
- Parse front matter metadata
|
||||
- Extract all design properties
|
||||
|
||||
2. **Identify key information:**
|
||||
- Component name (PascalCase)
|
||||
- Atomic category (Atom/Molecule/Organism)
|
||||
- Semantic root element
|
||||
- Variants and their options
|
||||
- States (hover, active, disabled, etc.)
|
||||
|
||||
3. **Validate specification:**
|
||||
- Ensure all required fields are present
|
||||
- Check for contradictions or ambiguities
|
||||
- Note any missing information
|
||||
|
||||
### Step 2: Determine Component Structure
|
||||
|
||||
Plan the component implementation:
|
||||
|
||||
1. **Determine component directory:**
|
||||
```
|
||||
src/components/
|
||||
atoms/ComponentName/
|
||||
molecules/ComponentName/
|
||||
organisms/ComponentName/
|
||||
```
|
||||
|
||||
2. **Plan file structure:**
|
||||
```
|
||||
ComponentName/
|
||||
├── index.ts # Barrel export
|
||||
├── ComponentName.tsx # Component implementation
|
||||
├── ComponentName.test.tsx # Vitest tests
|
||||
└── ComponentName.stories.tsx # Storybook stories
|
||||
```
|
||||
|
||||
3. **Identify dependencies:**
|
||||
- Child components (for Molecules/Organisms)
|
||||
- Icons or assets
|
||||
- Utility functions
|
||||
|
||||
### Step 3: Generate TypeScript Props Interface
|
||||
|
||||
Create type-safe props based on the specification:
|
||||
|
||||
1. **Read variant information from spec:**
|
||||
```markdown
|
||||
## Variants
|
||||
- variant: primary | secondary | tertiary
|
||||
- size: small | medium | large
|
||||
```
|
||||
|
||||
2. **Create props interface:**
|
||||
```typescript
|
||||
export interface ButtonProps {
|
||||
/** Button variant style */
|
||||
variant?: 'primary' | 'secondary' | 'tertiary';
|
||||
/** Button size */
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
/** Button content */
|
||||
children: React.ReactNode;
|
||||
/** Click handler */
|
||||
onClick?: () => void;
|
||||
/** Disabled state */
|
||||
disabled?: boolean;
|
||||
/** Additional CSS classes */
|
||||
className?: string;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Set default props:**
|
||||
- Define sensible defaults based on the "Default" state in spec
|
||||
- Use TypeScript default parameters
|
||||
|
||||
### Step 4: Generate Component Implementation
|
||||
|
||||
Use the component template to create the implementation:
|
||||
|
||||
1. **Read the component template:**
|
||||
```
|
||||
assets/templates/component.tsx.template
|
||||
```
|
||||
|
||||
2. **Fill in template placeholders:**
|
||||
- `{{COMPONENT_NAME}}`: Component name in PascalCase
|
||||
- `{{COMPONENT_DESCRIPTION}}`: Brief description from spec
|
||||
- `{{ATOMIC_CATEGORY}}`: Atoms, Molecules, or Organisms
|
||||
- `{{ROOT_ELEMENT}}`: Semantic HTML element
|
||||
- `{{TAILWIND_CLASSES}}`: Base Tailwind classes from spec
|
||||
|
||||
3. **Implement variant logic:**
|
||||
```typescript
|
||||
const variantClasses = {
|
||||
primary: 'bg-blue-500 text-white hover:bg-blue-600',
|
||||
secondary: 'bg-white text-blue-500 border-blue-500 hover:bg-blue-50',
|
||||
tertiary: 'bg-transparent text-blue-500 hover:bg-blue-50'
|
||||
};
|
||||
|
||||
const sizeClasses = {
|
||||
small: 'px-4 py-2 text-sm',
|
||||
medium: 'px-6 py-3 text-base',
|
||||
large: 'px-8 py-4 text-lg'
|
||||
};
|
||||
|
||||
const className = cn(
|
||||
'inline-flex items-center justify-center rounded-lg font-semibold',
|
||||
'transition-colors duration-200',
|
||||
'disabled:opacity-50 disabled:cursor-not-allowed',
|
||||
variantClasses[variant],
|
||||
sizeClasses[size],
|
||||
props.className
|
||||
);
|
||||
```
|
||||
|
||||
4. **Handle responsive behavior:**
|
||||
- Use Tailwind responsive prefixes from spec
|
||||
- Implement mobile-first approach
|
||||
```typescript
|
||||
className = cn(
|
||||
'w-full md:w-auto', // Full width on mobile, auto on tablet+
|
||||
'px-4 md:px-6 lg:px-8', // Responsive padding
|
||||
// ... other classes
|
||||
);
|
||||
```
|
||||
|
||||
5. **Implement accessibility:**
|
||||
- Add ARIA attributes as specified
|
||||
- Ensure keyboard navigation
|
||||
- Include focus states
|
||||
```typescript
|
||||
<button
|
||||
className={className}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
aria-label={ariaLabel}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
```
|
||||
|
||||
### Step 5: Generate Vitest Browser Mode Tests
|
||||
|
||||
Create comprehensive tests using the test template:
|
||||
|
||||
1. **Read the test template:**
|
||||
```
|
||||
assets/templates/test.tsx.template
|
||||
```
|
||||
|
||||
2. **Set up test structure:**
|
||||
```typescript
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { page } from '@vitest/browser/context';
|
||||
import { render } from 'vitest-browser-react';
|
||||
import { Button } from './Button';
|
||||
|
||||
describe('Button', () => {
|
||||
// Test cases here
|
||||
});
|
||||
```
|
||||
|
||||
3. **Follow TDD principles with Arrange-Act-Assert:**
|
||||
```typescript
|
||||
it('正しくレンダリングされること', async () => {
|
||||
// Arrange
|
||||
const props = { children: 'Click Me' };
|
||||
|
||||
// Act
|
||||
await render(<Button {...props} />);
|
||||
|
||||
// Assert
|
||||
const button = page.getByRole('button', { name: 'Click Me' });
|
||||
await expect.element(button).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
4. **Test all variants:**
|
||||
```typescript
|
||||
it.each([
|
||||
{ variant: 'primary', expectedClass: 'bg-blue-500' },
|
||||
{ variant: 'secondary', expectedClass: 'bg-white' },
|
||||
{ variant: 'tertiary', expectedClass: 'bg-transparent' }
|
||||
])('$variant バリアントが正しくレンダリングされること', async ({ variant, expectedClass }) => {
|
||||
// Arrange & Act
|
||||
await render(<Button variant={variant}>Button</Button>);
|
||||
|
||||
// Assert
|
||||
const button = page.getByRole('button');
|
||||
await expect.element(button).toHaveClass(expectedClass);
|
||||
});
|
||||
```
|
||||
|
||||
5. **Test all states:**
|
||||
```typescript
|
||||
it('無効状態が正しく動作すること', async () => {
|
||||
// Arrange
|
||||
const handleClick = vi.fn();
|
||||
await render(
|
||||
<Button disabled onClick={handleClick}>
|
||||
Disabled
|
||||
</Button>
|
||||
);
|
||||
|
||||
// Act
|
||||
const button = page.getByRole('button');
|
||||
await button.click();
|
||||
|
||||
// Assert
|
||||
await expect.element(button).toBeDisabled();
|
||||
expect(handleClick).not.toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
6. **Test interactions:**
|
||||
```typescript
|
||||
it('クリックイベントが動作すること', async () => {
|
||||
// Arrange
|
||||
const handleClick = vi.fn();
|
||||
await render(<Button onClick={handleClick}>Click Me</Button>);
|
||||
|
||||
// Act
|
||||
const button = page.getByRole('button');
|
||||
await button.click();
|
||||
|
||||
// Assert
|
||||
expect(handleClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
```
|
||||
|
||||
7. **Test accessibility:**
|
||||
```typescript
|
||||
it('キーボード操作が動作すること', async () => {
|
||||
// Arrange
|
||||
const handleClick = vi.fn();
|
||||
await render(<Button onClick={handleClick}>Press Enter</Button>);
|
||||
|
||||
// Act
|
||||
const button = page.getByRole('button');
|
||||
await button.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
// Assert
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
### Step 6: Generate Storybook Stories
|
||||
|
||||
Create interactive documentation:
|
||||
|
||||
1. **Read the Storybook template:**
|
||||
```
|
||||
assets/templates/storybook.tsx.template
|
||||
```
|
||||
|
||||
2. **Set up story structure:**
|
||||
```typescript
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Button } from './Button';
|
||||
|
||||
const meta = {
|
||||
title: 'Atoms/Button',
|
||||
component: Button,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: ['primary', 'secondary', 'tertiary']
|
||||
},
|
||||
size: {
|
||||
control: 'select',
|
||||
options: ['small', 'medium', 'large']
|
||||
}
|
||||
}
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
```
|
||||
|
||||
3. **Create stories for each variant:**
|
||||
```typescript
|
||||
export const Primary: Story = {
|
||||
args: {
|
||||
variant: 'primary',
|
||||
children: 'Primary Button'
|
||||
}
|
||||
};
|
||||
|
||||
export const Secondary: Story = {
|
||||
args: {
|
||||
variant: 'secondary',
|
||||
children: 'Secondary Button'
|
||||
}
|
||||
};
|
||||
|
||||
export const Tertiary: Story = {
|
||||
args: {
|
||||
variant: 'tertiary',
|
||||
children: 'Tertiary Button'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
4. **Create stories for different sizes:**
|
||||
```typescript
|
||||
export const Small: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
children: 'Small Button'
|
||||
}
|
||||
};
|
||||
|
||||
export const Medium: Story = {
|
||||
args: {
|
||||
size: 'medium',
|
||||
children: 'Medium Button'
|
||||
}
|
||||
};
|
||||
|
||||
export const Large: Story = {
|
||||
args: {
|
||||
size: 'large',
|
||||
children: 'Large Button'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
5. **Create stories for states:**
|
||||
```typescript
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
disabled: true,
|
||||
children: 'Disabled Button'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
6. **Create interactive playground:**
|
||||
```typescript
|
||||
export const Playground: Story = {
|
||||
args: {
|
||||
variant: 'primary',
|
||||
size: 'medium',
|
||||
children: 'Playground Button'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Step 7: Handle Complex Components
|
||||
|
||||
For Molecules and Organisms that use child components:
|
||||
|
||||
1. **Identify child components:**
|
||||
- Read component hierarchy from spec
|
||||
- Import child components
|
||||
|
||||
2. **Compose the component:**
|
||||
```typescript
|
||||
import { Button } from '@/components/atoms/Button';
|
||||
import { Input } from '@/components/atoms/Input';
|
||||
|
||||
export function SearchBar({ onSearch }: SearchBarProps) {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Input placeholder="Search..." />
|
||||
<Button onClick={onSearch}>Search</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
3. **Pass props to children:**
|
||||
- Map parent props to child props
|
||||
- Handle event delegation
|
||||
|
||||
### Step 8: Implement Responsive Behavior
|
||||
|
||||
Add responsive styles based on the specification:
|
||||
|
||||
1. **Read responsive behavior from spec:**
|
||||
```markdown
|
||||
## Responsive Behavior
|
||||
- Mobile (default): flex-col gap-4 text-sm
|
||||
- Tablet (md): md:flex-row md:gap-6 md:text-base
|
||||
- Desktop (lg): lg:gap-8 lg:text-lg
|
||||
```
|
||||
|
||||
2. **Apply Tailwind responsive prefixes:**
|
||||
```typescript
|
||||
className = cn(
|
||||
'flex flex-col gap-4 text-sm', // Mobile (default)
|
||||
'md:flex-row md:gap-6 md:text-base', // Tablet
|
||||
'lg:gap-8 lg:text-lg', // Desktop
|
||||
// ... other classes
|
||||
);
|
||||
```
|
||||
|
||||
3. **Test responsive behavior:**
|
||||
- Test at different viewport sizes
|
||||
- Verify layout changes
|
||||
|
||||
### Step 9: Add Barrel Export
|
||||
|
||||
Create index.ts for clean imports:
|
||||
|
||||
```typescript
|
||||
export { Button } from './Button';
|
||||
export type { ButtonProps } from './Button';
|
||||
```
|
||||
|
||||
### Step 10: Verify Implementation
|
||||
|
||||
Final checks before completion:
|
||||
|
||||
1. **Verify against specification:**
|
||||
- All variants implemented
|
||||
- All states handled
|
||||
- Responsive behavior correct
|
||||
- Accessibility requirements met
|
||||
|
||||
2. **Run tests:**
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
|
||||
3. **Run Storybook:**
|
||||
```bash
|
||||
npm run storybook
|
||||
```
|
||||
|
||||
4. **Type check:**
|
||||
```bash
|
||||
npm run type-check
|
||||
```
|
||||
|
||||
5. **Lint:**
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## Using Context7 for Latest Documentation
|
||||
|
||||
Always use Context7 MCP to get up-to-date documentation:
|
||||
|
||||
1. **Resolve library IDs:**
|
||||
```
|
||||
mcp__context7__resolve-library-id(libraryName: "react")
|
||||
mcp__context7__resolve-library-id(libraryName: "tailwindcss")
|
||||
mcp__context7__resolve-library-id(libraryName: "vitest")
|
||||
```
|
||||
|
||||
2. **Get library documentation:**
|
||||
```
|
||||
mcp__context7__get-library-docs(
|
||||
context7CompatibleLibraryID: "/facebook/react",
|
||||
topic: "hooks"
|
||||
)
|
||||
```
|
||||
|
||||
3. **Check project versions:**
|
||||
- Read package.json to determine versions
|
||||
- Use exact version for Context7 if available
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Type Safety:**
|
||||
- Use strict TypeScript
|
||||
- Define all props with proper types
|
||||
- Avoid `any` type
|
||||
|
||||
2. **Component Composition:**
|
||||
- Keep components focused and single-purpose
|
||||
- Use composition over inheritance
|
||||
- Extract reusable logic into hooks
|
||||
|
||||
3. **Styling:**
|
||||
- Use Tailwind CSS utility classes
|
||||
- Follow project's Tailwind configuration
|
||||
- Use `cn()` utility for conditional classes
|
||||
|
||||
4. **Testing:**
|
||||
- Write tests before implementation (TDD)
|
||||
- Test all variants and states
|
||||
- Test user interactions
|
||||
- Test accessibility
|
||||
|
||||
5. **Documentation:**
|
||||
- Add JSDoc comments to props
|
||||
- Create comprehensive Storybook stories
|
||||
- Include usage examples
|
||||
|
||||
6. **Accessibility:**
|
||||
- Use semantic HTML
|
||||
- Add ARIA attributes when needed
|
||||
- Ensure keyboard navigation
|
||||
- Test with screen readers
|
||||
|
||||
7. **Performance:**
|
||||
- Avoid unnecessary re-renders
|
||||
- Use React.memo when appropriate
|
||||
- Optimize large lists with virtualization
|
||||
|
||||
## Resources
|
||||
|
||||
This skill includes templates for code generation:
|
||||
|
||||
### assets/templates/
|
||||
|
||||
- **component.tsx.template**: React/TypeScript component structure
|
||||
- **test.tsx.template**: Vitest browser mode test structure
|
||||
- **storybook.tsx.template**: Storybook story structure
|
||||
|
||||
**Usage:** Use these templates as starting points. Fill in placeholders with values from the design specification.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Ignoring the specification:**
|
||||
- Always implement exactly as specified
|
||||
- Don't make assumptions
|
||||
- Ask for clarification if ambiguous
|
||||
|
||||
2. **Incomplete variant handling:**
|
||||
- Implement all variants from spec
|
||||
- Don't skip edge cases
|
||||
|
||||
3. **Poor test coverage:**
|
||||
- Test all variants
|
||||
- Test all states
|
||||
- Test all interactions
|
||||
|
||||
4. **Accessibility oversights:**
|
||||
- Don't forget ARIA attributes
|
||||
- Ensure keyboard navigation
|
||||
- Test with assistive technologies
|
||||
|
||||
5. **Inconsistent naming:**
|
||||
- Follow project naming conventions
|
||||
- Use consistent prop names
|
||||
- Match Figma component names
|
||||
|
||||
6. **Hardcoded values:**
|
||||
- Use props and configuration
|
||||
- Avoid magic numbers
|
||||
- Use design tokens when available
|
||||
|
||||
## Example Implementation Flow
|
||||
|
||||
**Input:** Button.design.md specification
|
||||
|
||||
**Steps:**
|
||||
1. Parse specification
|
||||
2. Create directory: `src/components/atoms/Button/`
|
||||
3. Generate `Button.tsx` with variants (primary, secondary, tertiary) and sizes (small, medium, large)
|
||||
4. Generate `Button.test.tsx` with tests for all variants, sizes, and states
|
||||
5. Generate `Button.stories.tsx` with interactive stories
|
||||
6. Create `index.ts` barrel export
|
||||
7. Verify implementation against specification
|
||||
8. Run tests and Storybook
|
||||
|
||||
**Output:**
|
||||
- Production-ready Button component
|
||||
- Comprehensive test suite
|
||||
- Interactive Storybook documentation
|
||||
|
||||
---
|
||||
|
||||
**This skill transforms design specifications into production-ready Next.js/React components with complete testing and documentation.**
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* {{COMPONENT_NAME}}
|
||||
*
|
||||
* {{COMPONENT_DESCRIPTION}}
|
||||
*
|
||||
* @category {{ATOMIC_CATEGORY}}
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export interface {{COMPONENT_NAME}}Props {
|
||||
/**
|
||||
* {{PROP_DESCRIPTION}}
|
||||
*/
|
||||
{{PROP_NAME}}{{PROP_OPTIONAL}}: {{PROP_TYPE}};
|
||||
}
|
||||
|
||||
/**
|
||||
* {{COMPONENT_NAME}} component
|
||||
*
|
||||
* {{USAGE_EXAMPLE}}
|
||||
*/
|
||||
export const {{COMPONENT_NAME}} = ({
|
||||
{{PROPS_DESTRUCTURED}}
|
||||
}: {{COMPONENT_NAME}}Props) => {
|
||||
return (
|
||||
<{{ROOT_ELEMENT}} className="{{TAILWIND_CLASSES}}">
|
||||
{{COMPONENT_CONTENT}}
|
||||
</{{ROOT_ELEMENT}}>
|
||||
);
|
||||
};
|
||||
|
||||
{{COMPONENT_NAME}}.displayName = '{{COMPONENT_NAME}}';
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* {{COMPONENT_NAME}} の Storybook ストーリー
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { {{COMPONENT_NAME}} } from './{{COMPONENT_NAME}}';
|
||||
|
||||
const meta = {
|
||||
title: '{{ATOMIC_CATEGORY}}/{{COMPONENT_NAME}}',
|
||||
component: {{COMPONENT_NAME}},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
{{ARG_TYPES}}
|
||||
},
|
||||
} satisfies Meta<typeof {{COMPONENT_NAME}}>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
/**
|
||||
* デフォルトの {{COMPONENT_NAME}}
|
||||
*/
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
{{DEFAULT_ARGS}}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* {{VARIANT_DESCRIPTION}}
|
||||
*/
|
||||
export const {{VARIANT_NAME}}: Story = {
|
||||
args: {
|
||||
{{VARIANT_ARGS}}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* {{COMPONENT_NAME}} のテスト
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { page } from '@vitest/browser/context';
|
||||
import { render } from 'vitest-browser-react';
|
||||
import { {{COMPONENT_NAME}} } from './{{COMPONENT_NAME}}';
|
||||
|
||||
describe('{{COMPONENT_NAME}}', () => {
|
||||
it('正しくレンダリングされること', async () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
{{TEST_PROPS}}
|
||||
};
|
||||
|
||||
// Act
|
||||
await render(<{{COMPONENT_NAME}} {...props} />);
|
||||
|
||||
// Assert
|
||||
{{TEST_ASSERTIONS}}
|
||||
});
|
||||
|
||||
it('{{TEST_CASE_DESCRIPTION}}', async () => {
|
||||
// Arrange
|
||||
{{TEST_ARRANGE}}
|
||||
|
||||
// Act
|
||||
{{TEST_ACT}}
|
||||
|
||||
// Assert
|
||||
{{TEST_ASSERT}}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user