composition-patterns
Skill14 starsChanged 37 days agoMITView on GitHub
React composition patterns — refactor boolean-prop-heavy components into compound components, flexible APIs, and Context providers. Use for component architecture design and review.
7 other projects use a version of this, 5 of them edited.
Adopted by
Most recently taken up by
- eea/eea.agent.skillsedited, first seen Nov 8, 2026
- PracticalSwan/agent-skillstheir own version, first seen Oct 19, 2026
- Marvellbrazil/my-agentic-skillsedited, first seen Oct 17, 2026
- udsy19/.claudeedited, first seen Oct 5, 2026
- 10xequity/claude-skill-librarytheir own version, first seen Aug 2, 2026
- fegone/claude-agent-starteredited, first seen Jul 6, 2026
Other versions7 projects use a version of this.
Word for word · 0
None found.
Edited · 5
- eea/eea.agent.skills★ 711% same
- Marvellbrazil/my-agentic-skills★ 414% same
- sagnikmitra/skills★ 111% same
- fegone/claude-agent-starter★ 014% same
- udsy19/.claude★ 014% same
Wrote their own version · 2
- PracticalSwan/agent-skills★ 22same name
- 10xequity/claude-skill-library★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository44 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- adaptSkill
- animateSkill
- auditSkill
- bolderSkill
- brainstormSkill
- build-fixSkill
- business-panelSkill
- checkpointSkill
- clarifySkill
- colorizeSkill
- confidence-checkSkill
- config-doctorSkill
- critiqueSkill
- delightSkill
- design-auditSkill
- devils-advocateSkill
- distillSkill
- eval-harnessSkill
- feature-plannerSkill
- fix-prSkill
- frontend-designSkill
- gap-analysisSkill
- grill-with-docsSkill
- hardenSkill
- impeccableSkill
- layoutSkill
- learnSkill
- optimizeSkill
- overdriveSkill
- polishSkill
- pytest-runnerSkill
- python-best-practicesSkill
- quieterSkill
- react-best-practicesSkill
- sc-helpSkill
- security-auditSkill
- shapeSkill
- tddSkill
- typesetSkill
- ui-ux-pro-maxSkill
- uv-packageSkill
- verifySkill
- web-design-guidelinesSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 3 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 7 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Avoid boolean prop abuse, use compound components, state lifting, and composing internals.
- Distinctive: line 28
Do NOT use for: Performance optimization (→ react-best-practices), UI/UX inspection (→ web-design-guidelines)
- Distinctive: line 273
Create explicit variant components instead of boolean props.
- Very specific: line 289
Use children for composition instead of renderX props.
“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
React Composition Patterns
Composition patterns for flexible and maintainable React components. Avoid boolean prop abuse, use compound components, state lifting, and composing internals.
When to Use
Use proactively when:
- Refactoring components with many boolean props
- Building reusable component libraries
- Designing flexible component APIs
- Reviewing component architecture
- Working with compound components or Context providers
Triggers: composition, compound component, boolean props, component structure, architecture review, provider pattern, context, refactor component
Do NOT use for: Performance optimization (→ react-best-practices), UI/UX inspection (→ web-design-guidelines)
Rule Categories (by Priority)
| Priority | Category | Impact | Description |
| 1 | Component Architecture | HIGH | Component structuring |
| 2 | State Management | MEDIUM | State management patterns |
| 3 | Implementation Patterns | MEDIUM | Implementation patterns |
| 4 | React 19 APIs | MEDIUM | React 19 changes |
1. Component Architecture (HIGH)
1.1 Prevent Boolean Prop Abuse
Impact: CRITICAL
Boolean props lead to combinatorial explosion. Use composition instead.
// ❌ Boolean prop explosion - unmaintainable
function Composer({
isThread,
isDMThread,
isEditing,
isForwarding,
}: Props) {
return (
<form>
{isDMThread ? <DMField /> : isThread ? <ThreadField /> : null}
{isEditing ? <EditActions /> : isForwarding ? <ForwardActions /> : <DefaultActions />}
</form>
)
}
// ✅ Composition - explicit variants
function ThreadComposer({ channelId }: { channelId: string }) {
return (
<Composer.Frame>
<Composer.Input />
<AlsoSendToChannelField id={channelId} />
<Composer.Footer>
<Composer.Submit />
</Composer.Footer>
</Composer.Frame>
)
}
function EditComposer() {
return (
<Composer.Frame>
<Composer.Input />
<Composer.Footer>
<Composer.CancelEdit />
<Composer.SaveEdit />
</Composer.Footer>
</Composer.Frame>
)
}1.2 Use Compound Components
Impact: HIGH
Structure complex components into subcomponents connected by shared context.
// ❌ Monolithic + render props
function Composer({
renderHeader,
renderFooter,
showAttachments,
}: Props) {
return (
<form>
{renderHeader?.()}
<Input />
{showAttachments && <Attachments />}
{renderFooter?.()}
</form>
)
}
// ✅ Compound components + shared context
const ComposerContext = createContext<ComposerContextValue | null>(null)
function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
return (
<ComposerContext value={{ state, actions, meta }}>
{children}
</ComposerContext>
)
}
function ComposerInput() {
const { state, actions: { update } } = use(ComposerContext)
return <TextInput value={state.input} onChangeText={text => update(s => ({ ...s, input: text }))} />
}
// Export as compound component
const Composer = {
Provider: ComposerProvider,
Frame: ComposerFrame,
Input: ComposerInput,
Submit: ComposerSubmit,
Footer: ComposerFooter,
}
// Usage
<Composer.Provider state={state} actions={actions} meta={meta}>
<Composer.Frame>
<Composer.Input />
<Composer.Footer>
<Composer.Submit />
</Composer.Footer>
</Composer.Frame>
</Composer.Provider>2. State Management (MEDIUM)
2.1 Separate State Implementation from UI
Impact: MEDIUM
Provider knows state implementation, UI only uses context interface.
// ❌ UI coupled to state implementation
function ChannelComposer({ channelId }: { channelId: string }) {
const state = useGlobalChannelState(channelId) // Coupled to specific implementation
const { submit } = useChannelSync(channelId)
return <Composer.Input value={state.input} />
}
// ✅ State management separated in Provider
function ChannelProvider({ channelId, children }: Props) {
const { state, update, submit } = useGlobalChannel(channelId)
return (
<Composer.Provider state={state} actions={{ update, submit }}>
{children}
</Composer.Provider>
)
}
// UI only needs interface
function ChannelComposer() {
return (
<Composer.Frame>
<Composer.Input /> {/* Reads state from context */}
<Composer.Submit />
</Composer.Frame>
)
}2.2 Define Generic Context Interface
Impact: HIGH
Define generic interface with 3 parts: state, actions, meta.
// Generic interface - any provider can implement
interface ComposerContextValue {
state: {
input: string
attachments: Attachment[]
isSubmitting: boolean
}
actions: {
update: (updater: (state: State) => State) => void
submit: () => void
}
meta: {
inputRef: React.RefObject<TextInput>
}
}
// Provider A: Local state
function ForwardMessageProvider({ children }) {
const [state, setState] = useState(initialState)
return <ComposerContext value={{ state, actions: { update: setState, submit }, meta }}>{children}</ComposerContext>
}
// Provider B: Global synced state
function ChannelProvider({ channelId, children }) {
const { state, update, submit } = useGlobalChannel(channelId)
return <ComposerContext value={{ state, actions: { update, submit }, meta }}>{children}</ComposerContext>
}
// Same UI works with both providers!2.3 Lift State to Provider
Impact: HIGH
Lift state to Provider so sibling components can access it.
// ❌ State trapped inside component
function ForwardMessageDialog() {
return (
<Dialog>
<ForwardMessageComposer /> {/* state trapped here */}
<MessagePreview /> {/* Cannot access state! */}
<ForwardButton /> {/* Cannot call submit! */}
</Dialog>
)
}
// ✅ Lift state to Provider
function ForwardMessageDialog() {
return (
<ForwardMessageProvider>
<Dialog>
<ForwardMessageComposer />
<MessagePreview /> {/* Access state via context */}
<ForwardButton /> {/* Call submit via context */}
</Dialog>
</ForwardMessageProvider>
)
}
// Anywhere inside Provider can access state/actions
function ForwardButton() {
const { actions } = use(ComposerContext)
return <Button onPress={actions.submit}>Forward</Button>
}3. Implementation Patterns (MEDIUM)
3.1 Create Explicit Component Variants
Impact: MEDIUM
Create explicit variant components instead of boolean props.
// ❌ Unclear what UI renders
<Composer isThread isEditing={false} channelId="abc" showAttachments />
// ✅ Immediately clear
<ThreadComposer channelId="abc" />
<EditMessageComposer messageId="xyz" />
<ForwardMessageComposer messageId="123" />3.2 Prefer Children over Render Props
Impact: MEDIUM
Use children for composition instead of renderX props.
// ❌ Render props - hard to read
<Composer
renderHeader={() => <CustomHeader />}
renderFooter={() => <><Formatting /><Emojis /></>}
/>
// ✅ Children - natural composition
<Composer.Frame>
<CustomHeader />
<Composer.Input />
<Composer.Footer>
<Composer.Formatting />
<Composer.Emojis />
</Composer.Footer>
</Composer.Frame>When render props appropriate: Parent needs to pass data to children
<List data={items} renderItem={({ item, index }) => <Item item={item} />} />4. React 19 APIs (MEDIUM)
⚠️ React 19+ only. Skip this section for React 18 or below.
4.1 React 19 API Changes
// ❌ forwardRef (unnecessary in React 19)
const ComposerInput = forwardRef<TextInput, Props>((props, ref) => {
return <TextInput ref={ref} {...props} />
})
// ✅ ref as regular prop
function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) {
return <TextInput ref={ref} {...props} />
}
// ❌ useContext (React 19)
const value = useContext(MyContext)
// ✅ use() - conditional calls possible
const value = use(MyContext)Quick Checklist
| Check | Rule |
| [ ] | 3+ Boolean props? → Refactor to composition |
| [ ] | Complex conditional rendering? → Create explicit variants |
| [ ] | State trapped in component? → Lift to Provider |
| [ ] | renderX props? → Change to children |
| [ ] | React 19? → Remove forwardRef, use use() |
Related Skills
/react-best-practices- Performance optimization (waterfall, bundle, rendering)/web-design-guidelines- UI/UX quality (accessibility, interaction)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

