design/motion-design/skills/gesture-motion-designer/SKILL.md
This skill should be used when the user wants to implement gesture-driven interactions or motion that responds to touch or pointer input. Trigger when the user mentions "swipe to dismiss", "drag to reorder", "pinch to zoom", "long press", "drag gesture", "touch event", "pan gesture", "flick or fling motion", "momentum-based animation", "spring on release", "pull to refresh", "swipeable card", "draggable element", or wants an interaction to "feel like iOS", "feel native", or "track my finger". Also trigger when the user asks how to handle gesture velocity, inertia, or dismiss thresholds.
npx skillsauth add harsh040506/claude-code-unified-skill-plugin-library gesture-motion-designerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Gesture interactions are complex to implement correctly: touch events, velocity tracking, threshold detection, momentum on release, and spring physics must all cooperate. The goal is interactions that track the user's input with zero lag during the gesture, then spring naturally to their final state on release.
The central rule: During active gesture, animate at 1:1 with pointer position — no easing, no delay. On release, continue at the gesture's final velocity into a spring. This is what makes touch feel native vs. "web-like."
| Gesture | Motion model | Output type |
|---------|-------------|-------------|
| Swipe-to-dismiss (card, notification) | Velocity threshold → dismiss or spring back | useSwipeToDismiss hook |
| Drag-to-reorder (list, kanban) | Drag 1:1, spring settle on drop | useDraggable + layout animation |
| Pull-to-refresh | Elastic resistance, threshold trigger | Elastic transform + callback |
| Pinch-to-zoom | Scale at midpoint, spring clamp on release | Gesture transform + boundary spring |
| Pan/scroll-linked | 1:1 position tracking | useMotionValue + useTransform |
| Long-press | Delay + scale feedback | Timer + spring scale |
Velocity matters at release. When a user flicks a card, the card should continue at the flick velocity and decelerate via spring — not restart from zero. Always capture velocity from the gesture end event.
Threshold decision logic:
| Condition | Action | |-----------|--------| | Displacement > 40% of element size | Dismiss/commit | | Velocity > 500px/s (regardless of displacement) | Dismiss/commit | | Neither threshold met | Spring back to origin |
Check velocity or displacement — not both required. Requiring both makes the gesture feel unresponsive.
Framer Motion — swipe-to-dismiss hook:
import { useMotionValue, useTransform, animate, PanInfo } from "framer-motion";
import { useState } from "react";
export function useSwipeToDismiss(
onDismiss: () => void,
threshold = 0.4
) {
const x = useMotionValue(0);
const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0]);
const rotate = useTransform(x, [-200, 200], [-15, 15]);
const [isDismissed, setIsDismissed] = useState(false);
function handleDragEnd(
event: MouseEvent | TouchEvent | PointerEvent,
info: PanInfo
) {
const width = (event.target as HTMLElement).offsetWidth;
const offset = Math.abs(info.offset.x);
const velocity = Math.abs(info.velocity.x);
if (offset > width * threshold || velocity > 500) {
const direction = info.offset.x > 0 ? 1 : -1;
setIsDismissed(true);
animate(x, direction * window.innerWidth, {
type: "spring",
stiffness: 400,
damping: 40,
velocity: info.velocity.x,
onComplete: onDismiss,
});
} else {
// Spring back — continues at gesture velocity, settles naturally
animate(x, 0, {
type: "spring",
stiffness: 500,
damping: 50,
velocity: info.velocity.x,
});
}
}
return { x, opacity, rotate, handleDragEnd, isDismissed };
}
Usage:
function SwipeableCard({ onDismiss, children }) {
const { x, opacity, rotate, handleDragEnd } = useSwipeToDismiss(onDismiss);
return (
<motion.div
style={{ x, opacity, rotate }}
drag="x"
dragConstraints={{ left: 0, right: 0 }} // constraints are elastic, not hard stops
dragElastic={0.7} // resistance when dragging past constraints
onDragEnd={handleDragEnd}
whileDrag={{ cursor: "grabbing" }}
>
{children}
</motion.div>
);
}
Framer Motion — drag-to-reorder:
<Reorder.Group axis="y" values={items} onReorder={setItems}>
{items.map((item) => (
<Reorder.Item key={item} value={item}>
{/* Framer handles drag + layout animation automatically */}
{item}
</Reorder.Item>
))}
</Reorder.Group>
Pull-to-refresh — elastic resistance:
const y = useMotionValue(0);
// Elastic resistance: input distance maps to dampened output
const clampedY = useTransform(y, (val) =>
val < 0 ? 0 : Math.min(val, 80 + (val - 80) * 0.3)
);
// Trigger refresh when past threshold
function handleDragEnd(_, info) {
if (info.offset.y > 80) {
onRefresh();
}
animate(y, 0, { type: "spring", stiffness: 400, damping: 40 });
}
Every gesture interaction must have a non-gesture equivalent:
aria-grabbed / aria-dropeffectGesture-only interactions fail for keyboard users, switch users, and assistive technology. Add role, aria-label, and keyboard handlers alongside every gesture.
For detailed native gesture patterns, React Native gesture handling, and iOS/Android physics parity, see:
references/gesture-patterns.md — Complete gesture type catalog, native feel guidelines, React Native equivalents, haptic feedback patternstesting
Performs quality control on single-cell RNA-seq data (.h5ad or .h5 files) using scverse best practices with MAD-based filtering and comprehensive visualizations. Use when users request QC analysis, filtering low-quality cells, assessing data quality, or following scverse/scanpy best practices for single-cell analysis.
tools
Deep learning for single-cell analysis using scvi-tools. This skill should be used when users need (1) data integration and batch correction with scVI/scANVI, (2) ATAC-seq analysis with PeakVI, (3) CITE-seq multi-modal analysis with totalVI, (4) multiome RNA+ATAC analysis with MultiVI, (5) spatial transcriptomics deconvolution with DestVI, (6) label transfer and reference mapping with scANVI/scArches, (7) RNA velocity with veloVI, or (8) any deep learning-based single-cell method. Triggers include mentions of scVI, scANVI, totalVI, PeakVI, MultiVI, DestVI, veloVI, sysVI, scArches, variational autoencoder, VAE, batch correction, data integration, multi-modal, CITE-seq, multiome, reference mapping, latent space.
testing
This skill should be used when scientists need help with research problem selection, project ideation, troubleshooting stuck projects, or strategic scientific decisions. Use this skill when users ask to pitch a new research idea, work through a project problem, evaluate project risks, plan research strategy, navigate decision trees, or get help choosing what scientific problem to work on. Typical requests include "I have an idea for a project", "I'm stuck on my research", "help me evaluate this project", "what should I work on", or "I need strategic advice about my research".
development
Run nf-core bioinformatics pipelines (rnaseq, sarek, atacseq) on sequencing data. Use when analyzing RNA-seq, WGS/WES, or ATAC-seq data—either local FASTQs or public datasets from GEO/SRA. Triggers on nf-core, Nextflow, FASTQ analysis, variant calling, gene expression, differential expression, GEO reanalysis, GSE/GSM/SRR accessions, or samplesheet creation.