Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Web Component Design

ASecurity

当构建 React/Vue/Svelte 组件库、设计组件 API 或落地前端设计系统时使用;做组合模式选型、CSS-in-JS 方案选择与可复用组件 API 的设计落地;不适用于纯样式微调、单页面一次性 UI 或后端逻辑;触发词:组件库、设计系统、复合组件、组件 API、CSS-in-JS

3 stars
0 votes
0 copies
2 views
Added 9/19/2026
ai-agentsreactvuenodeapifrontend

Works with

cursorcliapi

Security Analysis

A100/100

Scanned 9/19/2026

$npx -y skills add findscripter/everything-skills --skill web-component-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Web Component Design?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Web Component Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/findscripter-web-component-design/badge)](https://www.skillsdirectory.com/skills/findscripter-web-component-design)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: web-component-design
title: Web 组件设计模式
description: 当构建 React/Vue/Svelte 组件库、设计组件 API 或落地前端设计系统时使用;做组合模式选型、CSS-in-JS 方案选择与可复用组件 API 的设计落地;不适用于纯样式微调、单页面一次性 UI 或后端逻辑;触发词:组件库、设计系统、复合组件、组件 API、CSS-in-JS
domain: 研发/frontend
triggers: [组件库, 设计系统, 复合组件, render props, 组件 API 设计, CSS-in-JS, Tailwind, styled-components, 可复用组件, Vue 插槽, Svelte runes, forwardRef]
tags: [前端, 组件设计, 设计系统, react, vue, svelte, css-in-js, ui]
level: 进阶
status: stable
agents: [claude-code, codex, cursor, gemini-cli]
tools: [React, Vue 3, Svelte 5, Tailwind CSS, class-variance-authority, styled-components, Emotion, CSS Modules, Vanilla Extract]
requires: []
related: []
combines_with: []
license: MIT
source: wshobson/agents
source_license: MIT
---
采用现代框架,用清晰的组合模式与样式方案,构建可复用、易维护的 UI 组件。

## 何时使用

适用:
- 设计可复用组件库或设计系统
- 实现复杂的组件组合模式(复合组件 / render props / 插槽)
- 选型并落地 CSS-in-JS 方案
- 构建无障碍、响应式的 UI 组件
- 在整个代码库中统一组件 API 约定
- 将遗留组件重构为现代模式

不该用(负边界):
- 仅做单个页面的一次性 UI 或局部样式微调,不涉及复用
- 纯视觉/CSS 调整且无组件抽象需求
- 后端业务逻辑或数据层问题

## 步骤

1. 明确复用边界:判断是「一次性 UI」还是「需沉淀到组件库」,只有后者才走本流程。
2. 选组合模式:
   - 复合组件(Compound Components):一组协同工作的关联组件,通过 Context 共享状态。
   - Render Props:把渲染权委托给父级。
   - 插槽 Slots(Vue/Svelte):具名内容注入点。
3. 选样式方案(见下表),与团队既有技术栈对齐。
4. 设计组件 API:语义化 prop 名、合理默认值、用 `children` 支持组合、用 `className`/`style` 允许样式覆盖。
5. 补齐无障碍与质量:ARIA 属性、键盘支持、forwardRef、必要的 memo。
6. 重构既有组件时,先识别 prop 爆炸/重渲染级联等坏味道再下手。

### CSS-in-JS 方案选型

| 方案 | 思路 | 最适合 |
| --- | --- | --- |
| Tailwind CSS | 原子类 | 快速原型、设计系统 |
| CSS Modules | 局部作用域 CSS 文件 | 既有 CSS、渐进采用 |
| styled-components | 模板字符串 | React、动态样式 |
| Emotion | 对象/模板样式 | 灵活、SSR 友好 |
| Vanilla Extract | 零运行时 | 性能敏感型应用 |

## 指令

组件 API 设计原则:
- 用语义化 prop 名(`isLoading` 优于 `loading`)。
- 提供合理默认值(defaultVariants)。
- 通过 `children` 支持组合,避免大量配置型 prop。
- 通过 `className` / `style` 允许样式覆盖。

最佳实践:
1. 单一职责:每个组件把一件事做好。
2. 防止 prop 钻取:深层嵌套数据用 Context 传递。
3. 默认无障碍:内置 ARIA 属性与键盘支持。
4. 受控 vs 非受控:在合适场景同时支持两种模式。
5. 转发 ref:用 `forwardRef` 让父级访问 DOM 节点。
6. 记忆化:对昂贵渲染用 `React.memo` / `useMemo`。
7. 错误边界:包裹可能失败的组件。

## 示例

React + Tailwind 按钮(用 cva 管理变体 + forwardRef):

```tsx
import { forwardRef, type ComponentPropsWithoutRef } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        primary: "bg-blue-600 text-white hover:bg-blue-700",
        secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
        ghost: "hover:bg-gray-100 hover:text-gray-900",
      },
      size: {
        sm: "h-8 px-3 text-sm",
        md: "h-10 px-4 text-sm",
        lg: "h-12 px-6 text-base",
      },
    },
    defaultVariants: { variant: "primary", size: "md" },
  },
);

interface ButtonProps
  extends ComponentPropsWithoutRef<"button">,
    VariantProps<typeof buttonVariants> {
  isLoading?: boolean;
}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, isLoading, children, ...props }, ref) => (
    <button
      ref={ref}
      className={cn(buttonVariants({ variant, size }), className)}
      disabled={isLoading || props.disabled}
      {...props}
    >
      {isLoading && <Spinner className="mr-2 h-4 w-4" />}
      {children}
    </button>
  ),
);
Button.displayName = "Button";
```

React 复合组件(Context 驱动的 Accordion):

```tsx
import { createContext, useContext, useState, type ReactNode } from "react";

interface AccordionContextValue {
  openItems: Set<string>;
  toggle: (id: string) => void;
}

const AccordionContext = createContext<AccordionContextValue | null>(null);

function useAccordion() {
  const context = useContext(AccordionContext);
  if (!context) throw new Error("Must be used within Accordion");
  return context;
}

export function Accordion({ children }: { children: ReactNode }) {
  const [openItems, setOpenItems] = useState<Set<string>>(new Set());
  const toggle = (id: string) => {
    setOpenItems((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };
  return (
    <AccordionContext.Provider value={{ openItems, toggle }}>
      <div className="divide-y">{children}</div>
    </AccordionContext.Provider>
  );
}

Accordion.Item = function AccordionItem({
  id, title, children,
}: { id: string; title: string; children: ReactNode }) {
  const { openItems, toggle } = useAccordion();
  const isOpen = openItems.has(id);
  return (
    <div>
      <button onClick={() => toggle(id)} className="w-full text-left py-3">
        {title}
      </button>
      {isOpen && <div className="pb-3">{children}</div>}
    </div>
  );
};
```

复合组件的使用形态:

```tsx
<Select value={value} onChange={setValue}>
  <Select.Trigger>Choose option</Select.Trigger>
  <Select.Options>
    <Select.Option value="a">Option A</Select.Option>
    <Select.Option value="b">Option B</Select.Option>
  </Select.Options>
</Select>
```

Vue 3 用 provide/inject 实现 Tabs 上下文:

```vue
<script setup lang="ts">
import { ref, computed, provide, inject, type InjectionKey, type Ref } from "vue";

interface TabsContext {
  activeTab: Ref<string>;
  setActive: (id: string) => void;
}
const TabsKey: InjectionKey<TabsContext> = Symbol("tabs");

// 父组件
const activeTab = ref("tab-1");
provide(TabsKey, {
  activeTab,
  setActive: (id: string) => { activeTab.value = id; },
});

// 子组件使用
const tabs = inject(TabsKey);
const isActive = computed(() => tabs?.activeTab.value === props.id);
</script>
```

Svelte 5 用 runes(`$props` / `$derived`)写按钮:

```svelte
<script lang="ts">
  interface Props {
    variant?: 'primary' | 'secondary';
    size?: 'sm' | 'md' | 'lg';
    onclick?: () => void;
    children: import('svelte').Snippet;
  }
  let { variant = 'primary', size = 'md', onclick, children }: Props = $props();
  const classes = $derived(`btn btn-${variant} btn-${size}`);
</script>

<button class={classes} {onclick}>
  {@render children()}
</button>
```

## 注意事项

常见坑:
- Prop 爆炸:prop 太多时改用组合而非配置。
- 样式冲突:用局部作用域样式或 CSS Modules 隔离。
- 重渲染级联:用 React DevTools 定位,恰当地 memo。
- 无障碍缺口:用屏幕阅读器与键盘导航实测。
- 包体积:对未使用的组件变体做 tree-shaking。

## 互见

- 设计系统 token 与主题方案
- 前端无障碍(a11y)与 ARIA 实践
- 前端性能优化与渲染分析

---

采编自 wshobson/agents(MIT 许可)。

Attribution

findscripterfindscripter
View sourceSee grades on GitHubMore from findscripter →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →