web-component-development
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb Component Development
Web组件开发
Workflow
工作流
Phase 1: Design Extraction
阶段1:设计提取
Step 1: Overview (you do this yourself)
You MUST personally inspect the design before delegating anything:
- Fetch Figma node via MCP (,
get_design_context).get_screenshot - Take a screenshot — study the overall visual: layout structure, hierarchy, proportions, and color balance.
- Understand the design intent, component relationships, and visual rhythm.
- Identify distinct components or layers that need detailed extraction (e.g. header, card, button, icon group).
Do NOT skip this step or delegate it. You need the high-level context to coordinate subagents effectively.
Step 2: Parallel deep-dive (MUST delegate to subagents)
You MUST spawn subagents in parallel to extract detailed specs for each identified component/layer. Do NOT attempt to extract fine-grained details yourself — subagents have dedicated context for exhaustive spec extraction.
Each subagent extracts:
- Font: family, weight, size, line-height, letter-spacing, text-align, text-transform, text-decoration.
- Color: foreground, background (solid/gradient), border, opacity (exact values including alpha).
- Spacing: padding, margin, gap (every direction).
- Dimensions: width, height, min/max constraints.
- Effects: border-radius (per corner), border-width, box-shadow (offset, blur, spread, color), opacity, overflow.
- Icons: sizing, stroke width, color.
- States: hover, active, focus, disabled variations if present.
Each subagent should:
- Fetch the specific node's and
get_design_context.get_screenshot - Record ALL specs exhaustively — leave nothing unspecified.
- Map Figma tokens to project design system tokens where they exist; use raw values only when no token matches.
- Return a structured spec object for the component.
Step 3: Synthesis
Collect and merge all subagent results into a unified design spec before proceeding to implementation.
步骤1:概览(需自行完成)
在委派任何任务前,你必须亲自检查设计:
- 通过MCP获取Figma节点(、
get_design_context)。get_screenshot - 截取截图——研究整体视觉效果:布局结构、层级、比例和色彩平衡。
- 理解设计意图、组件关系和视觉节奏。
- 识别需要详细提取的独立组件或图层(例如页眉、卡片、按钮、图标组)。
请勿跳过此步骤或委派他人完成。你需要掌握高层上下文才能有效协调子代理。
步骤2:并行深度解析(必须委派给子代理)
你必须并行生成子代理,为每个已识别的组件/图层提取详细规格。请勿尝试自行提取细粒度细节——子代理具备专门的上下文,可进行详尽的规格提取。
每个子代理提取以下内容:
- 字体:字体系列、字重、字号、行高、字符间距、文本对齐、文本转换、文本装饰。
- 颜色:前景色、背景色(纯色/渐变)、边框、透明度(包含alpha通道的精确值)。
- 间距:内边距、外边距、间隙(各个方向)。
- 尺寸:宽度、高度、最小/最大约束。
- 效果:圆角(每个角)、边框宽度、盒阴影(偏移量、模糊度、扩散度、颜色)、透明度、溢出。
- 图标:尺寸、描边宽度、颜色。
- 状态:若存在悬停、激活、聚焦、禁用等变体则提取。
每个子代理应执行以下操作:
- 获取特定节点的和
get_design_context。get_screenshot - 详尽记录所有规格——不要遗漏任何细节。
- 将Figma标记映射到项目设计系统中已有的标记;仅当无匹配标记时使用原始值。
- 返回组件的结构化规格对象。
步骤3:合成
在进入实现阶段前,收集并合并所有子代理的结果,形成统一的设计规格。
Phase 2: Implementation
阶段2:实现
Start small. Start simple.
Build the smallest possible working version first with an elegant, minimal API.
- Do NOT add anything beyond what the design shows — no bonus features, no "improvements", no embellishments.
- Do NOT write hacky code — if the approach feels wrong, step back and redesign.
- Do NOT over-engineer for hypothetical future requirements.
Once verified correct, we incrementally add functionality.
Write the component following these principles:
Design fidelity — Faithfully convey the design's intent, not pixel-for-pixel reproduction of static values. Round obviously unreasonable fractional values that are Figma artifacts (e.g. → ). Adapt static layouts to responsive/interactive reality. The design is a communication, not a specification.
12.1px12pxShallow DOM — Use modern CSS layout (, ) directly. Avoid wrapper divs that exist only for styling. Every DOM node should carry semantic or layout purpose.
flexgridBorder & stroke strategy — Choose deliberately:
| Technique | Layout impact | When to use |
|---|---|---|
| Yes (shrinks content) | When border is part of the sizing model |
| No | Non-layout-affecting focus rings, selection |
| No | Decorative strokes, glow, elevation |
Absolute overlay | No | Complex multi-layer strokes on rounded corners |
Maintain border-radius concentricity: .
inner-radius = outer-radius − border-widthTypography — Set every parameter explicitly: , , , , , . Do not rely on inherited or default values for components.
font-familyfont-weightfont-sizeline-heightletter-spacingcolorColor — Use exact values from Figma including alpha. Prefer or Tailwind opacity modifiers () over approximation. Add variants for colors that lose contrast on dark backgrounds.
rgba()text-black/70dark:Touch targets — For buttons and clickable elements with small visual footprints, use an absolutely positioned pseudo-element (or a child div) with negative inset to expand the interactive area to at least 44×44px without affecting layout.
::afterAnimations — Use Motion (previously Framer Motion). Always call and skip or simplify animation when true. This also ensures deterministic screenshot testing.
useReducedMotion()从小处着手,从简开始。
首先构建最小可运行版本,采用简洁、极简的API。
- 请勿添加设计未展示的任何内容——无额外功能、无“改进”、无修饰。
- 请勿编写粗糙代码——若方法感觉有误,请退一步重新设计。
- 请勿为假设的未来需求过度设计。
在验证正确后,我们逐步添加功能。
遵循以下原则编写组件:
设计保真度——忠实地传达设计的_意图_,而非静态值的像素级复刻。对明显不合理的Figma artifact小数数值进行取整(例如 → )。使静态布局适配响应式/交互式实际场景。设计是一种沟通方式,而非严格规范。
12.1px12px扁平化DOM——直接使用现代CSS布局(、)。避免仅用于样式的包装div。每个DOM节点都应承载语义或布局用途。
flexgrid边框与描边策略——谨慎选择:
| 技术手段 | 布局影响 | 适用场景 |
|---|---|---|
| 是(会缩小内容) | 当边框属于尺寸模型的一部分时 |
| 否 | 不影响布局的聚焦环、选区 |
| 否 | 装饰性描边、发光效果、层级提升 |
绝对定位覆盖 | 否 | 圆角上的复杂多层描边 |
保持圆角同心度:。
inner-radius = outer-radius − border-width排版——显式设置每个参数:、、、、、。组件请勿依赖继承或默认值。
font-familyfont-weightfont-sizeline-heightletter-spacingcolor颜色——使用Figma中的精确值,包括alpha通道。优先使用或Tailwind透明度修饰符()而非近似值。为在深色背景上失去对比度的颜色添加变体。
rgba()text-black/70dark:触摸目标——对于视觉尺寸较小的按钮和可点击元素,使用绝对定位的伪元素(或子div)并设置负inset,将交互区域扩展至至少44×44px且不影响布局。
::after动画——使用Motion(原Framer Motion)。始终调用,当返回值为true时跳过或简化动画。这也确保了截图测试的确定性。
useReducedMotion()Phase 3: Stories
阶段3:Storybook故事
Write Storybook stories covering every meaningful variant before visual verification.
- One story per variant/state.
- A single composite story that elegantly lays out all variants — just the components themselves, no extra labels or decorations.
- Use seeded/deterministic data — no or
Math.random()in stories. Use hardcoded values or a seeded PRNG.Date.now()
Layout mode — Ask: "Am I showing a specimen, or simulating a host?"
| Mode | When | Example |
|---|---|---|
| Displaying a self-contained component whose size is determined by its content | Button, Badge, Input, Card |
| Simulating a real page host where the component fills or arranges within space | Dashboard, list page, split-pane, sidebar |
Container width — When a component's width semantics depend on "how wide is my host" (Card, Dialog, Form), use a decorator to provide an explicit width container:
tsx
export const Default: Story = {
decorators: [
(Story) => (
<div className="w-[360px] max-w-full">
<Story />
</div>
),
],
};Do NOT hard-code a width when the component is meant to participate in page-level layout (, , ). Instead, provide a layout container that defines the spatial context (fullscreen + padding wrapper, content area, explicit grid/flex parent).
w-fullflex-1gridmax-w-*Rule of thumb: unit component story → + explicit wrapper width; page/region component story → + layout container.
centeredfullscreen在视觉验证前,编写涵盖所有有意义变体的Storybook故事。
- 每个变体/状态对应一个故事。
- 一个组合故事,优雅地展示所有变体——仅展示组件本身,无额外标签或装饰。
- 使用种子化/确定性数据——故事中请勿使用或
Math.random()。使用硬编码值或种子化伪随机数生成器。Date.now()
布局模式——思考:“我是在展示样本,还是模拟宿主环境?”
| 模式 | 适用场景 | 示例 |
|---|---|---|
| 展示尺寸由内容决定的独立组件时 | 按钮、徽章、输入框、卡片 |
| 模拟真实页面宿主环境,组件填充或排列在空间内时 | 仪表盘、列表页、分栏面板、侧边栏 |
容器宽度——当组件的宽度语义依赖于“宿主有多宽”时(卡片、对话框、表单),使用装饰器提供明确的宽度容器:
tsx
export const Default: Story = {
decorators: [
(Story) => (
<div className="w-[360px] max-w-full">
<Story />
</div>
),
],
};当组件需要参与页面级布局时(、、),请勿硬编码宽度。相反,提供定义空间上下文的布局容器(全屏+内边距包装器、内容区域、明确的网格/弹性父容器)。
w-fullflex-1gridmax-w-*经验法则:单元组件故事 → + 明确的包装器宽度;页面/区域组件故事 → + 布局容器。
centeredfullscreenPhase 4: Browser Verification
阶段4:浏览器验证
Always verify every component in the browser before considering it done.
- Open the story's iframe URL directly (e.g. ) to get the isolated component without Storybook chrome.
http://localhost:6006/iframe.html?id=components-button--default - Inspect the rendered DOM — confirm every CSS property matches the Figma spec:
- Font: family, weight, size, line-height, letter-spacing.
- Color: foreground, background, border, opacity.
- Spacing: padding, margin, gap — verify computed values, not just class names.
- Dimensions: width, height, border-radius.
- Take a screenshot for visual comparison against the Figma screenshot.
- If anything is off, fix it and re-verify. Do not proceed until the component matches.
在完成组件前,务必在浏览器中验证每个组件。
- 直接打开故事的iframe URL(例如),获取无Storybook界面的孤立组件。
http://localhost:6006/iframe.html?id=components-button--default - 检查渲染后的DOM——确认每个CSS属性与Figma规格匹配:
- 字体:字体系列、字重、字号、行高、字符间距。
- 颜色:前景色、背景色、边框、透明度。
- 间距:内边距、外边距、间隙——验证计算值,而非仅类名。
- 尺寸:宽度、高度、圆角。
- 截取截图,与Figma截图进行视觉对比。
- 若有任何不符,修复后重新验证。在组件匹配前请勿继续。
Phase 5: Testing
阶段5:测试
Only after browser verification confirms the component is correct:
- Write unit tests (React Testing Library) covering rendering, props, accessibility, visual styles.
- Update snapshots (flag).
--update - Add visual regression (screenshot) tests if the project uses them.
- Run tests and confirm all pass.
仅在浏览器验证确认组件正确后:
- 编写单元测试(React Testing Library),涵盖渲染、属性、可访问性、视觉样式。
- 更新快照(使用标志)。
--update - 若项目使用视觉回归(截图)测试,则添加此类测试。
- 运行测试并确认全部通过。
Phase 6: Commit
阶段6:提交
Only after all tests pass and browser verification is complete:
- Run .
pnpm lint && pnpm format - Commit with conventional commit message.
仅在所有测试通过且浏览器验证完成后:
- 运行。
pnpm lint && pnpm format - 使用约定式提交信息提交代码。
Decomposition
分解原则
Always build bottom-up: atomic components first, then compose.
- Identify the smallest, most reusable pieces (buttons, icons, badges, text styles).
- Build each atomic component through the full cycle (implementation → stories → browser verification → tests) independently.
- Only after each atomic component is verified and stable, compose them into molecules (card, list item, form field).
- Continue composing upward into organisms and full layouts.
Do NOT build top-down by creating a large component and extracting pieces later — this leads to tightly coupled, hard-to-test code.
始终自底向上构建:先构建原子组件,再进行组合。
- 识别最小、最可复用的组件(按钮、图标、徽章、文本样式)。
- 独立完成每个原子组件的完整流程(实现 → Storybook故事 → 浏览器验证 → 测试)。
- 仅在每个原子组件验证通过且稳定后,将它们组合成分子组件(卡片、列表项、表单字段)。
- 继续向上组合成组织级组件和完整布局。
请勿自顶向下构建——先创建大型组件再提取部分内容会导致代码耦合紧密、难以测试。
Separation of Concerns
关注点分离
For any component with non-trivial logic, split presentation from logic:
| Layer | Responsibility | Tests |
|---|---|---|
| Presentation | Visual rendering, styling, layout. Props are primitives and ReactNode. No data fetching, no side effects. | Storybook stories, snapshot tests, screenshot tests |
| Container | Data fetching, state management, event handling. Composes presentation components. | Unit tests for logic, integration tests for data flow |
Presentation components must render identically given the same props — no internal randomness, no time-dependent rendering.
This separation is NOT optional for complex components. It enables:
- Independent visual iteration in Storybook without mocking data layers.
- Logic testing without rendering overhead.
- Reuse of presentation across different data sources.
对于任何具有非平凡逻辑的组件,将展示层与逻辑层分离:
| 层级 | 职责 | 测试类型 |
|---|---|---|
| 展示层 | 视觉渲染、样式、布局。属性为基本类型和ReactNode。无数据获取、无副作用。 | Storybook故事、快照测试、截图测试 |
| 容器层 | 数据获取、状态管理、事件处理。组合展示层组件。 | 逻辑单元测试、数据流集成测试 |
给定相同属性时,展示层组件必须渲染出完全相同的结果——无内部随机性、无时间依赖渲染。
对于复杂组件,此分离是强制性要求。它带来以下好处:
- 在Storybook中独立进行视觉迭代,无需模拟数据层。
- 无需渲染开销即可测试逻辑。
- 展示层可在不同数据源间复用。
Anti-Patterns
反模式
- Do not commit snapshots/screenshots before browser verification — they lock in wrong output.
- Do not guess font or color values — always extract from Figma or inspect in browser.
- Do not add animation without guard — breaks screenshot tests and a11y.
useReducedMotion - Do not use non-deterministic random data in stories — breaks visual regression.
- Do not add empty wrapper divs — if a div has only one class for one child, the class belongs on the child.
- Do not use when you need zero layout impact — use
border,outline, or an overlay instead.box-shadow
- 在浏览器验证前请勿提交快照/截图——这会锁定错误输出。
- 请勿猜测字体或颜色值——始终从Figma提取或在浏览器中检查。
- 请勿在无防护的情况下添加动画——会破坏截图测试和可访问性。
useReducedMotion - 请勿在故事中使用非确定性随机数据——会破坏视觉回归测试。
- 请勿添加空包装div——若div仅为一个子元素设置一个类,该类应直接添加到子元素上。
- 当需要零布局影响时请勿使用——改用
border、outline或覆盖层。box-shadow