5.0 KiB
5.0 KiB
Frontend Components — react-frontend-app
Component Hierarchy
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 <Outlet /> |
ThemeProvider |
children: ReactNode |
theme: 'red' | 'purple' (from context) |
Reads/writes localStorage; exposes theme and toggleTheme() via context; applies theme-red/theme-purple class to <html> |
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→ callstoggleTheme()fromThemeProvidercontext → context updatesthemestate → writes new value tolocalStorage(BR-2) → root element's theme class is updated → all themed elements re-render with new token values → transition is instant ifprefers-reduced-motion: reduce(BR-5), otherwise a short color transition plays. - In-page anchor navigation: Clicking a
Navlink or hero CTA scrolls smoothly to the target section (scroll-behavior: smooth), respectingprefers-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):queryFncurrently resolves the staticPackageCard[]data from the content module wrapped inPromise.resolve(...), consumed viauseQueryinPackagesSection. This keeps the component's data-access pattern identical to what it will be once a real backend endpoint exists — only thequeryFnimplementation will need to change in a future iteration (per FR-5).- No other components call
useQueryin this iteration;Nav,Hero,ProcessSection,AboutSection, andContactSectionread directly from the static content module for now.