Back to Dictionary
Action Feedback
●●●Requires Setup
AdvancedSwipe Gesture Hint
A subtle, bouncing horizontal nudge on a list item indicating that it can be swiped to reveal hidden actions (like delete or archive).
Use
Mobile-first list views
Avoid
Desktop applications without touch support
Safer Alternative
No safer default listed.
Risk Level
Low risk
Live Demo
What It Is
A subtle, bouncing horizontal nudge on a list item indicating that it can be swiped to reveal hidden actions (like delete or archive).
✓When to Use
- Mobile-first list views
- Email or message inboxes
- Task lists
✕When NOT to Use
- Desktop applications without touch support
- Items where a visible actions menu (e.g., "...") is present and sufficient
Configuration Tips
- 01Play the hint animation only once upon first entering the view
- 02Move the item slightly (e.g., 20px) to reveal the background action color momentarily
You've Seen It In
Apple MailGmailTodoist
AI Implementation Prompts
Move from a fast scaffold to production details, then tune timing and edge states.
Make the list item wiggle to the left briefly to show it can be swiped.
Reference Implementation
The same implementation approach used by the live preview, kept compact enough to inspect and adapt.
'use client';
import { motion, useAnimation } from 'framer-motion';
import { useEffect } from 'react';
import { Trash2 } from 'lucide-react';
export function SwipeGestureHintDemo({ isPlaying = false }: { isPlaying?: boolean }) {
const controls = useAnimation();
useEffect(() => {
if (!isPlaying) {
requestAnimationFrame(() => {
try { controls.set({ x: 0 }); } catch (e) { }
});
return;
}
const playHint = async () => {
await new Promise((r) => setTimeout(r, 600));
"text-stone-400 italic">// Nudge to reveal destructive action
await controls.start({
x: -48,
transition: { type: 'spring', stiffness: 400, damping: 25 }
});
await new Promise((r) => setTimeout(r, 300));
"text-stone-400 italic">// Snap back into place
await controls.start({
x: 0,
transition: { type: 'spring', stiffness: 300, damping: 20 }
});
};
const interval = setInterval(playHint, 2500);
playHint();
return () => clearInterval(interval);
}, [isPlaying, controls]);
return (
<div className="flex h-64 w-full items-center justify-center rounded-2xl bg-white p-6 shadow-sm ring-1 ring-stone-200">
<div className="w-full max-w-[280px] overflow-hidden rounded-xl border border-stone-200 bg-stone-50">
<div className="relative">
{"text-stone-400 italic">/* Background Action (Hidden Menu) */}
<div className="absolute inset-0 flex items-center justify-end bg-red-500 px-5">
<Trash2 className="h-5 w-5 text-white" />
</div>
{"text-stone-400 italic">/* Foreground List Item that slides */}
<motion.div
animate={controls}
className="relative flex items-center gap-4 bg-white p-4 shadow-sm"
>
<div className="h-10 w-10 shrink-0 rounded-full bg-stone-100" />
<div className="flex w-full flex-col gap-2">
<div className="h-3 w-3/4 rounded bg-stone-200" />
<div className="h-2 w-1/2 rounded bg-stone-100" />
</div>
</motion.div>
</div>
</div>
</div>
);
}