← Blurr Motion form-microinteractions-minimal
Categorie forms Tier 1 Techniek #19 Deps gsap

Motion Lab / Forms / microinteractions / minimal

Naam
E-mail
Bericht
1. Mechanisme — kopieer 1-op-1, geen styling-keuzes
// Mechanisme: form-microinteractions-minimal (techniek #19 — float-label + checkmark)
// Bij focus: label translate y:-8 + scale 0.85. Bij non-empty input: mini-checkmark fade-in.
// Auto-demo: cycle door 3 fields om de 2s, focust + filt programmatically.
import gsap from 'https://esm.sh/[email protected]';
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const fields = document.querySelectorAll('.mini-field');
fields.forEach((f) => {
  const inp = f.querySelector('input,textarea');
  const lbl = f.querySelector('.mini-label');
  const chk = f.querySelector('.mini-check');
  const sync = () => {
    const lifted = !!inp.value || document.activeElement === inp;
    if (reduce) { lbl.style.transform = lifted ? 'translateY(-18px) scale(0.85)' : 'none'; chk.style.opacity = inp.value ? '1' : '0'; return; }
    gsap.to(lbl, { y: lifted ? -18 : 0, scale: lifted ? 0.85 : 1, duration: 0.3, ease: 'power2.out', transformOrigin: 'left center' });
    gsap.to(chk, { autoAlpha: inp.value ? 1 : 0, duration: 0.25 });
  };
  inp.addEventListener('focus', sync);
  inp.addEventListener('blur', sync);
  inp.addEventListener('input', sync);
});
const samples = ['Anna de Vries', '[email protected]', 'Graag een offerte voor een nieuwe website.'];
let idx = 0;
const tick = () => {
  const inputs = Array.from(document.querySelectorAll('.mini-field input,.mini-field textarea'));
  if (!inputs.length) return;
  inputs.forEach((i) => { i.value = ''; i.dispatchEvent(new Event('input')); });
  const tgt = inputs[idx % inputs.length];
  tgt.focus();
  const text = samples[idx % samples.length];
  let n = 0;
  const type = () => { if (n <= text.length) { tgt.value = text.slice(0, n); tgt.dispatchEvent(new Event('input')); n++; setTimeout(type, 35); } };
  type();
  idx++;
};
if (!reduce) { setTimeout(tick, 800); setInterval(tick, 4500); }
2. Skeleton — DOM + class-namen, mag herschikken
<!-- Skeleton: form-microinteractions-minimal -->
<form class="mini-form">
  <div class="mini-field">
    <input type="text" />
    <span class="mini-label">Naam</span>
    <svg class="mini-check" viewBox="0 0 24 24" width="14" height="14"><path d="M5 12 L10 17 L19 8" stroke="currentColor" stroke-width="1" fill="none"/></svg>
  </div>
  <!-- 3 fields -->
  <button type="submit">Verstuur</button>
</form>
3. Styling-template — verplicht eigen invulling per merk
/* Styling: form-microinteractions-minimal */
:root {
  --block-paper: #F4F1EB;
  --block-ink: #0A0A0A;
  --block-rule: rgba(10,10,10,.18);
  --block-muted: rgba(10,10,10,.45);
}
.mini-form { background: var(--block-paper); color: var(--block-ink); font-family: 'Inter', system-ui, sans-serif; font-weight: 300; max-width: 480px; display: flex; flex-direction: column; gap: 2.5rem; padding: clamp(3rem,6vw,5rem) 0; }
.mini-form .mini-field { position: relative; padding-top: 1.25rem; }
.mini-form .mini-field input,
.mini-form .mini-field textarea { width: 100%; appearance: none; border: 0; border-bottom: 1px solid var(--block-rule); background: transparent; padding: .6rem 1.5rem .6rem 0; font: 300 1rem/1.5 'Inter', sans-serif; color: var(--block-ink); outline: none; resize: none; }
.mini-form .mini-field input:focus,
.mini-form .mini-field textarea:focus { border-bottom-color: var(--block-ink); }
.mini-form .mini-field textarea { min-height: 4rem; }
.mini-form .mini-label { position: absolute; left: 0; top: 1.85rem; font: 300 1rem/1 'Inter', sans-serif; color: var(--block-muted); pointer-events: none; }
.mini-form .mini-check { position: absolute; right: 0; top: 1.85rem; opacity: 0; visibility: hidden; color: var(--block-ink); }
.mini-form button { align-self: flex-start; appearance: none; background: var(--block-ink); color: var(--block-paper); border: 0; padding: .9rem 2rem; font: 300 .95rem 'Inter', sans-serif; letter-spacing: .02em; cursor: pointer; }