Skip to main content
skill Claude Code CX Codex Cursor

web-component-design — Claude Code skill: UI components

This skill helps design reusable components for React, Vue, and Svelte. Use it for UI libraries, design systems, or legacy component refactors.

Install into Claude Code · Plugin marketplace All methods and platforms ↓
/plugin marketplace add wshobson/agents
/plugin install ui-design@claude-code-workflows
Open on GitHub

What web-component-design does

web-component-design covers component composition, prop API design, and styling choices. It explains compound components, render props, and Vue or Svelte slots, then compares Tailwind CSS, CSS Modules, styled-components, Emotion, and Vanilla Extract.

The examples include a typed React Button using class-variance-authority and cn, a context-based React Accordion, a Vue 3 composable, and a Svelte 5 component built with runes. The material also addresses ARIA attributes, keyboard support, controlled and uncontrolled patterns, and forward refs.

Install it when you are shaping a component library or changing a UI API across a codebase. For a one-off component edit, this skill is probably more than you need.

What it helps with

  • design a reusable component API
  • build a compound component in React
  • choose a styling approach for a UI library
  • refactor legacy components into current patterns
  • share nested state through context or composables

Example prompts for the agent

  • Design a React Button API with size variants, loading state, and a forwarded ref.
  • Build an Accordion as a compound component with context and keyboard support.
  • Compare CSS Modules, styled-components, and Vanilla Extract for this component library.

How to install web-component-design

1Plugin marketplace

/plugin marketplace add wshobson/agents
/plugin install ui-design@claude-code-workflows

This installs the whole ui-design plugin with all its skills

2Skills CLI (Vercel)

npx skills add wshobson/agents --skill web-component-design -a claude-code

3Manually: put the files in place

~/.claude/skills/web-component-design/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/web-component-design/

From the same set213

The whole set →
typescript-advanced-types Seth Hobson Guides an agent through advanced TypeScript types, from generics to conditional and mapped types. Use it for typed libraries, API clients, or strict configuration objects. Claude Code CX Codex Cursor 92,169installs tailwind-design-system Seth Hobson Helps build design systems with Tailwind CSS v4, from theme tokens to component variants. Use it when a project needs shared UI patterns. Claude Code CX Codex Cursor 70,180installs brand-landingpage Travis D. Elliott This skill interviews you about the product and its visual direction, then builds a landing page through Stitch. Use it when there’s no established design yet. Claude Code CX Codex Cursor 39,476installs python-testing-patterns Seth Hobson This skill guides Python testing with pytest, fixtures and mocks. Use it when building a test suite or tracking down failing checks. Claude Code CX Codex Cursor 36,943installs python-performance-optimization Seth Hobson This skill profiles Python code to locate CPU and memory bottlenecks. Use it when an application responds slowly or consumes too many resources. Claude Code CX Codex Cursor 35,675installs nextjs-app-router-patterns Seth Hobson This skill covers Next.js App Router patterns for rendering, routing, and data fetching. Use it when starting an App Router project or moving from Pages Router. Claude Code CX Codex Cursor 32,529installs api-design-principles Seth Hobson Use this skill to plan or review REST and GraphQL APIs. It helps when writing a specification or setting API conventions for a team. Claude Code CX Codex Cursor 30,348installs code-review-excellence Seth Hobson This skill guides pull request reviews, catches logic and security issues, and helps teams give specific feedback. Use it for review standards or developer mentoring. Claude Code CX Codex Cursor 30,193installs

Similar

ima-sdk-client-side official Google LLC This skill supports Google IMA SDK integrations for client-side video and audio ads requested through VAST or VMAP. Use it for websites, apps, and TV platforms. Claude Code Gemini CLI CX Codex 4,500installs ima-dai-sdk official Google LLC This skill guides Google IMA DAI SDK integration for loading HLS and DASH streams. Use it for livestreams or video on demand in apps and websites. Claude Code Gemini CLI CX Codex 4,300installs premium-frontend-ui official Utkarsh Patrikar Guides GitHub Copilot when building animated web interfaces. Use it for a visually distinctive landing page or interactive portfolio. GitHub Copilot 4,900installs frontend-design official anthropics This skill guides intentional visual design for new interfaces and redesigns. Use it when a generic generated UI is not enough. Claude Code Claude.ai 1,025,790installs design-taste-frontend Leonxlnx This skill directs the design of public pages and work screens, then checks the result in a browser through screenshots. Use it when an interface feels generic or unfinished. Claude Code CX Codex Cursor +1 673,100installs prototype Matt Pocock Creates throwaway prototypes for checking state logic or exploring UI before committing the decision to the main codebase. Claude Code 986,201installs hyperframes heygen-com Instructs coding agents on creating, validating, and rendering HTML-based videos using the HyperFrames framework and CLI. Claude Code CX Codex Cursor +1 1,200,000installs hyperframes-cli heygen-com Controls HyperFrames video workflows from the CLI: audits layouts and contrast, edits timeline clips, captures snapshots, and renders locally or in cloud runtimes. Claude Code CX Codex Cursor +1 1,200,000installs

