better-ui
Design engineering principles for making interfaces feel polished. Use when building UI components, reviewing frontend code, implementing animations, hover states, shadows, borders, micro-interactions, enter/exit animations, or any visual detail work. Triggers on UI polish, design details, "make it feel better", "feels off", stagger animations, border radius, optical alignment, image outlines, box shadows.
Install
npx skills add https://github.com/jakubkrehel/skills --skill better-uiAnimations
Recipes for interruptible transitions, press feedback, first-render behavior, theme switches and the reduced-motion fallback. Staged entrances and exits live in enter-exit.md [blocked], and icon swaps in icon-transitions.md [blocked].
Interruptible animations
Scale on press
Static prop pattern
Where the button has no variant API to carry the opt-out, apply the scale class conditionally on a static prop:
Skip animation on page load
The icon recipe in icon-transitions.md [blocked] shows initial={false} used correctly. It suits icon swaps, toggles, tabs and segmented controls, anything with a default state on page load.
Setting it around a first-time entrance skips that entrance entirely. Check the component on a full page refresh before adding it.
Suppress transitions on theme switch
Inject a stylesheet that turns off every transition, force a style flush so the new colors commit while it applies, then remove it after the next frame:
The new theme resolves while the override is still in the document, so no transition starts. The nested requestAnimationFrame removes the override only after that paint.
That covers the OS-level change. An in-app toggle needs the same steps around its own flip: apply the override, change the theme, flush and remove. next-themes ships this as disableTransitionOnChange.
High-frequency motion
Reduced-motion fallback
The opacity fade runs for everyone, and movement, scale and blur join it only without the preference:
In Tailwind, prefix movement, scale and blur utilities with motion-safe:. In Motion, wrap the app in <MotionConfig reducedMotion="user">. It turns off transform and layout animations under the preference and keeps opacity. Blur still runs there, so branch on useReducedMotion() where a recipe animates filter.