Files
triqura-ecd/docs/styleguide-ux.md
2026-07-09 23:16:28 +02:00

13 KiB

Mini-EPD Style Guide & UX

Geëxtraheerd uit de mini-epd-prototype codebase. Gebruik dit document om dezelfde look & feel in een ander project toe te passen.


1. Tech Stack & Tooling

Categorie Keuze Versie
Framework Next.js (App Router) 14.2
Taal TypeScript 5.x
Styling Tailwind CSS 3.4
Component variants class-variance-authority (CVA) 0.7
Class merging tailwind-merge 3.4
Animaties tailwindcss-animate + Framer Motion 1.0 / 12.x
UI primitives Radix UI diverse
Iconen Lucide React 0.553
State management Zustand 5.x
Formulieren React Hook Form + Zod 7.x / 4.x
Rich text TipTap 3.x

Utility helper

// lib/utils.ts
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

2. Kleurensysteem

2.1 Basiskleuren

Token Hex Gebruik
app-background #F8FAFC Pagina-achtergrond (slate-50)
surface #FFFFFF Cards, panels
surface-sub #F1F5F9 Secundaire achtergrond (slate-100)
text-primary #0F172A Primaire tekst (slate-900)
text-secondary #475569 Secundaire/meta-tekst (slate-600)
border #E2E8F0 Standaard borders (slate-200)

2.2 Brand (Teal-first)

De primaire brandkleur is teal. Alle interactieve elementen, focus-states en links gebruiken deze kleur.

Token Hex Ratio Gebruik
brand-50 #F0FDFA Subtiele achtergrond
brand-100 #CCFBF1 Info-subtiel
brand-200 #99F6E4 Lichte tint
brand-400 #2DD4BF Decoratief
brand-500 #14B8A6 Accent
brand-600 #0D9488 3:1 UI-componenten (non-text)
brand-700 #0F766E 5.47:1 Primaire tekst & CTA (WCAG AA) ✓
brand-800 #115E59 Hover state
brand-900 #134E4A Donkerste tint
/* CSS custom properties */
--color-brand: #0F766E;
--color-brand-hover: #115E59;
--color-brand-active: #0D9488;
--color-brand-subtle: #F0FDFA;

2.3 AI Features (Amber)

AI-gerelateerde acties worden visueel onderscheiden door een amber kleurenpalet.

Token Hex Gebruik
ai-50 #FFFBEB Subtiele AI-achtergrond
ai-500 #F59E0B Primaire AI-kleur
ai-600 #D97706 AI-tekst (WCAG AA large)
ai-700 #B45309 AI hover

2.4 Module-accenten

Verschillende modules hebben een eigen kleurig accent:

Module Achtergrond Accent Border
Afspraken #E8F8EF #16A34A (groen) #CDECDC
Medicatie #FEF6DC #F59E0B (amber) #F6E7B6
Lab #FFEBDC #F97316 (oranje) #FFD2B8

2.5 Status & Feedback

Status Kleur Subtiel
Success #16A34A #ECFDF5
Warning #EAB308 #FEFCE8
Error #DC2626 #FEF2F2
Info #0F766E (teal) #CCFBF1

2.6 Severity Badges (DSM-light)

Ernst Achtergrond Tekst
Low #E5E7EB #374151
Medium #FEF3C7 #92400E
High #FEE2E2 #991B1B

2.7 Dark Mode

Dark mode is optioneel geïmplementeerd (MVP = licht thema):

.dark {
  --color-bg: #0a0a0a;
  --color-surface: #1a1a1a;
  --color-text: #ededed;
  --color-text-secondary: #a1a1a1;
  --color-border: #333333;
}

3. Typografie

3.1 Font Families

Drie fonts worden lokaal geladen via next/font/local:

Variabele Font Gewichten Gebruik
--font-serif Lora 400, 400i, 600 Long-form content, manifesto teksten
--font-sans Roboto 400, 500, 600 (+italic) UI, navigatie, metadata, body
--font-mono Source Code Pro 400, 600 Code, technische details, nummers

Body default: var(--font-sans), system-ui, -apple-system, sans-serif

3.2 Typografische Schaal

