Files
supabase/.github/instructions/studio-composition-patterns.instructions.md
Ali Waseem 3ece134d52 chore: updated copilot instructions (#44247)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Improve code review guidelines for copilot

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-27 05:26:47 -06:00

94 lines
2.5 KiB
Markdown

---
applyTo: "apps/studio/**"
---
# React Composition Patterns Review Rules
All comments are **advisory**.
## Core Principle
Avoid boolean prop proliferation. Use composition (compound components, explicit variants, children) instead of boolean flags to customize behavior.
## When to Flag
### 1. Boolean Prop Proliferation (HIGH)
Flag components accumulating boolean props like `isThread`, `isEditing`, `showAttachments`. Each boolean doubles the state space.
```tsx
// BAD — unclear intent, combinatorial explosion
<Composer isThread isDMThread isEditing isForwarding={false} />
// GOOD — self-documenting variants
<ThreadComposer channelId="abc" />
<EditMessageComposer messageId="xyz" />
```
### 2. Render Props Instead of Children (MEDIUM)
Flag `renderX` callback props when `children` composition would work.
```tsx
// BAD — render prop for structure
<Composer renderFooter={() => <F />} />
// GOOD — compound component
<Composer.Footer>
<Composer.Formatting />
<Composer.Emojis />
</Composer.Footer>
```
### 3. UI Coupled to State Implementation (MEDIUM)
Flag UI components calling specific state hooks like `useGlobalChannelState()` directly. The provider should own the state implementation; UI should only use a generic context interface.
```tsx
// BAD — UI knows HOW state is managed
const state = useGlobalChannelState(channelId)
// GOOD — provider owns implementation, UI uses context
<ChannelProvider channelId={channelId}>
<Composer /> {/* reads from context */}
</ChannelProvider>
```
### 4. State Trapped in Child Components (MEDIUM)
Flag state that siblings or dialogs need but can't access without prop drilling or refs. Lift it into a provider.
```tsx
// BAD — sibling can't access state
function ForwardComposer() {
const [state, setState] = useState(init)
}
// ForwardButton is a sibling and can't reach state
// GOOD — provider at shared ancestor
<ForwardMessageProvider>
<Composer /> {/* can access state */}
<ForwardButton /> {/* can also access state */}
</ForwardMessageProvider>
```
### 5. React 19 API Updates
Flag `forwardRef` and `useContext` in new code — use `ref` as a regular prop and `use()` instead.
```tsx
// BAD
const Input = forwardRef((props, ref) => <input ref={ref} />)
const value = useContext(MyContext)
// GOOD
function Input({ ref, ...props }) { return <input ref={ref} /> }
const value = use(MyContext)
```
## Key Principle
Lift state → Compose UI → Inject via generic context → No boolean prop proliferation.
Canonical standard: `.claude/skills/vercel-composition-patterns/SKILL.md`