Gabriel's banner
Gabriel's profile picture

Gabriel

@gabriell_lab7,286 subscribers

designer ex. @Porsche & @Audi

Shorts

Design Engineering Tip: Most UI animations are built for a single uninterrupted transition. Real users might reverse direction before the animation finishes. Use a spring transition that preserves the element’s current velocity instead of restarting from zero. This keeps rapid hover, press, and state changes smooth and responsive. transition={{ type: "spring", stiffness: 520, damping: 38, }}

Design Engineering Tip: Most UI animations are built for a single uninterrupted transition. Real users might reverse direction before the animation finishes. Use a spring transition that preserves the element’s current velocity instead of restarting from zero. This keeps rapid hover, press, and state changes smooth and responsive. transition={{ type: "spring", stiffness: 520, damping: 38, }}

62,136 Aufrufe

Since Opus 4.8 is out and more and more designers are getting into Design Engineering, I thought I’d share some of the interaction patterns I use most often: Use proximity, not just hover. When the cursor gets close, nearby elements can subtly scale and darken based on distance. It makes interfaces feel more responsive, less binary, and way more alive onpointermove = e => document.querySelectorAll(".dock>*").forEach(el => { const r = el.getBoundingClientRect(); const t = Math.max(0, 1 - Math.abs(e.clientX - r.x - r.width/2) / 120); el. style.scale = 1 + t * .5; });

Since Opus 4.8 is out and more and more designers are getting into Design Engineering, I thought I’d share some of the interaction patterns I use most often: Use proximity, not just hover. When the cursor gets close, nearby elements can subtly scale and darken based on distance. It makes interfaces feel more responsive, less binary, and way more alive onpointermove = e => document.querySelectorAll(".dock>*").forEach(el => { const r = el.getBoundingClientRect(); const t = Math.max(0, 1 - Math.abs(e.clientX - r.x - r.width/2) / 120); el. style.scale = 1 + t * .5; });

663,333 Aufrufe

I’ve been using 60% Apple-style corner smoothing all the time. But whenever I explain it to Codex or Claude Code, they often miss the point. So I made a skill that anyone can use with their AI agents: npx skills add gabrielobholz/corner-smoothing-skill Now I can simply say: “Create a rectangle with radius: 32 and smoothing: 60” and get the shape I actually mean.

I’ve been using 60% Apple-style corner smoothing all the time. But whenever I explain it to Codex or Claude Code, they often miss the point. So I made a skill that anyone can use with their AI agents: npx skills add gabrielobholz/corner-smoothing-skill Now I can simply say: “Create a rectangle with radius: 32 and smoothing: 60” and get the shape I actually mean.

95,520 Aufrufe

Design Engineering Tip: One CSS property is responsible for most ugly expand animations. It’s height: auto. Replace it with: grid-template-rows: 0fr → 1fr;

Design Engineering Tip: One CSS property is responsible for most ugly expand animations. It’s height: auto. Replace it with: grid-template-rows: 0fr → 1fr;

107,458 Aufrufe

If you struggle to describe UI transitions in Claude or Codex, these commonly used transition terms can help. Save this for later.

If you struggle to describe UI transitions in Claude or Codex, these commonly used transition terms can help. Save this for later.

267,114 Aufrufe

Design Engineering Tip: Don’t move objects at a constant shape. As speed increases, stretch them in the direction of travel. The faster they move, the more they deform. Combined with easing and subtle motion blur, even simple animations can feel significantly more dynamic. const x = useMotionValue(0) const v = useVelocity(x) const scaleX = useTransform(v, [-1200, 0, 1200], [1.8, 1, 1.8]) const blur = useTransform(v, [-1200, 0, 1200], [3, 0, 3]) `blur(${b}px)`), }} />

Design Engineering Tip: Don’t move objects at a constant shape. As speed increases, stretch them in the direction of travel. The faster they move, the more they deform. Combined with easing and subtle motion blur, even simple animations can feel significantly more dynamic. const x = useMotionValue(0) const v = useVelocity(x) const scaleX = useTransform(v, [-1200, 0, 1200], [1.8, 1, 1.8]) const blur = useTransform(v, [-1200, 0, 1200], [3, 0, 3]) `blur(${b}px)`), }} />

89,180 Aufrufe