Token Waarde Toepassing
--text-hero clamp(2.5rem, 6vw, 4rem) Hero quotes
--text-h1 clamp(2rem, 5vw, 3rem) Sectie-koppen
--text-h2 clamp(1.5rem, 4vw, 2.5rem) Subsecties
--text-body 1.25rem Content, lopende tekst
--text-small 0.875rem Metadata, labels

3.3 Line Heights

Token Waarde Gebruik
--line-height-tight 1.2 Headings
--line-height-relaxed 1.8 Body/content

4. Shadows & Border Radius

Shadows

Token Waarde
shadow-sm 0 1px 2px rgba(15,23,42,0.06)
shadow-md 0 2px 6px rgba(15,23,42,0.08)
shadow-lg 0 8px 20px rgba(15,23,42,0.10)

Alle shadows zijn gebaseerd op slate-900 alpha — geen hard zwart.

Border Radius

Token Waarde
--radius 0.625rem (10px)
rounded-lg var(--radius)
rounded-md calc(var(--radius) - 2px) ≈ 8px
rounded-sm calc(var(--radius) - 4px) ≈ 6px

5. Formulieren

State Property Waarde
Default bg #FFFFFF
Default border #CBD5E1
Default tekst #0F172A
Placeholder kleur #94A3B8
Hover border #94A3B8
Focus ring/border #0F766E (teal-700)
Disabled bg #F1F5F9
Disabled tekst #94A3B8
Invalid border #DC2626
Invalid tekst #B91C1C

Input component patroon:

<input className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1
  text-base shadow-sm transition-colors placeholder:text-muted-foreground
  focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring
  disabled:cursor-not-allowed disabled:opacity-50 md:text-sm" />

6. Component Patronen

6.1 Component Architectuur

  • Alle componenten gebruiken React.forwardRef voor ref-forwarding
  • Varianten via class-variance-authority (CVA)
  • Styling via Tailwind classes + cn() utility
  • Radix UI als headless primitives (Dialog, Tabs, Select, Popover, etc.)
  • Default = server component; "use client" alleen wanneer interactiviteit vereist is

6.2 Button

Variant Stijl
default bg-primary text-primary-foreground hover:bg-primary/90
destructive bg-destructive text-destructive-foreground hover:bg-destructive/90
outline border border-input bg-background hover:bg-accent
secondary bg-secondary text-secondary-foreground hover:bg-secondary/80
ghost hover:bg-accent hover:text-accent-foreground
link text-primary underline-offset-4 hover:underline
Size Afmetingen
default h-10 px-4 py-2
sm h-9 px-3
lg h-11 px-8
icon h-10 w-10

6.3 AI Button

Speciaal component voor AI-acties. Visueel onderscheiden door amber gradient.

Variant Stijl
default Amber gradient (from-amber-600 to-amber-700) + witte tekst
outline border-2 border-amber-500, tekst amber-700
ghost Transparant, tekst amber-700, hover amber-50

Features:

  • Sparkle-icoon () als visuele AI-indicator
  • Loading state met Loader2 spinner
  • Drie maten: sm, md, lg

6.4 Card

┌─────────────────────────────┐
│ CardHeader      (p-6)       │
│   CardTitle     (semibold)  │
│   CardDescription (muted)  │
│ CardContent     (p-6 pt-0) │
│ CardFooter      (p-6 pt-0) │
└─────────────────────────────┘
  • rounded-xl, border, bg-card, shadow

6.5 Badge

Varianten: default, secondary, destructive, outline
Base: rounded-md, px-2.5 py-0.5, text-xs font-semibold

6.6 Tabs

  • TabsList: rounded-lg bg-muted p-1
  • TabsTrigger: rounded-md px-3 py-1 text-sm font-medium
  • Active state: bg-background text-foreground shadow

6.7 Toast

  • Positie: top op mobile, bottom-right op desktop
  • Swipe-to-dismiss ondersteuning
  • Slide-in animatie (top op mobile, bottom op desktop)
  • Varianten: default en destructive

7. Layout & Navigatie

7.1 App Shell

