Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
2.5 KiB
Markdown
113 lines
2.5 KiB
Markdown
---
|
|
title: Use Compound Components
|
|
impact: HIGH
|
|
impactDescription: enables flexible composition without prop drilling
|
|
tags: composition, compound-components, architecture
|
|
---
|
|
|
|
## Use Compound Components
|
|
|
|
Structure complex components as compound components with a shared context. Each
|
|
subcomponent accesses shared state via context, not props. Consumers compose the
|
|
pieces they need.
|
|
|
|
**Incorrect (monolithic component with render props):**
|
|
|
|
```tsx
|
|
function Composer({
|
|
renderHeader,
|
|
renderFooter,
|
|
renderActions,
|
|
showAttachments,
|
|
showFormatting,
|
|
showEmojis,
|
|
}: Props) {
|
|
return (
|
|
<form>
|
|
{renderHeader?.()}
|
|
<Input />
|
|
{showAttachments && <Attachments />}
|
|
{renderFooter ? (
|
|
renderFooter()
|
|
) : (
|
|
<Footer>
|
|
{showFormatting && <Formatting />}
|
|
{showEmojis && <Emojis />}
|
|
{renderActions?.()}
|
|
</Footer>
|
|
)}
|
|
</form>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Correct (compound components with shared context):**
|
|
|
|
```tsx
|
|
const ComposerContext = createContext<ComposerContextValue | null>(null)
|
|
|
|
function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
|
|
return (
|
|
<ComposerContext value={{ state, actions, meta }}>
|
|
{children}
|
|
</ComposerContext>
|
|
)
|
|
}
|
|
|
|
function ComposerFrame({ children }: { children: React.ReactNode }) {
|
|
return <form>{children}</form>
|
|
}
|
|
|
|
function ComposerInput() {
|
|
const {
|
|
state,
|
|
actions: { update },
|
|
meta: { inputRef },
|
|
} = use(ComposerContext)
|
|
return (
|
|
<TextInput
|
|
ref={inputRef}
|
|
value={state.input}
|
|
onChangeText={(text) => update((s) => ({ ...s, input: text }))}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function ComposerSubmit() {
|
|
const {
|
|
actions: { submit },
|
|
} = use(ComposerContext)
|
|
return <Button onPress={submit}>Send</Button>
|
|
}
|
|
|
|
// Export as compound component
|
|
const Composer = {
|
|
Provider: ComposerProvider,
|
|
Frame: ComposerFrame,
|
|
Input: ComposerInput,
|
|
Submit: ComposerSubmit,
|
|
Header: ComposerHeader,
|
|
Footer: ComposerFooter,
|
|
Attachments: ComposerAttachments,
|
|
Formatting: ComposerFormatting,
|
|
Emojis: ComposerEmojis,
|
|
}
|
|
```
|
|
|
|
**Usage:**
|
|
|
|
```tsx
|
|
<Composer.Provider state={state} actions={actions} meta={meta}>
|
|
<Composer.Frame>
|
|
<Composer.Header />
|
|
<Composer.Input />
|
|
<Composer.Footer>
|
|
<Composer.Formatting />
|
|
<Composer.Submit />
|
|
</Composer.Footer>
|
|
</Composer.Frame>
|
|
</Composer.Provider>
|
|
```
|
|
|
|
Consumers explicitly compose exactly what they need. No hidden conditionals. And the state, actions and meta are dependency-injected by a parent provider, allowing multiple usages of the same component structure.
|