Coloriginz Design Systemshadcn custom registry

@col/demo-mode

Versie: 1.1.0 Toegevoegd: 2026-08-02

Herkomst

Geëxtraheerd uit supplier-onboarding-vercel/src/components/demo-banner.tsx (259 regels) toen bleek dat een tweede applicatie dezelfde testbalk nodig had — niet alleen de vorm, maar ook de werking: rolselectie en e-mailconfigurator.

Het origineel vermengde vier lagen: presentatie, client-gedrag, backend-contract en domeindata. Bij de extractie zijn die uit elkaar gehaald en zijn twee bugs uit het origineel verholpen (zie Bewuste keuzes).

Waarvoor

Een balk boven aan de pagina die zichtbaar maakt dat je niet op productie zit, met optioneel twee besturingselementen: van rol wisselen zonder uit te loggen, en schakelen tussen een testinbox en echte e-mailverzending.

Bedoeld voor test- en demo-omgevingen. Op productie rendert de app hem niet — dat is een keuze van de consumer, niet van het item zelf.

Gebruik het niet als algemene notificatiebalk; DemoBar is een shell met een slot en zou daarvoor werken, maar de tokens en naamgeving zijn op demo gericht.

Wat je app moet leveren

<DemoBar>

Prop Type Betekenis
message string Tekst in het midden
maxWidth string? Tailwind max-width class, default max-w-6xl
children ReactNode? Controls, rechts uitgelijnd

<DemoRoleSwitcher>

Prop Type Betekenis
available { value, label }[] Alle kiesbare rollen
active string[] Nu actieve rollen
onChange (roles) => void | Promise<void> Wordt aangeroepen met de nieuwe set
minRoles number? Minimaal actief te houden, default 1
disabled boolean?
labels { trigger, heading } Teksten

<DemoEmailSwitcher>

Controlled. provider: 'test' \| 'live', recipient: string \| null, onProviderChange, onRecipientSave, optioneel testInboxUrl, en een labels-object met twaalf teksten (zie demo-types.ts). De callbacks mogen false teruggeven om aan te geven dat de actie mislukte; dan toont het component geen bevestiging.

useDemoEmail(options?)

Geeft { provider, recipient, onProviderChange, onRecipientSave }. Opties: enabled (default true) en endpoint (default /api/email-provider). Fouten worden bewust stil geslikt — de balk mag de app nooit blokkeren — maar de callbacks geven false terug zodat de UI het wél kan tonen.

Backend-contract

GET  <endpoint>
  -> 200 { provider: 'test' | 'live', recipient: string | null }
  -> 404 als demo mode uit staat
  -> 401 als niet ingelogd

POST <endpoint>  { provider?: 'test' | 'live', recipient?: string | null }
  -> 200 { provider, recipient }
  -> 400 bij lege body of ongeldige provider

@col/demo-mode-starter levert een implementatie tegen cookies, plus een sjabloon voor het rolwissel-endpoint (POST { roles: string[] }).

Bestanden

Bestand Landt in Soort
demo-types.ts components/demo/ beheerd
roles.ts components/demo/ beheerd
demo-bar.tsx components/demo/ beheerd
demo-role-switcher.tsx components/demo/ beheerd
demo-email-switcher.tsx components/demo/ beheerd
use-demo-email.ts components/demo/ beheerd
demo-controls.tsx components/demo/ glue
email-provider-route.ts app/api/email-provider/ glue
switch-role-route.ts app/api/auth/switch-role/ glue

Upstream shadcn-afhankelijkheden: button, badge, input, dropdown-menu. Tokens: zeven --demo-* variabelen, meegeleverd via cssVars.

Gebruikt door

App Sinds versie Opmerkingen
supplier-onboarding-vercel (Onboarding Portal) 1.0.0 Consumer #1. Live op productie sinds 3 aug 2026. Glue koppelt aan Role/RoleLabels uit @/types en aan het eigen i18n-systeem.
floriday-app (Floriday middleware) 1.0.1 Consumer #2, sinds 3 aug 2026. Draait op base-ui in plaats van Radix — zie hieronder. Eén rol per gebruiker (UserRole, geen array), rol zit in de JWT dus de glue roept useSession().update({}) aan na een wissel. Geen NEXT_PUBLIC_DEMO_MODE: gate op VERCEL_ENV/VERCEL server-side.

Wat consumer #2 tegenkwam op base-ui

Twee dingen die de moeite van het weten waard zijn voor de volgende app die dit item niet op Radix draait:

Bewuste keuzes

Bekende beperkingen