┌──────────────────────────────────────┐
│ ┌──────────┐ ┌─────────────────────┐ │
│ │          │ │                     │ │
│ │ Sidebar  │ │   Main Content      │ │
│ │ (fixed)  │ │   (scrollable)      │ │
│ │          │ │                     │ │
│ │          │ │                     │ │
│ └──────────┘ └─────────────────────┘ │
└──────────────────────────────────────┘
  • Container: min-h-screen bg-slate-50 flex
  • Sidebar: fixed, w-78 open / w-28 collapsed
  • Main content: flex-grow, scrollable

7.2 Sidebar UX

Eigenschap Waarde
Desktop breedte (open) w-78 (312px)
Desktop breedte (collapsed) w-28 (112px)
Achtergrond bg-white
Border border-r border-slate-200
Transition duration-300 ease-in-out
Mobile Full overlay met bg-black/40 backdrop-blur-sm

Active nav item: bg-teal-50 text-teal-700 + icoon text-teal-600
Inactive nav item: text-slate-600 hover:bg-slate-50 hover:text-slate-900

Collapsed state: tooltips verschijnen links met een pijl-indicator (bg-slate-800 text-white)

Profiel sectie: avatar cirkel, naam, rol, online-indicator (bg-green-500 dot)
Logout: text-red-600 hover:bg-red-50


8. Animaties

8.1 Float Animatie

Subtiele zweef-animatie voor badges of decoratieve elementen:

@keyframes float {
  0%, 100% { transform: translateY(0px) rotate(0deg); }
  25%      { transform: translateY(-5px) rotate(0.5deg); }
  50%      { transform: translateY(-3px) rotate(-0.5deg); }
  75%      { transform: translateY(-7px) rotate(0.3deg); }
}
.animate-float { animation: float 5s ease-in-out infinite; }

8.2 Artifact Slide-in

Panel slide-in van rechts:

@keyframes artifact-enter {
  from { transform: translateX(100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}
.artifact-enter { animation: artifact-enter 200ms ease-out; }

8.3 Transition Defaults

  • Navigatie / sidebar: transition-all duration-300 ease-in-out
  • Buttons / interactie: transition-colors of transition-all duration-200
  • Toasts: slide-in + fade via tailwindcss-animate

8.4 Reduced Motion

Volledige prefers-reduced-motion ondersteuning:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.02ms !important;
    transition-duration: 0.03ms !important;
    scroll-behavior: auto !important;
  }
}

9. Toegankelijkheid (A11y)

Aspect Implementatie
Focus indicator outline: 2px solid var(--color-brand), outline-offset: 2px
Focus ring (components) ring-2 ring-ring ring-offset-2
Skip to main Verborgen link, zichtbaar bij focus
Kleurcontrast Brand teal-700 = 5.47:1 op wit (WCAG AA ✓)
ARIA labels Alle interactieve elementen (toggle buttons, sidebar)
Reduced motion Alle animaties gerespecteerd
Iconen aria-hidden="true" op decoratieve iconen
Taal <html lang="nl">

10. AI UX Conventies

AI-functies worden visueel onderscheiden van standaard UI:

Element Conventie
Kleur Amber-palet (geel/goud), nooit teal
Button AIButton component met Sparkle-icoon ()
Highlight .ai-source-highlight — lichtgeel (#fef08a) met border-radius: 2px
Loading Loader2 spinner (animatie: animate-spin)
Feedback Confidence indicators bij AI-gegenereerde content

11. Quick-Start Checklist

Om deze stijl in een nieuw project over te nemen:

  1. Installeer dependencies:

    pnpm add class-variance-authority clsx tailwind-merge tailwindcss-animate
    pnpm add lucide-react framer-motion
    pnpm add @radix-ui/react-dialog @radix-ui/react-tabs @radix-ui/react-select
    # + overige Radix primitives naar behoefte
    
  2. Kopieer fonts (Lora, Roboto, Source Code Pro) naar public/fonts/ en configureer in layout.tsx

  3. Kopieer CSS custom properties uit globals.css (sectie :root)

  4. Kopieer Tailwind config — met name colors, boxShadow, borderRadius extensies

  5. Kopieer cn() utility naar lib/utils.ts

  6. Kopieer UI components uit components/ui/ (shadcn-patroon met CVA)

  7. Zet antialiased op de <body> tag

  8. Zet lang="nl" op de <html> tag


Gegenereerd op basis van de mini-epd-prototype codebase (maart 2026).