Design Engineering Tip: Add friction at the end of a scroll interaction. When users reach the edge of a scrollable area, the movement should not just stop instantly. A subtle resistance, bounce, or slowdown can make the interface feel more physical and less mechanical. It helps users understand that they reached a boundary without needing extra labels or visual indicators. Used carefully, this can make scrolling feel more natural and closer to how objects behave in the real world.

Design Engineering Tip: Add friction at the end of a scroll interaction. When users reach the edge of a scrollable area, the movement should not just stop instantly. A subtle resistance, bounce, or slowdown can make the interface feel more physical and less mechanical. It helps users understand that they reached a boundary without needing extra labels or visual indicators. Used carefully, this can make scrolling feel more natural and closer to how objects behave in the real world.

24,503 Aufrufe

Design Engineering Tip Consider letting textareas grow with the content instead of introducing nested scrolling. It often creates a smoother writing experience and keeps forms easier to scan. CSS: textarea { field-sizing: content; }

Design Engineering Tip Consider letting textareas grow with the content instead of introducing nested scrolling. It often creates a smoother writing experience and keeps forms easier to scan. CSS: textarea { field-sizing: content; }

85,400 Aufrufe

Design Engineering Tip: Reduce backdrop blur while the user scrolls fast. Heavy blur during motion destroys perceived smoothness and increases GPU workload. Lowering blur dynamically keeps interfaces crisp while also improving performance. let t; const nav = document.querySelector(".navbar"); window.addEventListener("scroll", () => { nav. style.backdropFilter = "blur(8px)"; clearTimeout(t); t = setTimeout(() => { nav. style.backdropFilter = "blur(24px)"; }, 120); });

Design Engineering Tip: Reduce backdrop blur while the user scrolls fast. Heavy blur during motion destroys perceived smoothness and increases GPU workload. Lowering blur dynamically keeps interfaces crisp while also improving performance. let t; const nav = document.querySelector(".navbar"); window.addEventListener("scroll", () => { nav. style.backdropFilter = "blur(8px)"; clearTimeout(t); t = setTimeout(() => { nav. style.backdropFilter = "blur(24px)"; }, 120); });

86,826 Aufrufe

With Claude Fable 5 making software creation more accessible, interaction design is becoming an even bigger differentiator. So here is a Design Engineering Tip: Most interfaces wait for users to act. Better interfaces prepare for what users are about to do. This pattern is called Input Anticipation. By reacting to intent before an interaction happens, products feel faster, smarter, and easier to use. JS const box = document.querySelector(".input") const ring = document.querySelector(".focus-ring") addEventListener("pointermove", (e) => { const r = box.getBoundingClientRect() const dx = Math.max(r.left - e.clientX, 0, e.clientX - r.right) const dy = Math.max(r. top - e.clientY, 0, e.clientY - r.bottom) const distance = Math.hypot(dx, dy) const intent = Math.max(0, 1 - distance / 180) ** 2 ring. style.opacity = intent }) Save this for later.

With Claude Fable 5 making software creation more accessible, interaction design is becoming an even bigger differentiator. So here is a Design Engineering Tip: Most interfaces wait for users to act. Better interfaces prepare for what users are about to do. This pattern is called Input Anticipation. By reacting to intent before an interaction happens, products feel faster, smarter, and easier to use. JS const box = document.querySelector(".input") const ring = document.querySelector(".focus-ring") addEventListener("pointermove", (e) => { const r = box.getBoundingClientRect() const dx = Math.max(r.left - e.clientX, 0, e.clientX - r.right) const dy = Math.max(r. top - e.clientY, 0, e.clientY - r.bottom) const distance = Math.hypot(dx, dy) const intent = Math.max(0, 1 - distance / 180) ** 2 ring. style.opacity = intent }) Save this for later.

39,344 Aufrufe

Design Engineering Tip: If you’re using the same corner radius across your entire UI, try scaling it with the component size: 12px → XS (buttons, tags) 16px → S (cards, inputs) 24px → M (modals, panels) As components get larger, increasing the radius can help preserve the same visual softness and balance.

Design Engineering Tip: If you’re using the same corner radius across your entire UI, try scaling it with the component size: 12px → XS (buttons, tags) 16px → S (cards, inputs) 24px → M (modals, panels) As components get larger, increasing the radius can help preserve the same visual softness and balance.

28,199 Aufrufe

Kind of crazy that you can just use Codex or Claude and vibe code things like this into existence

Kind of crazy that you can just use Codex or Claude and vibe code things like this into existence

26,064 Aufrufe

Videos

Keine weiteren Inhalte verfügbar