React Composition
Purpose
Apply the "Composition Is All You Need" pattern: replace shallow, prop-configured React modules with deeper component families whose interface is small, explicit, and composable.
Core rule:
Lift shared state, compose internals.
Vocabulary to use
- Module — component, hook, provider, compound component family, or utility with an interface and implementation.
- Interface — props, children shape, context contract, valid combinations, ordering, side effects, error modes.
- Implementation — rendering, state management, effects, data sync, and styling behind the interface.
- Depth — leverage behind a small interface.
- Seam — where behavior can vary without editing in place; often a provider, context contract, child component, or JSX composition point.
- Adapter — concrete provider/hook/state source satisfying the same interface.
- Leverage — reusable internals, fewer invalid prop combinations, flexible layout.
- Locality — variant behavior lives where the variant is rendered.
Trigger signals
Load this skill when you see:
- Boolean mode props:
isEditing, isThread, isForwarding, hideFooter, renderTerms, onlyEditName.
- One parent deciding which component tree children render.
- Repeated conditions spread through the same component.
- UI config arrays gaining exceptions:
divider, isMenu, render, variant, hiddenWhen.
- Render props used mainly to escape an over-controlling parent.
- Prop drilling of form state, refs, submit handlers, focus handlers, or mutation behavior.
- Several related UI variants sharing structure but requiring different internal pieces.
Diagnostic tests
- Boolean tree test — if a prop determines which component tree renders from the parent, prefer composition.
- Deletion test — if deleting the abstraction makes complexity vanish, it was shallow; if complexity spreads across callers, it was earning its keep.
- Interface test surface — test the public component family interface, not extracted helper trivia.
- Adapter reality check — one provider/state implementation is a hypothetical seam; two implementations make the seam real.
Preferred shape
<Composer.Provider value={composerState}>
<Composer.Dropzone />
<Composer.Frame>
<Composer.Header />
<Composer.Input />
<Composer.Footer>
<Composer.CommonActions />
<Composer.Submit />
</Composer.Footer>
</Composer.Frame>
</Composer.Provider>
Variant-specific features become rendered components, not flags:
<Composer.Provider value={threadComposerState}>
<Composer.Frame>
<Composer.Header />
<Composer.AlsoSendToChannel />
<Composer.Input />
<Composer.Footer>
<Composer.CommonActions />
<Composer.Submit />
</Composer.Footer>
</Composer.Frame>
</Composer.Provider>
Workflow
- Map real variants and what differs: state source, layout, actions, validation, submit behavior, persistence.
- Name shared internals:
Provider, Frame, Header, Input, Footer, CommonActions, Submit, domain-specific toggles.
- Define a context interface containing only what children need.
- Create adapters: each variant provider translates its state source into the same interface.
- Compose call sites with exact JSX. Prefer omission over
showX={false}.
- Abstract only after repetition; keep escape hatches to individual parts.
- Test representative composed variants and provider adapters through the public interface.
Output format
When advising, return: current interface problem, proposed seam, composed JSX shape, adapter plan, tests, and migration path.
See REFERENCE.md for examples, decision guide, naming, testing, and migration details.
1---2name: react-composition3description: React Composition4---56# React Composition78## Purpose910Apply the "Composition Is All You Need" pattern: replace shallow, prop-configured React modules with deeper component families whose interface is small, explicit, and composable.1112Core rule:1314> Lift shared state, compose internals.1516## Vocabulary to use1718- **Module** — component, hook, provider, compound component family, or utility with an interface and implementation.19- **Interface** — props, children shape, context contract, valid combinations, ordering, side effects, error modes.20- **Implementation** — rendering, state management, effects, data sync, and styling behind the interface.21- **Depth** — leverage behind a small interface.22- **Seam** — where behavior can vary without editing in place; often a provider, context contract, child component, or JSX composition point.23- **Adapter** — concrete provider/hook/state source satisfying the same interface.24- **Leverage** — reusable internals, fewer invalid prop combinations, flexible layout.25- **Locality** — variant behavior lives where the variant is rendered.2627## Trigger signals2829Load this skill when you see:3031- Boolean mode props: `isEditing`, `isThread`, `isForwarding`, `hideFooter`, `renderTerms`, `onlyEditName`.32- One parent deciding which component tree children render.33- Repeated conditions spread through the same component.34- UI config arrays gaining exceptions: `divider`, `isMenu`, `render`, `variant`, `hiddenWhen`.35- Render props used mainly to escape an over-controlling parent.36- Prop drilling of form state, refs, submit handlers, focus handlers, or mutation behavior.37- Several related UI variants sharing structure but requiring different internal pieces.3839## Diagnostic tests4041- **Boolean tree test** — if a prop determines which component tree renders from the parent, prefer composition.42- **Deletion test** — if deleting the abstraction makes complexity vanish, it was shallow; if complexity spreads across callers, it was earning its keep.43- **Interface test surface** — test the public component family interface, not extracted helper trivia.44- **Adapter reality check** — one provider/state implementation is a hypothetical seam; two implementations make the seam real.4546## Preferred shape4748```tsx49<Composer.Provider value={composerState}>50 <Composer.Dropzone />51 <Composer.Frame>52 <Composer.Header />53 <Composer.Input />54 <Composer.Footer>55 <Composer.CommonActions />56 <Composer.Submit />57 </Composer.Footer>58 </Composer.Frame>59</Composer.Provider>60```6162Variant-specific features become rendered components, not flags:6364```tsx65<Composer.Provider value={threadComposerState}>66 <Composer.Frame>67 <Composer.Header />68 <Composer.AlsoSendToChannel />69 <Composer.Input />70 <Composer.Footer>71 <Composer.CommonActions />72 <Composer.Submit />73 </Composer.Footer>74 </Composer.Frame>75</Composer.Provider>76```7778## Workflow79801. Map real variants and what differs: state source, layout, actions, validation, submit behavior, persistence.812. Name shared internals: `Provider`, `Frame`, `Header`, `Input`, `Footer`, `CommonActions`, `Submit`, domain-specific toggles.823. Define a context interface containing only what children need.834. Create adapters: each variant provider translates its state source into the same interface.845. Compose call sites with exact JSX. Prefer omission over `showX={false}`.856. Abstract only after repetition; keep escape hatches to individual parts.867. Test representative composed variants and provider adapters through the public interface.8788## Output format8990When advising, return: current interface problem, proposed seam, composed JSX shape, adapter plan, tests, and migration path.9192See [REFERENCE.md](REFERENCE.md) for examples, decision guide, naming, testing, and migration details.