Claude-skill-registry generic-react-ux-designer
Professional UI/UX design expertise for React applications. Covers design thinking, user psychology (Hick's/Fitts's/Jakob's Law), visual hierarchy, interaction patterns, accessibility, performance-driven design, and design critique. Use when designing features, improving UX, solving user problems, or conducting design reviews.
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/generic-react-ux-designer" ~/.claude/skills/majiayu000-claude-skill-registry-generic-react-ux-designer && rm -rf "$T"
manifest:
skills/data/generic-react-ux-designer/SKILL.mdsource content
React UX Designer
Professional UX expertise for React/TypeScript applications.
Extends: Generic UX Designer - Read base skill for design thinking process, user psychology, heuristic evaluation, and research methods.
React Interaction Patterns
Micro-interactions with Framer Motion
// Checkbox animation <motion.div animate={{ scale: checked ? 1 : 0 }} transition={{ type: "spring", stiffness: 500 }} > <Check className="w-4 h-4" /> </motion.div> // Button press feedback <motion.button whileTap={{ scale: 0.98 }} whileHover={{ scale: 1.02 }} transition={{ type: "spring", stiffness: 400 }} > Click me </motion.button> // Toast notification <motion.div initial={{ opacity: 0, y: 50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 50 }} > <Toast message={message} /> </motion.div>
Loading States
// Skeleton (preferred over spinners) <div className="animate-pulse space-y-4"> <div className="h-8 bg-slate-200 rounded w-3/4" /> <div className="h-4 bg-slate-200 rounded" /> </div> // Progress indicator for long operations <div className="relative w-full h-2 bg-slate-200 rounded"> <motion.div className="absolute h-full bg-primary rounded" initial={{ width: 0 }} animate={{ width: `${progress}%` }} /> </div>
Optimistic UI Pattern
const handleLike = async () => { // Update UI immediately setLiked(true); setCount((c) => c + 1); try { await api.like(id); } catch { // Rollback on error setLiked(false); setCount((c) => c - 1); toast.error("Failed to save"); } };
React Accessibility Patterns
Focus Management
// Modal focus trap function Modal({ isOpen, onClose, children }: ModalProps) { const modalRef = useRef<HTMLDivElement>(null); useEffect(() => { if (isOpen) { const firstFocusable = modalRef.current?.querySelector( "button, [href], input, select, textarea", ) as HTMLElement; firstFocusable?.focus(); } }, [isOpen]); // Trap focus within modal const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Tab") { const focusables = modalRef.current?.querySelectorAll( "button, [href], input, select, textarea", ); // Handle tab cycling... } if (e.key === "Escape") onClose(); }; return ( <div ref={modalRef} role="dialog" aria-modal="true" onKeyDown={handleKeyDown} > {children} </div> ); }
Keyboard Navigation
// Custom keyboard shortcut useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === "k") { e.preventDefault(); openCommandPalette(); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, []); // Arrow key navigation in list const handleKeyDown = (e: KeyboardEvent, index: number) => { switch (e.key) { case "ArrowDown": e.preventDefault(); focusItem(index + 1); break; case "ArrowUp": e.preventDefault(); focusItem(index - 1); break; } };
Motion Accessibility
// Respect prefers-reduced-motion const prefersReducedMotion = window.matchMedia( "(prefers-reduced-motion: reduce)", ).matches; <motion.div initial={{ opacity: 0, y: prefersReducedMotion ? 0 : 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: prefersReducedMotion ? 0 : 0.3 }} />;
Form UX Patterns
React Hook Form Integration
function ContactForm() { const { register, handleSubmit, formState: { errors }, } = useForm(); return ( <form onSubmit={handleSubmit(onSubmit)}> <div className="space-y-1"> <label htmlFor="email" className="text-sm font-medium"> Email </label> <input id="email" {...register("email", { required: "Email is required" })} aria-invalid={errors.email ? "true" : "false"} aria-describedby={errors.email ? "email-error" : undefined} className={cn("input", errors.email && "border-red-500")} /> {errors.email && ( <p id="email-error" className="text-sm text-red-500"> {errors.email.message} </p> )} </div> </form> ); }
Inline Validation
// Validate on blur, show on focus const [touched, setTouched] = useState(false); const [error, setError] = useState(""); <input onBlur={() => { setTouched(true); setError(validate(value)); }} onFocus={() => setError("")} // Clear while editing className={touched && error ? "border-red-500" : ""} />;
Modal/Dialog Patterns
Confirmation Dialog
function ConfirmDialog({ isOpen, onConfirm, onCancel, title, message }: Props) { return ( <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" > <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} role="alertdialog" aria-modal="true" aria-labelledby="dialog-title" aria-describedby="dialog-desc" className="bg-white rounded-xl p-6 max-w-md" > <h2 id="dialog-title" className="text-lg font-semibold"> {title} </h2> <p id="dialog-desc" className="mt-2 text-muted"> {message} </p> <div className="mt-4 flex gap-3 justify-end"> <button onClick={onCancel} className="btn-secondary"> Cancel </button> <button onClick={onConfirm} className="btn-primary"> Confirm </button> </div> </motion.div> </motion.div> ); }
Command Palette (⌘K Pattern)
function CommandPalette({ isOpen, onClose }: Props) { const [query, setQuery] = useState(""); const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { if (isOpen) inputRef.current?.focus(); }, [isOpen]); const filtered = useMemo( () => commands.filter((c) => c.label.toLowerCase().includes(query.toLowerCase()), ), [query], ); return ( <div role="dialog" aria-label="Command palette"> <input ref={inputRef} value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Type a command..." aria-autocomplete="list" /> <ul role="listbox"> {filtered.map((cmd) => ( <li key={cmd.id} role="option"> {cmd.label} </li> ))} </ul> </div> ); }
Empty & Error States
// Empty state with action function EmptyState({ title, description, action }: Props) { return ( <div className="text-center py-12"> <Icon className="mx-auto h-12 w-12 text-muted" /> <h3 className="mt-4 text-lg font-medium">{title}</h3> <p className="mt-2 text-muted">{description}</p> <button onClick={action.onClick} className="mt-4 btn-primary"> {action.label} </button> </div> ); } // Error state with retry function ErrorState({ error, onRetry }: Props) { return ( <div className="text-center py-12" role="alert"> <AlertCircle className="mx-auto h-12 w-12 text-red-500" /> <h3 className="mt-4 text-lg font-medium">Something went wrong</h3> <p className="mt-2 text-muted">{error.message}</p> <button onClick={onRetry} className="mt-4 btn-primary"> Try again </button> </div> ); }
React UX Checklist
Interaction Quality:
- Immediate feedback on user actions
- Loading states for async operations
- Optimistic updates where appropriate
- Smooth animations (60fps)
Accessibility:
- Keyboard navigation complete
- Focus management in modals
- Motion respects prefers-reduced-motion
- ARIA labels on interactive elements
Forms:
- Inline validation
- Clear error messages
- Smart defaults
- Progress indication for multi-step
See Also
- Generic UX Designer - Design thinking, psychology
- UX Principles - Research methods, heuristics
- Design Patterns - Visual patterns