diff --git a/docs/architecture/website/REACT_COMPONENT_ARCHITECTURE.md b/docs/architecture/website/REACT_COMPONENT_ARCHITECTURE.md index 50019b4fb..f29b1da75 100644 --- a/docs/architecture/website/REACT_COMPONENT_ARCHITECTURE.md +++ b/docs/architecture/website/REACT_COMPONENT_ARCHITECTURE.md @@ -110,27 +110,35 @@ export function TeamsTemplate({ teams, searchQuery, onSearchChange, onTeamClick - Can use Next.js hooks (but not Next.js components like `Link`) - Should be reusable within the app context - **Strictly Forbidden**: Generic UI primitives (`Box`, `Surface`) and generic wrappers (`Layout`, `Container`) -- **Strictly Forbidden**: The `className` prop (styling must be handled by UI components) +- **Strictly Forbidden**: Raw HTML tags (use `ui/` components instead) +- **Strictly Forbidden**: The `className` or `style` props +- **Strictly Forbidden**: Passing implementation details (Tailwind classes, CSS values) as props to UI components **Example**: ```typescript // components/teams/TeamLeaderboardPreview.tsx 'use client'; +import { Card, CardHeader, TeamRow } from '@/ui'; + export function TeamLeaderboardPreview({ teams, onTeamClick }: Props) { // App-specific logic: medal colors, ranking, etc. - const getMedalColor = (position: number) => { /* ... */ }; + const getMedalColor = (position: number) => { + if (position === 0) return 'gold'; + if (position === 1) return 'silver'; + return 'none'; + }; return ( - - Top Teams + + {teams.map((team, index) => ( onTeamClick(team.id)} - medalColor={getMedalColor(index)} + achievement={getMedalColor(index)} /> ))} @@ -153,14 +161,22 @@ export function TeamLeaderboardPreview({ teams, onTeamClick }: Props) { - Only receive props and render - Maximum reusability - **Strict Layering**: Generic primitives (`Box`, `Surface`, `Stack`, `Grid`) are internal to this layer. +- **Encapsulation**: Must NOT expose `className`, `style`, or Tailwind-specific props to consumers. +- **Semantic APIs**: Use semantic props (e.g., `variant="primary"`, `size="large"`) instead of implementation details. **Example**: ```typescript // ui/Button.tsx -export function Button({ children, variant, onClick }: ButtonProps) { +// GOOD: Semantic API +export function Button({ children, variant = 'primary', onClick }: ButtonProps) { + const classes = { + primary: 'bg-blue-600 text-white hover:bg-blue-700', + secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300', + }[variant]; + return (