---
applyTo: "**/*.tsx"
description: React component conventions
---

# React + TypeScript components

- Function components with a local `type Props`; named exports; one component per file.
- Keep components presentational where possible; data fetching goes through the project's data layer (TanStack Query, loaders, or server components), not `useEffect` + `fetch`.
- Derive state during render. Effects only for syncing with external systems, always with a cleanup.
- Pass `ref` as a regular prop (React 19); don't write new `forwardRef` wrappers.
- Lists use stable `key`s from data ids.
- Event handler props are named `onX`, handlers inside are `handleX`.
- Accessibility: semantic elements, labelled inputs, `alt` on images, `aria-label` on icon-only buttons, no click handlers on `div`s.
- Styling follows the file's existing approach (Tailwind classes via `cn()`, CSS modules); don't mix systems in one component.
- Never use `any`; type events (`React.ChangeEvent<HTMLInputElement>`) and children (`React.ReactNode`).

## Tests
Testing Library with `userEvent`; query by role/label. One test file per component next to it (`Button.test.tsx`).
