### Natural Element Entrance Animations with CSS Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Demonstrates how to animate element entrances naturally by avoiding `scale(0)` and starting from a higher scale with opacity. The 'Good' example shows a preferred method for smoother entry. ```css /* Bad */ .entering { transform: scale(0); } /* Good */ .entering { transform: scale(0.95); opacity: 0; } ``` -------------------------------- ### Natural Element Entry Animations in CSS Source: https://context7.com/emilkowalski/skill/llms.txt Demonstrates natural-feeling element entry animations by avoiding scale(0) and using scale(0.95) with opacity. Includes a modern CSS example using @starting-style for toast notifications. ```css /* Bad - feels unnatural */ .entering-bad { transform: scale(0); } /* Good - feels like a real object */ .entering { transform: scale(0.95); opacity: 0; } /* Modern CSS entry animation with @starting-style */ .toast { opacity: 1; transform: translateY(0); transition: opacity 400ms ease, transform 400ms ease; @starting-style { opacity: 0; transform: translateY(100%); } } ``` -------------------------------- ### Web Animations API (WAAPI) Example Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Demonstrates using the Web Animations API (WAAPI) for programmatic CSS animations. This approach offers JavaScript control with CSS performance benefits, including hardware acceleration and interruptibility, without requiring external libraries. ```js element.animate([ { clipPath: 'inset(0 0 100% 0)' }, { clipPath: 'inset(0 0 0 0)' }, ], { duration: 1000, fill: 'forwards', easing: 'cubic-bezier(0.77, 0, 0.175, 1)', }); ``` -------------------------------- ### Asymmetric Enter/Exit Timing CSS Transitions Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Demonstrates asymmetric transition timing for enter and exit animations using CSS. The example shows a slow, deliberate press animation and a snappy release animation, a common pattern for improving user experience. ```css /* Release: fast */ .overlay { transition: clip-path 200ms ease-out; } /* Press: slow and deliberate */ .button:active .overlay { transition: clip-path 2s linear; } ``` -------------------------------- ### Accessibility: prefers-reduced-motion React Hook Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md A React example demonstrating how to conditionally apply animations based on the user's 'prefers-reduced-motion' setting using a custom hook. ```jsx const shouldReduceMotion = useReducedMotion(); const closedX = shouldReduceMotion ? 0 : '-100%'; ``` -------------------------------- ### Origin-Aware Popover Scaling with CSS Variables Source: https://context7.com/emilkowalski/skill/llms.txt Ensures popovers scale from their trigger point rather than the center by utilizing CSS variables for transform-origin. Provides examples for Radix UI, Base UI, and a modal exception. ```css /* Radix UI popover */ .popover { transform-origin: var(--radix-popover-content-transform-origin); } /* Base UI popover */ .popover { transform-origin: var(--transform-origin); } /* Exception: Modals stay centered (not anchored to a trigger) */ .modal { transform-origin: center; } ``` -------------------------------- ### Spring Animations with Framer Motion in React Source: https://context7.com/emilkowalski/skill/llms.txt Utilizes Framer Motion's `useSpring` hook in React to create natural, physics-based animations with momentum, suitable for drag interactions and gestures. Includes examples of both Apple-style and traditional physics spring configurations. ```jsx import { useSpring } from 'framer-motion'; function MouseTracker() { const [mouseX, setMouseX] = useState(0); // Without spring: feels artificial, instant // const rotation = mouseX * 0.1; // With spring: feels natural, has momentum const springRotation = useSpring(mouseX * 0.1, { stiffness: 100, damping: 10, }); return ( setMouseX(e.clientX - window.innerWidth / 2)} /> ); } // Apple-style spring configuration (easier to reason about) const appleSpring = { type: "spring", duration: 0.5, bounce: 0.2 }; // Traditional physics spring (more control) const physicsSpring = { type: "spring", mass: 1, stiffness: 100, damping: 10 }; ``` -------------------------------- ### JavaScript for Pointer Capture and Multi-Touch Protection Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Provides JavaScript snippets for handling drag interactions. One snippet demonstrates preventing multiple touch points from interfering with a drag, ensuring only the initial touch initiates and continues the drag. Another snippet outlines the start of a drag interaction. ```javascript function onPress() { if (isDragging) return; // Start drag... } ``` -------------------------------- ### Custom CSS Easing Curves for UI Animations Source: https://context7.com/emilkowalski/skill/llms.txt Defines custom cubic-bezier easing curves for more professional and polished UI animations. These curves offer stronger easing than built-in options and are demonstrated with example CSS for dropdowns. ```css :root { /* Strong ease-out for UI interactions (enter/exit animations) */ --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* Strong ease-in-out for on-screen movement */ --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* iOS-like drawer curve (from Ionic Framework) */ --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); } /* Example: Dropdown animation using custom easing */ .dropdown { opacity: 0; transform: scale(0.95); transform-origin: var(--radix-dropdown-menu-content-transform-origin); transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); } .dropdown[data-state="open"] { opacity: 1; transform: scale(1); } ``` -------------------------------- ### JavaScript for Momentum-Based Dismissal Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Implements momentum-based dismissal logic in JavaScript. It calculates the velocity of a swipe gesture and dismisses the element if the velocity exceeds a threshold, allowing for quick dismissals even if the swipe distance is short. Requires tracking drag start time and distance. ```javascript const timeTaken = new Date().getTime() - dragStartTime.current.getTime(); const velocity = Math.abs(swipeAmount) / timeTaken; if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) { dismiss(); } ``` -------------------------------- ### Configure Spring Physics Parameters Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Springs can be configured using either duration-based parameters for easier reasoning or traditional physics parameters for granular control over mass, stiffness, and damping. ```javascript // Apple's approach (recommended — easier to reason about) { type: "spring", duration: 0.5, bounce: 0.2 } // Traditional physics (more control) { type: "spring", mass: 1, stiffness: 100, damping: 10 } ``` -------------------------------- ### Optimize Framer Motion for Hardware Acceleration Source: https://context7.com/emilkowalski/skill/llms.txt Demonstrates how to use full transform strings instead of shorthand properties to ensure smooth animations. Also contrasts direct element style manipulation versus CSS variable updates. ```jsx element.style.setProperty('--swipe-amount', `${distance}px`); element.style.transform = `translateY(${distance}px)`; ``` -------------------------------- ### CSS Transitions vs Keyframes for UI Animations Source: https://context7.com/emilkowalski/skill/llms.txt Demonstrates the use of CSS transitions for interruptible UI elements like toasts and toggles, and keyframes for non-interruptible, predetermined animations. It highlights how to apply these for dynamic UI updates and avoid issues with rapidly triggered elements. ```css .toast { transition: transform 400ms ease; } @keyframes slideIn { from { transform: translateY(100%); } to { transform: translateY(0); } } .drawer-hidden { transform: translateY(100%); /* Moves by own height */ } .toast-enter { transform: translateY(-100%); /* Enters from above */ } ``` -------------------------------- ### Interruptible UI Animations with CSS Transitions vs. Keyframes Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Compares CSS transitions and keyframes for UI animations, recommending transitions for interruptible interactions like adding toasts or toggling states due to their ability to be retargeted. ```css /* Interruptible - good for UI */ .toast { transition: transform 400ms ease; } /* Not interruptible - avoid for dynamic UI */ @keyframes slideIn { from { transform: translateY(100%); } to { transform: translateY(0); } } ``` -------------------------------- ### Percentage-Based translateY for Dynamic Sizing Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Demonstrates the use of percentage values in `translateY()` to move elements by their own height or width, ensuring adaptability regardless of actual dimensions. Useful for components like drawers and toasts. ```css /* Works regardless of drawer height */ .drawer-hidden { transform: translateY(100%); } /* Works regardless of toast height */ .toast-enter { transform: translateY(-100%); } ``` -------------------------------- ### Modern CSS Enter Animations with @starting-style Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Utilizes the CSS `@starting-style` rule for animating element entry without JavaScript, providing a cleaner and more declarative approach compared to legacy patterns. ```css .toast { opacity: 1; transform: translateY(0); transition: opacity 400ms ease, transform 400ms ease; @starting-style { opacity: 0; transform: translateY(100%); } } ``` -------------------------------- ### Responsive Button Feedback with CSS Transitions Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Applies a subtle scale effect on button click to provide instant user feedback. Uses CSS transitions for smooth animation. Works for any pressable element. ```css .button { transition: transform 160ms ease-out; } .button:active { transform: scale(0.97); } ``` -------------------------------- ### Framer Motion Hardware Acceleration Comparison Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Compares Framer Motion's non-hardware-accelerated shorthand properties with hardware-accelerated transform strings. The shorthand properties use requestAnimationFrame on the main thread, which can lead to dropped frames under load, while the transform string leverages hardware acceleration for smoother animations. ```jsx ``` ```jsx ``` -------------------------------- ### UI Review Markdown Table Format Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md The mandatory format for presenting UI code improvements. It requires a markdown table with 'Before', 'After', and 'Why' columns to ensure clear communication of design changes. ```markdown | Before | After | Why | | --- | --- | --- | | `transition: all 300ms` | `transition: transform 200ms ease-out` | Specify exact properties; avoid `all` | | `transform: scale(0)` | `transform: scale(0.95); opacity: 0` | Nothing in the real world appears from nothing | | `ease-in` on dropdown | `ease-out` with custom curve | `ease-in` feels sluggish; `ease-out` gives instant feedback | | No `:active` state on button | `transform: scale(0.97)` on `:active` | Buttons must feel responsive to press | | `transform-origin: center` on popover | `transform-origin: var(--radix-popover-content-transform-origin)` | Popovers should scale from their trigger | ``` -------------------------------- ### CSS Button Press Feedback with Scaling Source: https://context7.com/emilkowalski/skill/llms.txt Implements button press feedback using CSS by scaling the button down slightly on active state. This provides immediate visual confirmation to the user. It also includes styles for transition effects on button content. ```css .button { transition: transform 160ms ease-out; } .button:active { transform: scale(0.97); } /* Combined with blur for state transitions */ .button-content { transition: filter 200ms ease, opacity 200ms ease; } .button-content.transitioning { filter: blur(2px); opacity: 0.7; } ``` -------------------------------- ### 3D Transforms for Depth with CSS Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Demonstrates creating 3D effects using CSS 3D transforms and `preserve-3d`. Enables complex animations like orbiting and coin flips without JavaScript. Requires `transform-style: preserve-3d` on a wrapper element. ```css .wrapper { transform-style: preserve-3d; } @keyframes orbit { from { transform: translate(-50%, -50%) rotateY(0deg) translateZ(72px) rotateY(360deg); } to { transform: translate(-50%, -50%) rotateY(360deg) translateZ(72px) rotateY(0deg); } } ``` -------------------------------- ### Instant Tooltip Hover Animation in CSS Source: https://context7.com/emilkowalski/skill/llms.txt Configures tooltips to have an initial delay but appear instantly on subsequent hovers once one is active. Achieved by conditionally setting transition duration to 0ms. ```css .tooltip { transition: transform 125ms ease-out, opacity 125ms ease-out; transform-origin: var(--transform-origin); } .tooltip[data-starting-style], .tooltip[data-ending-style] { opacity: 0; transform: scale(0.97); } /* Skip animation on subsequent tooltips when one is already open */ .tooltip[data-instant] { transition-duration: 0ms; } ``` -------------------------------- ### Tooltip Animation Control with CSS Transitions Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Manages tooltip animations, including a delay for initial appearance and instant display on subsequent hovers. Uses CSS transitions and data attributes to control timing. ```css .tooltip { transition: transform 125ms ease-out, opacity 125ms ease-out; transform-origin: var(--transform-origin); } .tooltip[data-starting-style], .tooltip[data-ending-style] { opacity: 0; transform: scale(0.97); } /* Skip animation on subsequent tooltips */ .tooltip[data-instant] { transition-duration: 0ms; } ``` -------------------------------- ### Legacy JavaScript Enter Animation Fallback Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Provides a fallback pattern using React's `useEffect` hook for animating element entry when browser support for `@starting-style` is not available. ```jsx // Legacy pattern (still works everywhere) useEffect(() => { setMounted(true); }, []); //
``` -------------------------------- ### Implement Spring Animations with Framer Motion Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Use spring physics to create natural, momentum-based animations for decorative interactions. The useSpring hook interpolates values to avoid artificial, instant updates. ```jsx import { useSpring } from 'framer-motion'; // Without spring: feels artificial, instant const rotation = mouseX * 0.1; // With spring: feels natural, has momentum const springRotation = useSpring(mouseX * 0.1, { stiffness: 100, damping: 10, }); ``` -------------------------------- ### Perform Animations with Web Animations API (WAAPI) Source: https://context7.com/emilkowalski/skill/llms.txt Provides programmatic control over animations using the browser's native hardware-accelerated API. Useful for complex sequences like staggered list reveals without external libraries. ```javascript element.animate( [ { clipPath: 'inset(0 0 100% 0)' }, { clipPath: 'inset(0 0 0 0)' } ], { duration: 1000, fill: 'forwards', easing: 'cubic-bezier(0.77, 0, 0.175, 1)', } ); document.querySelectorAll('.item').forEach((item, index) => { item.animate( [ { opacity: 0, transform: 'translateY(8px)' }, { opacity: 1, transform: 'translateY(0)' } ], { duration: 300, delay: index * 50, fill: 'forwards', easing: 'cubic-bezier(0.23, 1, 0.32, 1)', } ); }); ``` -------------------------------- ### Enhancing Transitions with CSS Blur and Scale Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Combines `filter: blur()` with scale-on-press effects for smoother crossfade transitions between states, masking imperfections and creating a more natural visual flow. Blur should be kept subtle. ```css .button { transition: transform 160ms ease-out; } .button:active { transform: scale(0.97); } .button-content { transition: filter 200ms ease, opacity 200ms ease; } .button-content.transitioning { filter: blur(2px); opacity: 0.7; } ``` -------------------------------- ### CSS 3D Transforms for Depth Effects Source: https://context7.com/emilkowalski/skill/llms.txt Illustrates how to implement 3D transform effects using rotateX(), rotateY(), and transform-style: preserve-3d. This is useful for creating depth, orbiting animations, card flips, and spatial interfaces, enhancing user experience with visual richness. ```css .wrapper { transform-style: preserve-3d; perspective: 1000px; } .card { transition: transform 600ms var(--ease-in-out); transform-style: preserve-3d; } .card:hover { transform: rotateY(10deg) rotateX(5deg); } @keyframes orbit { from { transform: translate(-50%, -50%) rotateY(0deg) translateZ(72px) rotateY(360deg); } to { transform: translate(-50%, -50%) rotateY(360deg) translateZ(72px) rotateY(0deg); } } ``` -------------------------------- ### Implement Staggered CSS Animations Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md This snippet demonstrates how to create a cascading entrance effect using CSS animation-delay on nth-child elements. It uses a fade-in and translateY transform to create a smooth, natural appearance for lists or grouped items. ```css .item { opacity: 0; transform: translateY(8px); animation: fadeIn 300ms ease-out forwards; } .item:nth-child(1) { animation-delay: 0ms; } .item:nth-child(2) { animation-delay: 50ms; } .item:nth-child(3) { animation-delay: 100ms; } .item:nth-child(4) { animation-delay: 150ms; } @keyframes fadeIn { to { opacity: 1; transform: translateY(0); } } ``` -------------------------------- ### Create Staggered CSS Animations Source: https://context7.com/emilkowalski/skill/llms.txt Uses CSS nth-child selectors and animation-delay to create cascading entry effects for lists of items. ```css .item { opacity: 0; transform: translateY(8px); animation: fadeIn 300ms ease-out forwards; } .item:nth-child(1) { animation-delay: 0ms; } .item:nth-child(2) { animation-delay: 50ms; } .item:nth-child(3) { animation-delay: 100ms; } .item:nth-child(4) { animation-delay: 150ms; } @keyframes fadeIn { to { opacity: 1; transform: translateY(0); } } ``` -------------------------------- ### JavaScript for CSS Variable vs. Transform Performance Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Illustrates a performance optimization in JavaScript. It shows the difference between updating a CSS variable on a parent element (which can trigger expensive recalculations for all children) and directly updating the `transform` property of an element (which is more performant as it only affects the target element). ```javascript // Bad: triggers recalc on all children element.style.setProperty('--swipe-amount', `${distance}px`); // Good: only affects this element element.style.transform = `translateY(${distance}px)`; ``` -------------------------------- ### Restrict Hover States to Pointer Devices Source: https://context7.com/emilkowalski/skill/llms.txt Uses media queries to ensure hover effects only trigger on devices with precise pointing capabilities, preventing unwanted behavior on touch screens. ```css @media (hover: hover) and (pointer: fine) { .card:hover { transform: scale(1.02); box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); } .link:hover { color: var(--accent); } } ``` -------------------------------- ### Implement Clip-Path Reveal Animations Source: https://context7.com/emilkowalski/skill/llms.txt Uses the CSS clip-path property to create reveal effects, image transitions, and comparison sliders. The inset shape defines rectangular clipping regions that can be animated via transitions. ```css .overlay { clip-path: inset(0 100% 0 0); transition: clip-path 200ms ease-out; } .button:active .overlay { clip-path: inset(0 0 0 0); transition: clip-path 2s linear; } .image-reveal { clip-path: inset(0 0 100% 0); transition: clip-path 800ms var(--ease-in-out); } .image-reveal.visible { clip-path: inset(0 0 0 0); } .comparison-top { clip-path: inset(0 50% 0 0); } ``` -------------------------------- ### Popover Transform Origin for Natural Scaling Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Sets the `transform-origin` for popovers to scale from their trigger point, not the center, for a more natural feel. Modals are an exception and should retain center origin. ```css /* Radix UI */ .popover { transform-origin: var(--radix-popover-content-transform-origin); } /* Base UI */ .popover { transform-origin: var(--transform-origin); } ``` -------------------------------- ### CSS Clip-Path for Animations and Reveals Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Utilizes the `clip-path` CSS property for various animation effects, including revealing content, creating tabs with color transitions, hold-to-delete patterns, image reveals on scroll, and comparison sliders. The `inset()` function is key for defining clipping regions. ```css /* Fully hidden from right */ .hidden { clip-path: inset(0 100% 0 0); } /* Fully visible */ .visible { clip-path: inset(0 0 0 0); } /* Reveal from left to right */ .overlay { clip-path: inset(0 100% 0 0); transition: clip-path 200ms ease-out; } .button:active .overlay { clip-path: inset(0 0 0 0); transition: clip-path 2s linear; } ``` -------------------------------- ### Touch Device Hover State Media Query Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md A CSS media query to conditionally apply hover effects only on devices that support fine pointer hovering, preventing unintended hover states on touch devices where taps can trigger hover events. ```css @media (hover: hover) and (pointer: fine) { .element:hover { transform: scale(1.05); } } ``` -------------------------------- ### Implement Reduced Motion Accessibility Source: https://context7.com/emilkowalski/skill/llms.txt Respects user system preferences for reduced motion by disabling transform-based animations while maintaining opacity transitions. Includes both CSS media query and React hook implementations. ```css @media (prefers-reduced-motion: reduce) { .element { animation: fade 0.2s ease; } .drawer { transition: opacity 200ms ease; } } ``` ```jsx import { useReducedMotion } from 'framer-motion'; function Drawer({ isOpen }) { const shouldReduceMotion = useReducedMotion(); const closedX = shouldReduceMotion ? 0 : '-100%'; return ( ); } ``` -------------------------------- ### Handle Momentum-Based Gesture Dismissal Source: https://context7.com/emilkowalski/skill/llms.txt Calculates swipe velocity to dismiss elements based on flick speed rather than just distance. Includes logic to reset position if thresholds are not met and prevents multi-touch interference. ```javascript const SWIPE_THRESHOLD = 50; const VELOCITY_THRESHOLD = 0.11; function handleDragEnd(swipeAmount, dragStartTime) { const timeTaken = new Date().getTime() - dragStartTime.current.getTime(); const velocity = Math.abs(swipeAmount) / timeTaken; if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > VELOCITY_THRESHOLD) { dismiss(); } else { resetPosition(); } } function onPress() { if (isDragging) return; } ``` -------------------------------- ### Define Custom CSS Easing Curves Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Standard CSS easing functions are often too weak for modern UI. These custom cubic-bezier curves provide stronger, more intentional movement for UI interactions and on-screen transitions. ```css /* Strong ease-out for UI interactions */ --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* Strong ease-in-out for on-screen movement */ --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* iOS-like drawer curve (from Ionic Framework) */ --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); ``` -------------------------------- ### Accessibility: prefers-reduced-motion CSS Source: https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md Applies CSS animations with reduced motion preferences. This media query ensures that animations are gentler or disabled for users who have requested reduced motion, improving accessibility and preventing motion sickness. ```css @media (prefers-reduced-motion: reduce) { .element { animation: fade 0.2s ease; /* No transform-based motion */ } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.