Claude-skill-registry interactive-states
Interactive states for UI elements - hover, active, focus, disabled, loading. Use when implementing button states, form field states, or interactive feedback.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/interactive-states" ~/.claude/skills/majiayu000-claude-skill-registry-interactive-states && rm -rf "$T"
manifest:
skills/data/interactive-states/SKILL.mdsource content
Interactive States
Complete state system for interactive elements.
Agent Workflow (MANDATORY)
Before implementation:
- fuse-ai-pilot:explore-codebase - Check existing state patterns
- fuse-ai-pilot:research-expert - Framer Motion state animations
After: Run fuse-ai-pilot:sniper for validation.
State Flow
Default → Hover → Pressed/Active → Focus → Disabled → Loading
Button States
import { motion } from "framer-motion"; export function Button({ children, disabled, isLoading }) { return ( <motion.button // Hover state (50-100ms) whileHover={{ scale: 1.02 }} // Pressed state (100-150ms) whileTap={{ scale: 0.98 }} transition={{ duration: 0.1 }} disabled={disabled || isLoading} className={cn( // Default "px-4 py-2 rounded-lg bg-primary text-primary-foreground", "font-medium transition-colors", // Focus visible "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50", // Disabled "disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none", )} > {isLoading ? <Spinner className="h-4 w-4 animate-spin" /> : children} </motion.button> ); }
State Timing Guide
| State | Duration | Easing |
|---|---|---|
| Hover in | 50-100ms | ease-out |
| Hover out | 150ms | ease-in |
| Press | 100-150ms | ease-out |
| Focus | instant | - |
| Loading | - | linear (spin) |
Card Hover States
<motion.div className="bg-surface rounded-2xl p-6 shadow-md transition-shadow" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} whileHover={{ y: -4, boxShadow: "0 25px 50px -12px rgb(0 0 0 / 0.15)", }} transition={{ duration: 0.2 }} > {children} </motion.div>
Input Field States
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", }; <input className={cn( "w-full px-4 py-3 rounded-lg border transition-all", "focus:outline-none", inputStates[state] )} />
Focus States (Accessibility)
/* Visible focus ring */ className="focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2" /* Focus within (for groups) */ className="focus-within:ring-2 focus-within:ring-primary"
Loading States
/* Spinner button */ <button disabled={isLoading}> {isLoading ? ( <Loader2 className="h-4 w-4 animate-spin" /> ) : ( "Submit" )} </button> /* Skeleton loading */ <div className="animate-pulse"> <div className="h-4 bg-muted rounded w-3/4" /> <div className="h-4 bg-muted rounded w-1/2 mt-2" /> </div> /* Progress state */ <motion.div className="h-1 bg-primary rounded-full" initial={{ width: 0 }} animate={{ width: `${progress}%` }} />
Interactive Feedback Patterns
/* Ripple effect on click */ const [ripple, setRipple] = useState(null); <button onClick={(e) => { const rect = e.currentTarget.getBoundingClientRect(); setRipple({ x: e.clientX - rect.left, y: e.clientY - rect.top }); }} > {ripple && ( <motion.span className="absolute bg-white/30 rounded-full" initial={{ width: 0, height: 0 }} animate={{ width: 100, height: 100, opacity: 0 }} style={{ left: ripple.x, top: ripple.y }} /> )} </button> /* Checkbox toggle */ <motion.div animate={{ scale: checked ? 1 : 0 }} transition={{ type: "spring", stiffness: 500 }} > <Check className="h-4 w-4" /> </motion.div>
State Composition with CVA
const buttonVariants = cva("...", { variants: { state: { default: "", loading: "opacity-80 pointer-events-none", success: "bg-success text-success-foreground", error: "bg-destructive text-destructive-foreground", }, }, });
Validation
[ ] All 5 states defined (default, hover, active, focus, disabled) [ ] Loading state with spinner/skeleton [ ] Hover timing 50-100ms [ ] Focus visible for keyboard users [ ] Disabled prevents all interaction [ ] Motion respects prefers-reduced-motion
References
- Button states detail../../references/buttons-guide.md
- Form field states../../references/forms-guide.md
- Animation timings../../references/motion-patterns.md