# Frontend Components — react-frontend-app ## Component Hierarchy ```mermaid graph TD root_route["__root.tsx\n(Root Route: ThemeProvider + QueryClientProvider)"] layout["RootLayout\n(Nav + Footer wrapper)"] index_route["index.tsx\n(/ Index Route)"] nav["Nav"] theme_toggle["ThemeToggle"] hero["Hero"] packages_section["PackagesSection"] package_card["PackageCard (x3)"] process_section["ProcessSection"] process_step["ProcessStep (x3)"] about_section["AboutSection"] contact_section["ContactSection"] footer["Footer"] root_route --> layout layout --> nav nav --> theme_toggle layout --> index_route index_route --> hero index_route --> packages_section packages_section --> package_card index_route --> process_section process_section --> process_step index_route --> about_section index_route --> contact_section layout --> footer classDef root_node fill:#4CAF50,stroke:#2e7d32,stroke-width:2px,color:#000; classDef layout_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000; classDef page_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000; classDef guard_node fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000; class root_route root_node; class layout,index_route layout_node; class nav,hero,packages_section,package_card,process_section,process_step,about_section,contact_section,footer page_node; class theme_toggle guard_node; ``` Text alternative: The root route provides ThemeProvider and QueryClientProvider and renders a RootLayout (Nav with ThemeToggle, plus Footer) wrapping the index route, which renders Hero, PackagesSection (three PackageCard instances), ProcessSection (three ProcessStep instances), AboutSection, and ContactSection. ## Components: Props and State | Component | Props | State | Notes | |---|---|---|---| | `RootRoute` (`__root.tsx`) | — | — | Hosts `ThemeProvider` and `QueryClientProvider`; renders `` | | `ThemeProvider` | `children: ReactNode` | `theme: 'red' \| 'purple'` (from context) | Reads/writes `localStorage`; exposes `theme` and `toggleTheme()` via context; applies `theme-red`/`theme-purple` class to `` | | `RootLayout` | `children: ReactNode` | — | Renders `Nav`, `children` (routed content), `Footer` | | `Nav` | `links: NavLink[]` | — | Renders logo, `nav-links`, `ThemeToggle`, CTA link | | `ThemeToggle` | — | — | Reads `theme`/`toggleTheme` from `ThemeProvider` context; `aria-label="Wissel kleurthema"`, `aria-pressed` reflects whether purple is active | | `Hero` | `content: HeroContent` | — | Renders eyebrow, heading, lead, animated code line (caret respects `prefers-reduced-motion`), two CTA buttons | | `PackagesSection` | `packages: PackageCard[]` | — | Renders section head + grid of `PackageCard` | | `PackageCard` | `pkg: PackageCard` | — | Renders one pricing card; `featured` prop styling for "Meest gekozen" | | `ProcessSection` | `steps: ProcessStep[]` | — | Renders section head + grid of `ProcessStep` | | `ProcessStep` | `step: ProcessStep` | — | Renders one process step (label, title, description) | | `AboutSection` | `content: AboutContent` | — | Renders paragraphs + tech-stack panel | | `ContactSection` | `content: ContactInfo` | — | Renders contact box with mailto CTA | | `Footer` | — | — | Renders copyright + mono tagline | ## User Interaction Flows - **Theme toggle click**: `ThemeToggle` → calls `toggleTheme()` from `ThemeProvider` context → context updates `theme` state → writes new value to `localStorage` (BR-2) → root element's theme class is updated → all themed elements re-render with new token values → transition is instant if `prefers-reduced-motion: reduce` (BR-5), otherwise a short color transition plays. - **In-page anchor navigation**: Clicking a `Nav` link or hero CTA scrolls smoothly to the target section (`scroll-behavior: smooth`), respecting `prefers-reduced-motion` (falls back to instant jump). - **Hover / focus-visible states**: Preserved 1-to-1 from the reference design on nav links, buttons, and cards (border/color changes on `:hover`/`:focus-visible`). - **Mailto CTA**: Clicking the contact CTA or the inline mail link opens the visitor's mail client via a `mailto:` link with a prefilled subject. ## Form Validation Rules None — this iteration has no forms; the only interactive control is the theme toggle and standard anchor/mailto links. ## API Integration Points (Forward-Looking) - `usePackagesQuery` (TanStack Query hook, placeholder): `queryFn` currently resolves the static `PackageCard[]` data from the content module wrapped in `Promise.resolve(...)`, consumed via `useQuery` in `PackagesSection`. This keeps the component's data-access pattern identical to what it will be once a real backend endpoint exists — only the `queryFn` implementation will need to change in a future iteration (per FR-5). - No other components call `useQuery` in this iteration; `Nav`, `Hero`, `ProcessSection`, `AboutSection`, and `ContactSection` read directly from the static content module for now.