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>
101 lines
2.2 KiB
Markdown
101 lines
2.2 KiB
Markdown
---
|
|
title: Avoid Boolean Prop Proliferation
|
|
impact: CRITICAL
|
|
impactDescription: prevents unmaintainable component variants
|
|
tags: composition, props, architecture
|
|
---
|
|
|
|
## Avoid Boolean Prop Proliferation
|
|
|
|
Don't add boolean props like `isThread`, `isEditing`, `isDMThread` to customize
|
|
component behavior. Each boolean doubles possible states and creates
|
|
unmaintainable conditional logic. Use composition instead.
|
|
|
|
**Incorrect (boolean props create exponential complexity):**
|
|
|
|
```tsx
|
|
function Composer({
|
|
onSubmit,
|
|
isThread,
|
|
channelId,
|
|
isDMThread,
|
|
dmId,
|
|
isEditing,
|
|
isForwarding,
|
|
}: Props) {
|
|
return (
|
|
<form>
|
|
<Header />
|
|
<Input />
|
|
{isDMThread ? (
|
|
<AlsoSendToDMField id={dmId} />
|
|
) : isThread ? (
|
|
<AlsoSendToChannelField id={channelId} />
|
|
) : null}
|
|
{isEditing ? (
|
|
<EditActions />
|
|
) : isForwarding ? (
|
|
<ForwardActions />
|
|
) : (
|
|
<DefaultActions />
|
|
)}
|
|
<Footer onSubmit={onSubmit} />
|
|
</form>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Correct (composition eliminates conditionals):**
|
|
|
|
```tsx
|
|
// Channel composer
|
|
function ChannelComposer() {
|
|
return (
|
|
<Composer.Frame>
|
|
<Composer.Header />
|
|
<Composer.Input />
|
|
<Composer.Footer>
|
|
<Composer.Attachments />
|
|
<Composer.Formatting />
|
|
<Composer.Emojis />
|
|
<Composer.Submit />
|
|
</Composer.Footer>
|
|
</Composer.Frame>
|
|
)
|
|
}
|
|
|
|
// Thread composer - adds "also send to channel" field
|
|
function ThreadComposer({ channelId }: { channelId: string }) {
|
|
return (
|
|
<Composer.Frame>
|
|
<Composer.Header />
|
|
<Composer.Input />
|
|
<AlsoSendToChannelField id={channelId} />
|
|
<Composer.Footer>
|
|
<Composer.Formatting />
|
|
<Composer.Emojis />
|
|
<Composer.Submit />
|
|
</Composer.Footer>
|
|
</Composer.Frame>
|
|
)
|
|
}
|
|
|
|
// Edit composer - different footer actions
|
|
function EditComposer() {
|
|
return (
|
|
<Composer.Frame>
|
|
<Composer.Input />
|
|
<Composer.Footer>
|
|
<Composer.Formatting />
|
|
<Composer.Emojis />
|
|
<Composer.CancelEdit />
|
|
<Composer.SaveEdit />
|
|
</Composer.Footer>
|
|
</Composer.Frame>
|
|
)
|
|
}
|
|
```
|
|
|
|
Each variant is explicit about what it renders. We can share internals without
|
|
sharing a single monolithic parent.
|