Questions about web-component-design

How do I install web-component-design in Claude Code?

Run npx skills add wshobson/agents --skill web-component-design -a claude-code. The skill file is placed at ~/.claude/skills/web-component-design/SKILL.md.

What does web-component-design do?

It guides reusable component work in React, Vue, and Svelte. The skill covers composition patterns, prop APIs, styling approaches, and refactoring.

Which frameworks and patterns does it cover?

The material covers React, Vue 3, and Svelte 5, along with compound components, render props, slots, context, and composables.

Source text

SKILL.md · MIT
---
name: web-component-design
description: Master React, Vue, and Svelte component patterns including CSS-in-JS, composition strategies, and reusable component architecture. Use when building UI component libraries, designing component APIs, or implementing frontend design systems.
---

# Web Component Design

Build reusable, maintainable UI components using modern frameworks with clean composition patterns and styling approaches.

## When to Use This Skill

- Designing reusable component libraries or design systems
- Implementing complex component composition patterns
- Choosing and applying CSS-in-JS solutions
- Building accessible, responsive UI components
- Creating consistent component APIs across a codebase
- Refactoring legacy components into modern patterns
- Implementing compound components or render props

## Core Concepts

### 1. Component Composition Patterns

**Compound Components**: Related components that work together

```tsx
// Usage
<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>
```

**Render Props**: Delegate rendering to parent

```tsx
<DataFetcher url="/api/users">
  {({ data, loading, error }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
</DataFetcher>
```

**Slots (Vue/Svelte)**: Named content injection points

```vue
<template>
  <Card>
    <template #header>Title</template>
    <template #content>Body text</template>
    <template #footer><Button>Action</Button></template>
  </Card>
</template>
```

### 2. CSS-in-JS Approaches

| Solution              | Approach               | Best For                          |
| --------------------- | ---------------------- | --------------------------------- |
| **Tailwind CSS**      | Utility classes        | Rapid prototyping, design systems |
| **CSS Modules**       | Scoped CSS files       | Existing CSS, gradual adoption    |
| **styled-components** | Template literals      | React, dynamic styling            |
| **Emotion**           | Object/template styles | Flexible, SSR-friendly            |
| **Vanilla Extract**   | Zero-runtime           | Performance-critical apps         |

### 3. Component API Design

```tsx
interface ButtonProps {
  variant?: "primary" | "secondary" | "ghost";
  size?: "sm" | "md" | "lg";
  isLoading?: boolean;
  isDisabled?: boolean;
  leftIcon?: React.ReactNode;
  rightIcon?: React.ReactNode;
  children: React.ReactNode;
  onClick?: () => void;
}
```

**Principles**:

- Use semantic prop names (`isLoading` vs `loading`)
- Provide sensible defaults
- Support composition via `children`
- Allow style overrides via `className` or `style`

## Quick Start: React Component with Tailwind

```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";
```

## Framework Patterns

### React: Compound Components

```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>
  );
};
```

### Vue 3: Composables

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

interface TabsContext {
  activeTab: Ref<string>;
  setActive: (id: string) => void;
}

const TabsKey: InjectionKey<TabsContext> = Symbol("tabs");

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

// Child component usage
const tabs = inject(TabsKey);
const isActive = computed(() => tabs?.activeTab.value === props.id);
</script>
```

### Svelte 5: Runes

```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>
```

## Best Practices

1. **Single Responsibility**: Each component does one thing well
2. **Prop Drilling Prevention**: Use context for deeply nested data
3. **Accessible by Default**: Include ARIA attributes, keyboard support
4. **Controlled vs Uncontrolled**: Support both patterns when appropriate
5. **Forward Refs**: Allow parent access to DOM nodes
6. **Memoization**: Use `React.memo`, `useMemo` for expensive renders
7. **Error Boundaries**: Wrap components that may fail

## Common Issues

- **Prop Explosion**: Too many props - consider composition instead
- **Style Conflicts**: Use scoped styles or CSS Modules
- **Re-render Cascades**: Profile with React DevTools, memo appropriately
- **Accessibility Gaps**: Test with screen readers and keyboard navigation
- **Bundle Size**: Tree-shake unused component variants

© Seth Hobson · MIT · wshobson/agents

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor