Skip to content

Craft

BuiltTunedInspectable

Craft · 試作

A lab of small, self-contained interactions — the kind I build to get a feel exactly right: the slide, the spring, the way a thing should respond to your hand. Every one runs at 60fps, works on touch and keyboard, and opens to its full build breakdown and source.

06experiments · interactive & inspectable

Experiments

Liquid Glass nav

One shared spotlight pill glides under whatever you hover or focus, then settles back on the selected item — a single animated element, not a fade per link.

  • GSAP
  • Shared element
  • Keyboard
Build breakdown
  • The pill is one absolutely-positioned span; on hover/focus I measure the target button's offsetLeft + width and tween x/width with power3.out (~280ms — under the 300ms perceived-instant ceiling).
  • Only transform and width animate — no layout per frame — so it holds 60fps.
  • Focus drives the exact same motion as hover, and Enter/Space selects; the pill re-aligns on resize.
  • Reduced motion → the pill jumps instantly instead of tweening.
Full build & source →

Drag-to-dismiss sheet

A bottom sheet you can fling away. Drag past 40% of its height — or flick it down fast — to dismiss; anything less springs back. Pulling up rubber-bands.

  • GSAP
  • Pointer Events
  • Gesture
Build breakdown
  • Dragging is hand-rolled on Pointer Events with setPointerCapture, so the gesture survives the pointer leaving the grabber (mouse + touch alike).
  • Release reads distance and velocity (px/ms from event timestamps): past the threshold it dismisses, otherwise GSAP springs it back to rest.
  • Upward pulls past rest are damped to 25% for a rubber-band feel; touch-action:none stops the page scrolling under the drag.
  • Keyboard users get an explicit Close button and Escape; focus moves into the sheet on open and back to the trigger on close.
Full build & source →

Origin-aware popover

The panel grows out of the button that opened it — its transform-origin points at the trigger's centre, so it unfolds from the right spot every time.

  • GSAP
  • transform-origin
  • A11y
Build breakdown
  • On open I measure the trigger, clamp the panel within the stage, and set transform-origin to the trigger's centre in px.
  • Mouse opens with a quick scale(0.96)+fade from that origin; keyboard opens instantly — animating keyboard-driven UI is disorienting.
  • Positioning + the tween run in a GSAP layout effect, so the panel never flashes unpositioned.
  • Escape closes and restores focus to the trigger; an outside pointerdown closes without stealing focus.
Full build & source →

Click to copy

Click-to-copy email

Tap the address and it's on your clipboard — the icon pops to a check and the button confirms 'Copied', then settles back. The same control ships on the contact page.

  • GSAP
  • Clipboard API
  • A11y
Build breakdown
  • Copy goes through the async Clipboard API, with a hidden-textarea + execCommand fallback for older or insecure contexts so it still works everywhere.
  • On success the icon swaps Copy → Check and pops with a GSAP back.out(3) scale; the address itself stays select-all for manual copy.
  • The result is announced through a polite aria-live status region, so screen-reader users hear 'Copied' without focus moving.
  • Reduced motion → the icon swaps instantly with no pop.
Full build & source →

Magnetic button

Move near it and the button leans toward your cursor — its label drifting a little further for depth — then springs back the moment you leave.

  • GSAP
  • quickTo
  • Pointer
Build breakdown
  • On pointermove I read the cursor's offset from the button's centre and translate the button a fraction of it (≈0.4×, clamped to ±40px) so it leans toward you without chasing the cursor off the card.
  • Both axes run through prebuilt gsap.quickTo setters — no tween is allocated per move — so it holds 60fps under a fast flick.
  • The label sits in its own layer and travels a touch further than the button, for a parallax sense of depth.
  • Leaving springs everything back to rest with elastic.out. It's a real button (keyboard-focusable, Enter/Space activates); the magnet is pointer-only, and reduced motion → it sits still.
Full build & source →

Off

Spring-loaded toggle

A switch whose thumb overshoots the far edge and settles back — squashing a little as it travels — so flipping it feels physical, not linear.

  • GSAP
  • back.out
  • A11y
Build breakdown
  • The thumb travels on a GSAP back.out(2.4) spring, so it overshoots the far edge and rebounds — that little settle is what sells the 'click'.
  • As it moves the thumb squashes ~14% along its direction of travel, then rounds back out at rest, like a physical switch.
  • The track colour crossfades neutral ↔ accent in lockstep with the throw.
  • It's a real role=switch — aria-checked, Tab to focus, Space/Enter to flip, with a visible focus ring; reduced motion snaps it with no overshoot.
Full build & source →