05 — Interaction Design
05 — Interaction Design
Section titled “05 — Interaction Design”“Nintendo maakt al 40 jaar de meest satisfying games ter wereld. Het geheim is wat game designers ‘juice’ noemen — de overdreven feedback op elke actie die het brein vertelt: Dat ging goed. Doe het nog eens.”
Dit document beschrijft de volledige interactielaag van Beam: geluiden, micro-animaties, cursors, ambient muziek, en het Nintendo Juice principe. Deze laag maakt de editor niet alleen functioneel maar voelbaar goed.
Inhoudsopgave
Section titled “Inhoudsopgave”- Nintendo Juice — Het Principe
- Micro-geluiden
- Micro-animaties
- Custom Cursors
- Ambient Muziek
- Interaction Design in de Styling Builder
- Technische Implementatie
- Toegankelijkheid
- Bouwvolgorde
1. Nintendo Juice — Het Principe
Section titled “1. Nintendo Juice — Het Principe”Meervoudige Feedback
Section titled “Meervoudige Feedback”In Mario pakt je een muntje → geluidje + sparkle + counter animatie + lichte screen shake. Vier feedback-signalen voor één simpele actie. Het voelt geweldig terwijl je rationeel weet dat het “maar een muntje” is.
In Zelda open je een kist → slow-motion + icoontje stijgt op + fanfare + tekst beschrijving. Een moment van ceremonie voor een ontdekking.
De vuistregel voor Beam: elke gebruikersactie verdient minimaal twee feedback-signalen (visueel + audio, of visueel + beweging). Eén signaal voelt klinisch. Twee voelen menselijk. Drie voelen magisch.
Nintendo Referenties → Beam Toepassingen
Section titled “Nintendo Referenties → Beam Toepassingen”| Nintendo Referentie | Beam Toepassing |
|---|---|
| Mario munt (geluid + sparkle + counter) | Block toevoegen: pop + fade-in + block counter update |
| Zelda kist (fanfare + reveal) | Addon activatie: booster pack unboxing (kaart voor kaart) |
| Mario star (muziek verandert + onkwetsbaarheid) | Publiceren: confetti + chime + dashboard viert mee |
| Zelda Korok (verrassing op onverwachte plek) | Secret synergie block ontdekt: glow + speciaal geluidje |
| Animal Crossing museum (curated collectie) | Beam Codex: je block collectie groeit en wordt mooier |
| Mario Kart boost (screen blur + snelheidslijnen) | Undo/redo: shimmer effect over het canvas |
| Zelda cooking (ingrediënten combineren → resultaat) | Pattern maken: blocks combineren → iets nieuws |
| Wii Sports bowling (iedereen kan het) | Guardrails: je kunt het niet lelijk maken |
De Editor als Instrument
Section titled “De Editor als Instrument”Het ultieme doel: de editor voelt als een instrument dat je bespeelt. Niet als een formulier dat je invult. Na een uur bouwen voel je je niet uitgeput maar energiek — omdat de tool met je meewerkt.
2. Micro-geluiden
Section titled “2. Micro-geluiden”Overzicht Editor Geluiden
Section titled “Overzicht Editor Geluiden”Subtiele, warme geluiden die feedback geven zonder opdringerig te zijn. Denk aan Notion of Linear — niet aan arcade games.
| Actie | Geluid | Karakter |
|---|---|---|
| Block toevoegen | Zacht “pop” | Iets nieuws verschijnt |
| Block verwijderen | Zacht “whoosh” | Iets verdwijnt elegant |
| Block verplaatsen (drag) | Subtiel “slide” | Beweging, gewicht |
| Block droppen | Zacht “thud” | Iets landt op zijn plek |
| Pagina opslaan | Warm “ding” | Bevestiging, veiligheid |
| Pagina publiceren | Groter “chime” | Feestelijk moment |
| Undo/Redo | Zacht “tick/tock” | Tijd terugdraaien |
| Selectie | Click | Precies, responsief |
| Block groeperen | Harmonisch “merge” geluid | Dingen komen samen |
| Foutmelding | Zacht “bonk” | Nope, maar niet boos |
| Achievement unlock | Subtiel “level up” chime | Herkenbaar, belonend |
| Site live | Confetti + triumfantelijke chime | Het grote moment |
Geluidsprofiel per Gilde
Section titled “Geluidsprofiel per Gilde”| Gilde | Sound Character | Inspiratie |
|---|---|---|
| ⚕️ Healers | Klankschaal, natuur, water | Spa-achtig, meditatief |
| 🎨 Creators | Creatieve tonen, potlood, canvas | Atelier-sfeer |
| 🏪 Merchants | Kassageluiden, verpakkend | Winkelsfeer, warm |
| 📚 Scholars | Boekpagina’s, pen op papier | Bibliotheek, focus |
| 🍽️ Hosts | Bestek, kurk, deurbelletje | Gastvrij, huiselijk |
| 🔧 Builders | Hout, metaal, precisiegereedschap | Werkplaats, ambacht |
Technische Specificaties
Section titled “Technische Specificaties”- Alle geluiden standaard aan maar met volume slider (0–100%)
- Geluiden als kleine
.webmbestanden (< 5KB elk), opgeslagen op CF R2 - Web Audio API voor low-latency playback
- Geladen op eerste interactie — niet bij page load
- Geluidsprofiel gekoppeld aan het gekozen gilde (verandert automatisch mee)
3. Micro-animaties
Section titled “3. Micro-animaties”Editor Animaties
Section titled “Editor Animaties”Elke interactie heeft een subtiele beweging die het resultaat bevestigt:
| Actie | Animatie |
|---|---|
| Block hover | Zachte glow/highlight, licht optillen (2px shadow) |
| Block selecteren | Smooth border-animatie, sidebar slide-in |
| Block toevoegen | Fade-in + slight scale (0.95 → 1.0) |
| Block verwijderen | Shrink + fade-out |
| Drag start | Block tilt licht, shadow groeit (lifted) |
| Drop | Bounce-settle op doelpositie |
| Pagina opslaan | Checkmark animatie in save-button |
| Pagina publiceren | Button → confetti burst (eenmalig per publicatie) |
| Achievement | Toast slide-in met glow effect |
| Undo | Subtiele “rewind” shimmer over het canvas |
| Block groeperen | Elements bewegen naar elkaar toe → merge animatie |
Spring Physics
Section titled “Spring Physics”Alle animaties gebruiken spring physics — niet lineaire beziers. Dit geeft een natuurlijk gevoel alsof objecten massa hebben.
Implementatie: gebruik motion (het standalone framework-agnostische pakket) of CSS spring bezier waarden:
import { motion } from 'motion'
// Block toevoegen<motion.div initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} transition={{ type: 'spring', stiffness: 400, damping: 25 }}/>
// Drag feedback<motion.div whileDrag={{ scale: 1.02, rotate: 1, boxShadow: '0 8px 24px rgba(0,0,0,0.15)' }} transition={{ type: 'spring', stiffness: 600, damping: 30 }}/>
// Drop landing<motion.div animate={{ y: [4, 0] }} transition={{ type: 'spring', stiffness: 500, damping: 20 }}/>Confetti bij Publiceren
Section titled “Confetti bij Publiceren”Eenmalig per publicatie — het grote moment verdient ceremonie:
import confetti from 'canvas-confetti'
export function celebratePublish() { confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 }, colors: ['#1B4D7A', '#D4883E', '#F5F0EB'] // brand colors })}4. Custom Cursors
Section titled “4. Custom Cursors”De standaard cursor is functioneel maar emotieloos. Een custom cursor voegt persoonlijkheid toe.
| Context | Cursor |
|---|---|
| Default | Beam branded pointer (subtiel, niet gimmicky) |
| Over blocks | Crosshair met zachte glow |
| Drag modus | Grab hand → grabbing hand (met shadow) |
| Text editing | Beam branded I-beam |
| Color picker | Pipet/eyedropper |
| Resize | Elegante resize arrows |
Per Gilde Cursor Theme (optioneel)
Section titled “Per Gilde Cursor Theme (optioneel)”- ⚕️ Healers: zachte, ronde cursor
- 🎨 Creators: potlood/pen cursor
- 🔧 Builders: precision crosshair
Technische Implementatie
Section titled “Technische Implementatie”- SVG cursors via CSS
cursor: url()voor performance - Fallback naar system cursors bij
prefers-reduced-motion - Gebruiker kan kiezen: Beam cursor / Gilde cursor / Systeem cursor
.editor-canvas { cursor: url('/cursors/beam-default.svg') 4 4, auto;}.editor-canvas[data-dragging] { cursor: url('/cursors/beam-grabbing.svg') 12 12, grabbing;}5. Ambient Muziek
Section titled “5. Ambient Muziek”Optioneel, subtiel, en contextbewust. Niet als achtergrondmuziek die je verdraagt, maar als sfeer die je dag beter maakt.
Context-Afhankelijke Muziek
Section titled “Context-Afhankelijke Muziek”| Modus | Muziek | Karakter |
|---|---|---|
| Editor (bouwen) | Lo-fi ambient, soft focus | Concentratie, flow |
| Dashboard (plannen) | Licht, positief, ruimtelijk | Overzicht, controle |
| Preview (bewonderen) | Stiller, meer ruimte | Het resultaat staat centraal |
| Publiceren | Kort moment van triomf | Climax → rust |
Muziekprofiel per Gilde
Section titled “Muziekprofiel per Gilde”| Gilde | Muziekstijl |
|---|---|
| ⚕️ Healers | Ambient pads, klankschalen, natuur |
| 🎨 Creators | Lo-fi beats, creatieve piano, vinyl crackle |
| 🏪 Merchants | Jazzy, upbeat lo-fi, warm |
| 📚 Scholars | Classical-inspired ambient, focus |
| 🍽️ Hosts | Café jazz, acoustic, gezellig |
| 🔧 Builders | Minimal techno-ambient, industrieel maar warm |
Technische Specificaties
Section titled “Technische Specificaties”- Standaard uit — opt-in bij eerste gebruik: “Wil je ambient muziek terwijl je bouwt?”
- Volume slider onafhankelijk van geluidseffecten
- Naadloze loops (geen hoorbare start/stop)
- Context-switch crossfade (editor → dashboard → preview)
- Respecteer browser autoplay policies
- ~5 tracks per profiel, random rotatie
- Muziek als streaming vanuit CF R2 (geen grote downloads)
6. Interaction Design in de Styling Builder
Section titled “6. Interaction Design in de Styling Builder”De styling builder is niet alleen functioneel — hij voelt goed. Elke actie heeft minimaal twee feedback-signalen:
| Actie | Visueel | Audio |
|---|---|---|
| Kleur wijzigen | Ripple-animatie door alle tokens die de kleur gebruiken | Zacht “toon” geluid (pitch volgt kleur-hue) |
| Shade schaal hergenereren | Vloeiende overgang van oude naar nieuwe tinten | Oplopende toonreeks (laag→hoog) |
| Font wisselen | Smooth morph van oude naar nieuwe font in canvas | Zacht “page turn” |
| Radius aanpassen | Alle elementen animeren met spring physics | Subtiel “click” per stap |
| Guardrail ✅ | Groen vinkje fade-in | Zacht “ding” |
| Guardrail ⚠️ | Element schudt licht + suggestie slide-in | Zacht “bonk” |
| Token opslaan | Checkmark animatie op save-button | Warm “ding” |
| Publiceren | Confetti burst + tokens “settelen” met bounce | Triumfantelijk “chime” |
| Style Pack laden | Kaart-voor-kaart onthulling van de nieuwe stijl | Unboxing geluidjes |
Geluidsprofiel: volgt het gilde van de gebruiker. Een Healer hoort klankschaal-achtige tonen, een Creator hoort atelier-geluiden.
Radius Aanpassen — Ripple Effect
Section titled “Radius Aanpassen — Ripple Effect”Wanneer de gebruiker de radius aanpast, animeren alle elementen in het preview-canvas simultaan:
// Alle border-radius-waarden animeren synchroonconst radiusPresets = { none: '0px', small: '4px', medium: '8px', large: '16px', pill: '9999px'}
// Spring physics voor de overganganimate('.preview-element', { borderRadius: radiusPresets[newPreset]}, { type: 'spring', stiffness: 300, damping: 20 })7. Technische Implementatie
Section titled “7. Technische Implementatie”Sound Engine
Section titled “Sound Engine”interface BeamAudioEngine { // Sound effects playSound(id: SoundId, options?: { volume?: number }): void setSoundVolume(volume: number): void // 0-100 setSoundProfile(gilde: GildeId): void setSoundEnabled(enabled: boolean): void
// Ambient music playAmbient(context: 'editor' | 'dashboard' | 'preview'): void stopAmbient(): void setMusicVolume(volume: number): void setMusicProfile(gilde: GildeId): void setMusicEnabled(enabled: boolean): void crossfade(toContext: string, duration: number): void}
type SoundId = | 'block-add' | 'block-remove' | 'block-drop' | 'block-drag' | 'save' | 'publish' | 'undo' | 'redo' | 'select' | 'group' | 'error' | 'achievement' | 'site-live'Integratie met Editor Store
Section titled “Integratie met Editor Store”// In Zustand store actions — sound wordt automatisch afgespeeldaddBlock: (type, index) => { set((state) => { /* block logic */ }) audioEngine.playSound('block-add')},removeBlock: (blockId) => { set((state) => { /* block logic */ }) audioEngine.playSound('block-remove')},savePage: async () => { await api.savePage(/* ... */) audioEngine.playSound('save')},publishPage: async () => { await api.publishPage(/* ... */) audioEngine.playSound('publish') celebratePublish() // confetti},Motion Library
Section titled “Motion Library”import { animate, spring } from 'motion'
// Block toevoegenexport function animateBlockAdd(element: HTMLElement) { animate(element, { opacity: [0, 1], scale: [0.95, 1] }, { duration: 0.2, easing: spring({ stiffness: 400, damping: 25 }) } )}
// Block verwijderenexport function animateBlockRemove(element: HTMLElement): Promise<void> { return animate(element, { opacity: [1, 0], scale: [1, 0.95] }, { duration: 0.15 } ).finished}
// Undo shimmerexport function animateUndo(canvas: HTMLElement) { animate(canvas, { filter: ['brightness(1)', 'brightness(1.05)', 'brightness(1)'] }, { duration: 0.3, easing: 'ease-out' } )}Asset Structuur op CF R2
Section titled “Asset Structuur op CF R2”r2/beam-assets/ sounds/ default/ block-add.webm block-remove.webm save.webm publish.webm achievement.webm ... healers/ block-add.webm ← klankschaal variant ... creators/ block-add.webm ← atelier variant ... music/ healers/ editor-01.mp3 editor-02.mp3 ... creators/ ...8. Toegankelijkheid
Section titled “8. Toegankelijkheid”prefers-reduced-motion
Section titled “prefers-reduced-motion”Alle animaties respecteren de gebruikersvoorkeur:
@media (prefers-reduced-motion: reduce) { .beam-animated { transition: none !important; animation: none !important; }}// In motion wrappersconst prefersReducedMotion = window.matchMedia( '(prefers-reduced-motion: reduce)').matches
const transition = prefersReducedMotion ? { duration: 0 } : { type: 'spring', stiffness: 400, damping: 25 }Geluiden bij Reduced Motion
Section titled “Geluiden bij Reduced Motion”Bij prefers-reduced-motion: reduce worden geluiden standaard uitgeschakeld. De gebruiker kan ze expliciet aanzetten via de instellingen.
Gebruikerscontrole
Section titled “Gebruikerscontrole”- Volume slider (0–100%) voor geluidseffecten, apart van muziek
- Muziek is opt-in — nooit automatisch
- Cursor kan worden teruggezet naar system cursor
- Alle interactie-feedback is optioneel (maar aanbevolen)
9. Bouwvolgorde
Section titled “9. Bouwvolgorde”Fase 1: Basis Geluiden
Section titled “Fase 1: Basis Geluiden”- Web Audio API wrapper (
BeamAudioEngine) - 10 basis geluiden: add, remove, drag, drop, save, publish, undo, redo, select, error
- Sound settings in user preferences
prefers-reduced-motionsupport- Assets op CF R2
Fase 2: Micro-animaties
Section titled “Fase 2: Micro-animaties”- Spring physics setup (
motionlibrary) - Block operaties: fade-in/out, drag tilt, drop bounce
- Sidebar slide-in bij block selectie
- Checkmark animatie op save
- Confetti bij publiceren
Fase 3: Gilde Awareness
Section titled “Fase 3: Gilde Awareness”- Geluidsprofiel per gilde (6 profielen, elk met 10+ varianten)
- Muziekprofiel per gilde (5 tracks per profiel)
- Context-switch crossfade (editor/dashboard/preview)
Fase 4: Custom Cursors
Section titled “Fase 4: Custom Cursors”- Beam cursor SVGs
- Context-afhankelijke cursors (grab, I-beam, eyedropper)
- Gilde cursor themes
Fase 5: Styling Builder Interacties
Section titled “Fase 5: Styling Builder Interacties”- Ripple-animatie bij kleurpropagatie
- Pitch-variatie bij kleurwijziging (hue → toon)
- Toonreeks bij shade generatie
- Unboxing geluidjes bij Style Pack wisselen
Fase 6: Ambient Muziek
Section titled “Fase 6: Ambient Muziek”- Muziek streaming systeem
- Naadloze loops
- Context-switch crossfade
- Opt-in flow bij eerste gebruik