Swipeable List
beui/swipeable-listFreeBlock
Mobile-style list rows that swipe left or right to reveal contextual action buttons.
Install it
npx shadcn@latest add https://beui.dev/r/swipeable-list.jsonSource
1"use client";2// beui.dev/components/blocks/swipeable-list34import {5 animate,6 motion,7 useMotionValue,8 useReducedMotion,9 type PanInfo,10} from "motion/react";11import {12 useCallback,13 useEffect,14 useRef,15 useState,16 type ReactNode,17} from "react";18import { cn } from "@/lib/utils";1920export type SwipeSide = "left" | "right";2122export type SwipeableListValue = {23 id: string;24 side: SwipeSide;25};2627export type SwipeActionTone =28 | "neutral"29 | "primary"30 | "success"31 | "warning"32 | "danger";3334export type SwipeAction = {35 id: string;36 label: ReactNode;37 icon: ReactNode;38 tone?: SwipeActionTone;39 disabled?: boolean;40 onClick?: (item: SwipeableListItem) => void;41};4243export type SwipeableListItem = {44 id: string;45 title?: ReactNode;46 description?: ReactNode;47 meta?: ReactNode;48 leading?: ReactNode;49 content?: ReactNode;50 leftActions?: SwipeAction[];51 rightActions?: SwipeAction[];52 disabled?: boolean;53};5455export type SwipeableListClassNames = {56 root?: string;57 item?: string;58 rail?: string;59 action?: string;60 surface?: string;61 leading?: string;62 content?: string;63 title?: string;64 description?: string;65 meta?: string;66};6768export interface SwipeableListProps {69 items: SwipeableListItem[];70 value?: SwipeableListValue | null;71 defaultValue?: SwipeableListValue | null;72 onValueChange?: (value: SwipeableListValue | null) => void;73 onAction?: (payload: {74 item: SwipeableListItem;75 action: SwipeAction;76 side: SwipeSide;77 }) => void;78 actionWidth?: number;79 revealThreshold?: number;80 closeOnAction?: boolean;81 className?: string;82 classNames?: SwipeableListClassNames;83 renderItem?: (item: SwipeableListItem) => ReactNode;84}8586// Distance-based release spring keeps short rebounds and full reveals feeling87// equally direct, closer to native mobile list interactions.88const ROW_SETTLE = {89 type: "spring",90 stiffness: 560,91 damping: 48,92 mass: 0.82,93 restDelta: 0.5,94 restSpeed: 8,95} as const;96const OPEN_DISTANCE_RATIO = 0.46;97const CLOSE_DISTANCE_RATIO = 0.72;98const OPEN_VELOCITY = 720;99const CLOSE_VELOCITY = 320;100const FLING_DISTANCE = 14;101const RELEASE_VELOCITY_LIMIT = 1500;102103const ACTION_TONE_CLASS: Record<SwipeActionTone, string> = {104 neutral: "text-muted-foreground group-hover:text-foreground",105 primary: "text-foreground",106 success: "text-emerald-600 dark:text-emerald-400",107 warning: "text-amber-600 dark:text-amber-400",108 danger: "text-destructive",109};110111function useControllableSwipeValue({112 value,113// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| File Upload Attachment Uploadattachment-upload | beui | Blocks | Free | 4 deps · 5 files | |
| Availability Scheduleravailability-scheduler | beui | Blocks | Free | 4 deps · 15 files | |
| Bloom Menubloom-menu | beui | Blocks | Free | 4 deps · 3 files | |
| Command Palettecommand-palette | beui | Blocks | Free | 4 deps · 3 files | |
| Dynamic Islanddynamic-island | beui | Blocks | Free | 3 deps · 3 files | |
| Expandable Action Barexpandable-action-bar | beui | Blocks | Free | 3 deps · 2 files | |
| Expandable Tabsexpandable-tabs | beui | Blocks | Free | 3 deps · 3 files | |
| Feedback Widgetfeedback-widget | beui | Blocks | Free | 4 deps · 9 files |
