stolinski/s-stack/design-engineering
- community
Checking that the SKILL.md file is still in the repository.
Use when designing, building, reviewing, or polishing user interfaces, motion, component behavior, interaction details, and product-feel across any frontend stack. Generalized from Emil Kowalski-style design engineering principles; framework-neutral, implementation-first.
Install
npx vskill@latest install stolinski/s-stack/design-engineeringSKILL.md
Design Engineering
Purpose
Use this skill to make interfaces feel intentional, fast, and physically believable — not merely functional. It is framework-neutral: apply it to HTML/CSS, Svelte, React, Vue, native apps, Web Components, canvas/WebGL, or design specs.
The goal is not decoration. The goal is product feel: the compounding effect of layout, motion, responsiveness, accessibility, and tiny interaction details that users rarely notice consciously but absolutely feel.
When to Use
Use for:
- UI polish passes
- Interaction design and component behavior
- Motion design, transitions, gestures, and microinteractions
- Reviewing frontend code for feel, responsiveness, and accessibility
- Turning a rough UI into something crisp and shippable
- Designing component APIs where behavior and styling must stay coherent
- Diagnosing why an interface feels slow, awkward, cheap, or janky
Do not use for:
- Pure backend work with no user-facing behavior
- Brand strategy without UI execution
- Large design-system governance unless the task includes concrete UI behavior
Core Philosophy
Taste is trained
Good taste is not vibes. It is pattern recognition built by studying great interfaces, reverse-engineering why they feel good, inspecting tiny details, and practicing until the defaults become sharp.
Do not stop at “it works.” Ask what the user feels in the first 100ms after they act.
Invisible details compound
The best UI details disappear. A popover opens from the trigger. A button visibly responds to pressure. A list reorders without losing spatial continuity. A destructive action feels serious without feeling dramatic.
Users may not name these details, but their nervous system does.
Beauty is leverage
Most software is good enough. Taste is a differentiator. Strong defaults, precise motion, and coherent interaction details make tools feel more trustworthy and more desirable.
Operating Loop
- Identify the user action.
- Identify the expected physical response.
- Decide whether motion helps or hurts.
- Make the first frame responsive.
- Preserve spatial continuity.
- Implement with the least fragile primitive.
- Test slowly, quickly, interrupted, repeated, keyboard-only, touch, and reduced-motion.
- Remove anything that feels ornamental under repetition.
Review Output Contract
When reviewing UI or code, prefer a compact table:
| Before | After | Why | |
|---|---|---|---|
transition: all 300ms | transition: transform 180ms var(--ease-out), opacity 180ms var(--ease-out) | Exact properties avoid accidental slow/janky animations | |
Element appears from scale(0) | Start at scale(.96) + opacity: 0 | Real objects do not appear from mathematical nothing | |
| Popover scales from center | Popover scales from trigger edge/origin | Motion should explain where the surface came from | |
| Keyboard command opens animated palette | Keyboard command opens instantly | Frequent keyboard actions must feel immediate |
If making changes, also report:
- Changed: files/areas touched
- Verified: exact command/browser/device checks run
- Remaining: only if something material is still unresolved
Animation Decision Framework
1. Should this animate?
Ask how often the user sees it.
| Frequency | Decision | |
|---|---|---|
| Hundreds of times/day: command palette, keyboard nav, shortcut-driven actions | No animation, or effectively instant | |
| Tens of times/day: hover, row focus, common navigation | Minimal feedback only | |
| Occasional: dialogs, drawers, toasts, settings panels | Standard motion is useful | |
| Rare: onboarding, empty-state celebration, marketing demo | Delight is allowed |
Rule: keyboard-initiated actions should generally not animate. Keyboard users are asking for speed.
2. What is the purpose?
Valid purposes:
- Feedback: confirms an input was received
- Spatial continuity: explains where something came from or went
- State indication: connects previous state to next state
- Jarring-change prevention: avoids a broken-looking jump
- Education: demonstrates behavior or hierarchy
- Delight: only when rare enough not to become tax
If the purpose is only “looks cool,” cut it unless the moment is rare and intentionally expressive.
3. What easing should it use?
Default decisions:
- Entering/exiting surfaces: strong
ease-out - Moving objects already on screen:
ease-in-out - Hover/color/soft property changes: standard
easeor tokenized curve - Constant looping motion:
linear - Drag/release, physics, interrupts: spring/inertia model when available
Useful CSS curves:
Avoid ease-in for most UI entrances. It withholds motion at the moment the user is watching, so it feels sluggish.
4. How fast should it be?
| Interaction | Duration | |
|---|---|---|
| Press feedback | 80–160ms | |
| Hover/focus feedback | 100–180ms | |
| Tooltip | 100–160ms, often no delay after first hover | |
| Popover/menu | 140–220ms | |
| Toast enter | 180–260ms | |
| Dialog/drawer | 200–320ms | |
| Page/route transition | 200–400ms, only if it preserves orientation | |
| Exit of temporary UI | Usually faster than enter |
Perceived performance matters more than raw duration. The first visual response should happen immediately, even if the full transition takes longer.
Motion Rules with Teeth
Never animate all
Bad:
Good:
Prefer transform and opacity
Animate transform and opacity by default. Treat layout properties (height, width, top, left, margin) as expensive and suspicious unless the element count is small and you have tested it.
If animating layout is necessary, isolate the damage:
- Limit the animated subtree
- Use containment where appropriate
- Avoid animating large lists
- Test under CPU throttling or real low-end devices
Do not appear from scale(0)
Bad:
Good:
Objects should feel like they enter the world, not spawn from zero dimension.
Origin matters
- Popovers, dropdowns, menus: scale/slide from the trigger or attachment edge.
- Modals: stay centered; do not pretend they came from a random button unless the design is explicitly morphing.
- Tooltips: small offset from anchor; fast and calm.
- Drawers/sheets: move from their physical screen edge.
Make press states physical
Buttons and pressable controls need a visible response.
Good patterns:
For dense professional tools, reduce the scale change: .99 or a color/brightness response can be enough.
Prefer interruptible motion
Users change their mind mid-transition. UI should survive interruption.
Prefer:
- CSS transitions for simple state changes
- Web Animations API for controllable imperative animation
- Spring/inertia libraries for gestures
- Timeline libraries only when sequencing is truly needed
Avoid brittle keyframe choreography for basic UI state changes.
Use @starting-style for enter transitions when supported
For native CSS enter animations without mounting hacks:
Use progressive enhancement. Do not make the component depend on unsupported behavior without a fallback.
Component Design Principles
Components own behavior, not just pixels
A polished component defines:
- States: idle, hover, focus, active, loading, disabled, selected, invalid
- Input modes: mouse, touch, keyboard, screen reader
- Timing: how it enters, exits, interrupts, and repeats
- Layout behavior: overflow, wrapping, density, container constraints
- Accessibility: roles, names, focus movement, reduced motion
A component that only defines colors and border radius is not done.
Design APIs around intent
Prefer component props/options that encode product intent over raw styling knobs.
Better:
Worse:
Expose escape hatches only when real use cases demand them.
Empty, loading, and error states are part of the component
Do not bolt them on later. A component should know how it behaves when:
- Data has not loaded
- Data is empty
- Data failed
- Data is stale while refetching
- The user lacks permission
- The viewport is cramped
Focus is a design material
Keyboard focus should be visible, tasteful, and predictable. Never remove outlines without replacing them. Focus movement must match user intent.
Checklist:
- Tab order follows visual/task order
- Escape closes temporary surfaces
- Focus returns to the trigger after dismissal
- Dialogs trap focus only while modal
- Roving focus is used for composite widgets when appropriate
Gestures and Drag Interactions
Dismiss by intent, not distance alone
Use a combination of distance and velocity. A quick confident flick should dismiss even if distance is short; a slow accidental drag should recover.
Boundaries should damp, not brick-wall
When dragging past a limit, apply resistance/friction instead of hard stopping. Hard stops feel cheap and broken.
Capture the pointer
For web drag interactions, use pointer events and pointer capture so dragging remains coherent even if the pointer leaves the element.
Guard multi-touch if the gesture is single-pointer.
Release must settle somewhere believable
On release, animate to the nearest intentional state: closed, open, dismissed, snapped, reordered. Do not leave fractional awkward states unless the UI is truly continuous.
Layout and Visual Polish
Alignment beats decoration
Before adding effects, fix:
- Uneven spacing
- Optical alignment
- Baseline rhythm
- Hit target size
- Text contrast
- Icon/text balance
- Ragged wrapping in common widths
Use hierarchy before chrome
If a screen feels confusing, do not add borders everywhere. Clarify hierarchy with grouping, spacing, type scale, and content order first.
Defaults should be opinionated
A high-quality component should look good with minimal configuration. If every usage needs five props/classes to look acceptable, the abstraction is weak.
Responsive behavior is not just breakpoints
Check:
- Long labels
- Narrow containers
- Tall content
- Touch targets
- Safe areas / notches
- Reduced pointer precision
- Text zoom
- OS/browser font rendering differences
Accessibility and User Preferences
Reduced motion is not optional
Implement prefers-reduced-motion. Reduced does not always mean zero; it means remove vestibular motion and long transitions.
Prefer component-scoped reductions when possible so you do not destroy useful non-motion affordances globally.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/design-engineering/SKILL.md
Popularity
- Repository stars
- 59
- Repository forks
- 2
- 7-day trend score
- 20
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/stolinski/s-stack/design-engineering)