Agent skill
component-composition
Component composition patterns with nesting, slots, compound components, and render props. Use when creating reusable components, component APIs, or complex component hierarchies.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/component-composition
SKILL.md
Component Composition
Advanced composition patterns for scalable components.
Agent Workflow (MANDATORY)
Before implementation:
- fuse-ai-pilot:explore-codebase - Check existing composition patterns
- fuse-ai-pilot:research-expert - React 19 composition patterns
After: Run fuse-ai-pilot:sniper for validation.
Pattern Overview
| Pattern | Use Case | Complexity |
|---|---|---|
| Children | Simple containers | Low |
| Slots | Named regions | Medium |
| Compound | Related sub-components | Medium |
| Render Props | Custom rendering | High |
| Context | Shared state | High |
1. Children Pattern (Basic)
function Card({ children, className }: { children: React.ReactNode }) {
return (
<div className={cn("bg-surface rounded-2xl p-6", className)}>
{children}
</div>
);
}
// Usage
<Card>
<h2>Title</h2>
<p>Content</p>
</Card>
2. Slots Pattern
interface CardProps {
header?: React.ReactNode;
footer?: React.ReactNode;
children: React.ReactNode;
}
function Card({ header, footer, children }: CardProps) {
return (
<div className="bg-surface rounded-2xl overflow-hidden">
{header && (
<div className="px-6 py-4 border-b border-border">
{header}
</div>
)}
<div className="p-6">{children}</div>
{footer && (
<div className="px-6 py-4 border-t border-border bg-muted/50">
{footer}
</div>
)}
</div>
);
}
// Usage
<Card
header={<h2>Settings</h2>}
footer={<Button>Save</Button>}
>
<p>Card content here</p>
</Card>
3. Compound Components
const CardContext = createContext<{ variant: string }>({ variant: "default" });
function Card({ children, variant = "default" }) {
return (
<CardContext.Provider value={{ variant }}>
<div className="bg-surface rounded-2xl">{children}</div>
</CardContext.Provider>
);
}
Card.Header = function CardHeader({ children }) {
return <div className="px-6 py-4 border-b">{children}</div>;
};
Card.Body = function CardBody({ children }) {
return <div className="p-6">{children}</div>;
};
Card.Footer = function CardFooter({ children }) {
const { variant } = useContext(CardContext);
return (
<div className={cn("px-6 py-4", variant === "glass" && "bg-white/5")}>
{children}
</div>
);
};
// Usage
<Card variant="glass">
<Card.Header>
<h2>Title</h2>
</Card.Header>
<Card.Body>
<p>Content</p>
</Card.Body>
<Card.Footer>
<Button>Action</Button>
</Card.Footer>
</Card>
4. Render Props
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
renderEmpty?: () => React.ReactNode;
}
function List<T>({ items, renderItem, renderEmpty }: ListProps<T>) {
if (items.length === 0) {
return renderEmpty?.() ?? <p>No items</p>;
}
return (
<ul className="space-y-2">
{items.map((item, i) => (
<li key={i}>{renderItem(item, i)}</li>
))}
</ul>
);
}
// Usage
<List
items={users}
renderItem={(user) => <UserCard user={user} />}
renderEmpty={() => <EmptyState message="No users found" />}
/>
5. As Prop (Polymorphic)
type ButtonProps<T extends React.ElementType> = {
as?: T;
children: React.ReactNode;
} & React.ComponentPropsWithoutRef<T>;
function Button<T extends React.ElementType = "button">({
as,
children,
...props
}: ButtonProps<T>) {
const Component = as || "button";
return (
<Component
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg"
{...props}
>
{children}
</Component>
);
}
// Usage
<Button>Click me</Button>
<Button as="a" href="/link">Link button</Button>
<Button as={Link} to="/route">Router link</Button>
6. Forwarded Refs
const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
return (
<input
ref={ref}
className="w-full px-4 py-2 rounded-lg border"
{...props}
/>
);
});
Input.displayName = "Input";
// Usage with ref
const inputRef = useRef<HTMLInputElement>(null);
<Input ref={inputRef} />
Composition Guidelines
| DO | DON'T |
|---|---|
| Use children for simple nesting | Over-engineer simple components |
| Use slots for named regions | Use too many slots (max 3-4) |
| Use compound for related parts | Create deep nesting (max 2 levels) |
| Forward refs for form elements | Forget displayName |
Validation
[ ] Appropriate pattern for complexity
[ ] TypeScript props properly typed
[ ] displayName set on forwardRef
[ ] Context used sparingly
[ ] Max 2-3 composition levels
[ ] Documented API in JSDoc
References
../../references/design-patterns.md- Component patterns../../references/component-examples.md- Production examples
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?