home / skills / fusengine / agents / interactive-states
This skill helps implement and validate interactive button and input states using motion, focus, and loading cues for accessible UI.
npx playbooks add skill fusengine/agents --skill interactive-statesReview the files below or copy the command above to add this skill to your agents.
---
name: interactive-states
description: Use when implementing button states, form field states, or interactive feedback. Covers hover, active, focus, disabled, loading states.
versions:
framer-motion: "11"
user-invocable: true
allowed-tools: Read, Write, Edit, Glob, Grep
related-skills: adding-animations, generating-components
---
# Interactive States
## Agent Workflow (MANDATORY)
Before implementation, use `TeamCreate` to spawn 3 agents:
1. **fuse-ai-pilot:explore-codebase** - Check existing state patterns
2. **fuse-ai-pilot:research-expert** - Framer Motion state animations
After: Run **fuse-ai-pilot:sniper** for validation.
---
## Overview
| State | Visual | Timing |
|-------|--------|--------|
| Default | Base appearance | - |
| Hover | Scale/color change | 50-100ms |
| Pressed | Scale down | 100-150ms |
| Focus | Ring outline | instant |
| Disabled | Opacity 50% | - |
| Loading | Spinner | - |
---
## Quick Reference
### Button States
```tsx
<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
transition={{ duration: 0.1 }}
className={cn(
"px-4 py-2 rounded-lg bg-primary",
"focus:outline-none focus-visible:ring-2",
"disabled:opacity-50 disabled:cursor-not-allowed",
)}
>
{isLoading ? <Spinner /> : children}
</motion.button>
```
### Card Hover
```tsx
<motion.div
whileHover={{
y: -4,
boxShadow: "0 25px 50px -12px rgb(0 0 0 / 0.15)",
}}
transition={{ duration: 0.2 }}
>
```
### Input States
```tsx
const inputStates = {
default: "border-border bg-surface",
focus: "border-primary ring-2 ring-primary/20",
valid: "border-success bg-success/5",
error: "border-destructive bg-destructive/5",
disabled: "border-muted bg-muted/50 cursor-not-allowed",
};
```
### Focus Visible
```tsx
className="focus:outline-none focus-visible:ring-2 focus-visible:ring-primary"
```
### Loading State
```tsx
<button disabled={isLoading}>
{isLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
"Submit"
)}
</button>
```
---
## Validation Checklist
```
[ ] All 5 states defined (default, hover, active, focus, disabled)
[ ] Loading state with spinner
[ ] Hover timing 50-100ms
[ ] Focus visible for keyboard users
[ ] Disabled prevents interaction
```
---
## Best Practices
### DO
- Use Framer Motion for hover/tap
- Visible focus for accessibility
- Spinner for loading states
- Consistent timing across app
### DON'T
- Skip focus states
- Forget loading feedback
- Use slow animations (>200ms)
- Remove outline without replacement
This skill helps implement consistent interactive states for UI components such as buttons, inputs, and cards. It defines visual behavior for hover, active/pressed, focus, disabled, and loading states with recommended timing and accessibility considerations. The guidance includes Framer Motion patterns, CSS utility examples, and a validation checklist to ensure coverage.
The skill inspects component implementations and applies state patterns: motion-driven hover and tap animations, visible focus rings for keyboard users, opacity and cursor changes for disabled elements, and spinners for loading. It provides concrete code snippets and timing guidelines (50–150ms ranges) and validates presence of all required states and loading feedback. Use the provided input and button patterns as drop-in examples and adapt tokens for your design system.
What timing should I use for hover and press animations?
Use 50–100ms for hover transitions and 100–150ms for pressed/active feedback to keep interactions snappy.
How should loading states be handled?
Render a compact spinner, set disabled on the control, and ensure focus and aria attributes reflect the busy state so screen readers are informed.