React
Convenções de componente React 18 — estrutura de pasta, export, props tipadas — independente da biblioteca de estilo (SCSS Modules ou Tailwind). Invoque ao criar ou revisar qualquer componente React.
React
Convenções de componente que valem qualquer que seja a lib de estilo. Estilização em si mora em
frontend/scss-bem ou frontend/tailwind, conforme o archetype do projeto.
Referência
| Arquivo | Conteúdo |
|---|---|
| reference/components.md | Estrutura de componente, export, props tipadas |
| reference/folder-structure.md | Estrutura de src/, regra de colocação e promoção |
Regras inegociáveis
- Export nomeado, não
default, para componentes não-page. Páginas roteadas (src/pages/) podem seguirexport default, que é o que roteadores com lazy-loading esperam. - Props tipadas com
interface, nuncatypeinline anônimo. - Sem inline styles (
style={{}}) — a classe/token vem da lib de estilo do projeto. Exceção: valor verdadeiramente dinâmico que não dá pra expressar em classe (ex. progresso calculado). - Componente sobe para
src/components/só quando há 2+ usos reais. - Componente
.tsxé só estrutura — tipo de dado externo (form, resposta de API, params de URL) vem de um schema zod (frontend/react-hook-form-zod), nuncainterface/typesolto no.tsx.
Skills relacionadas
- Tipagem:
frontend/typescript - Build tool, aliases, env vars:
frontend/vite - Estilo:
frontend/scss-bemoufrontend/tailwind - Componentes gerados via CLI (shadcn/ui):
frontend/shadcn-ui - Forms:
frontend/react-hook-form-zod - Testes:
frontend/vitest-testing-library,frontend/playwright-e2e
Documentos de referência
Componentes
fonte ↗Componentes
Referência de frontend/react. Volte ao índice para o quando-invocar.
- Uma pasta por componente (
.tsx+ arquivo de estilo do projeto +.test.tsx) quando o componente tem estilo próprio em arquivo separado (frontend/scss-bem); um arquivo solto quando o estilo é só classe utilitária (frontend/tailwind— ver aquela skill). - Export nomeado, não
default, para componentes não-page. - Props tipadas com
interface, nunca comtypeinline anônimo. - Nunca use inline styles (
style={{}}).
// Button/Button.tsx
interface ButtonProps {
label: string;
variant?: 'primary' | 'secondary';
onClick: () => void;
}
export function Button({ label, variant = 'primary', onClick }: ButtonProps) {
return (
<button className={/* classe vem da lib de estilo do projeto — ver frontend/scss-bem ou frontend/tailwind */ ''} onClick={onClick}>
{label}
</button>
);
}
O arquivo de estilo em si (.module.scss + BEM, ou classes utilitárias Tailwind) segue a convenção
do skill de estilo do archetype — frontend/scss-bem ou frontend/tailwind.
Export: se o código existente do projeto for inconsistente (mistura export const Foo = ... e
export default Foo), prefira export nomeado para componentes novos que não são página/rota — é
mais fácil de refatorar e evita o erro comum de importar { Foo } de um arquivo que só tem
export default.
Estrutura de pastas
fonte ↗Estrutura de pastas
Referência de frontend/react. Volte ao índice para o quando-invocar.
src/
├── assets/ # imagens e fontes estáticas
├── components/ # componentes usados em 2+ lugares
│ └── Button/
├── pages/ # uma pasta por rota / view
│ └── Dashboard/
├── forms/ (ou junto da page) # um form = .tsx (estrutura) + .schema.ts (tipo + validação)
│ └── LoginForm/
├── hooks/ # hooks reutilizados em 2+ lugares
├── lib/ # funções utilitárias e acesso a API
│ └── __tests__/
├── schemas/ # schemas zod usados em 2+ lugares
└── types/
└── index.ts
O arquivo/pasta de estilo global (styles/ ou index.css) segue a convenção do skill de estilo do
projeto (frontend/scss-bem ou frontend/tailwind) — não é parte deste layout genérico.
Regra de colocação
| Asset | 1 lugar | 2+ lugares |
|---|---|---|
| Componente | dentro da própria pasta de página | src/components/ |
| Schema zod (+ tipo de dado externo) | <Form>.schema.ts junto do form (nunca inline no .tsx, mesmo com um único form — ver frontend/react-hook-form-zod) |
src/schemas/ |
| Mock de teste | mesma pasta do teste | src/mocks/ |
| Tipo (não derivado de schema) | mesmo arquivo ou types.ts local |
src/types/index.ts |
| Função utilitária | inline ou utils.ts local |
src/lib/ |
Não crie pasta compartilhada preventivamente — promova quando o reuso acontecer de verdade.
Regra de promoção de schema zod
Assim que um schema zod passa a ser usado em 2+ lugares, ele vira global — nunca duplicado/copiado-colado entre arquivos (isso é o mesmo valor de validação virando hardcoded em dois lugares que podem divergir):
- Schema de formulário (RHF) reutilizado por 2+ forms →
src/schemas/(verfrontend/react-hook-form-zod). - Schema de validação de resposta de API (não ligado a um form — ex.:
UserSchema.parse(raw)defrontend/typescript) reutilizado por 2+ chamadas →src/lib/, junto do client/função que faz a chamada.
Em ambos os casos, o arquivo original passa a importar do destino global — nunca mantenha as duas cópias.