Bottom Sheet
sora-ui/bottom-sheetFreeComponent
A draggable, snap-point bottom sheet built on Radix Dialog for accessibility, with Motion driving the drag gesture and glide.
Install it
npx shadcn@latest add https://ui.soralabs.io.vn/r/bottom-sheet.jsonSource
1"use client";23import { cn } from "@/lib/utils";4import {5 AnimatePresence,6 type HTMLMotionProps,7 motion,8 type PanInfo,9 useDragControls,10} from "motion/react";11import { Dialog as SheetPrimitive } from "radix-ui";12import {13 type ComponentProps,14 type ReactNode,15 useCallback,16 useEffect,17 useState,18} from "react";19import { useControlledState } from "@/hooks/use-controlled-state";20import { usePrefersReducedMotion } from "@/hooks/use-prefers-reduced-motion";21import { EASE_DRAWER } from "@/lib/ease";22import { getStrictContext } from "@/lib/get-strict-context";2324// Vaul-style glide: a long, fully-damped tween reads smoother than a spring on25// open — no settle/overshoot, just one clean decel. Same curve drives the26// backdrop fade so the surface and scrim move as one.27const DRAWER_TRANSITION = { duration: 0.5, ease: EASE_DRAWER } as const;2829interface BottomSheetContextType {30 open: boolean;31 setOpen: (open: boolean) => void;32}3334const [BottomSheetProvider, useBottomSheet] =35 getStrictContext<BottomSheetContextType>("BottomSheetContext");3637type BottomSheetProps = ComponentProps<typeof SheetPrimitive.Root>;3839function BottomSheet({40 open,41 defaultOpen,42 onOpenChange,43 ...props44}: BottomSheetProps) {45 const [isOpen, setIsOpen] = useControlledState({46 value: open,47 defaultValue: defaultOpen ?? false,48 onChange: onOpenChange,49 });5051 return (52 <BottomSheetProvider value={{ open: isOpen, setOpen: setIsOpen }}>53 <SheetPrimitive.Root54 data-slot="bottom-sheet"55 onOpenChange={setIsOpen}56 open={isOpen}57 {...props}58 />59 </BottomSheetProvider>60 );61}6263type BottomSheetTriggerProps = ComponentProps<typeof SheetPrimitive.Trigger>;6465function BottomSheetTrigger(props: BottomSheetTriggerProps) {66 return <SheetPrimitive.Trigger data-slot="bottom-sheet-trigger" {...props} />;67}6869type BottomSheetCloseProps = ComponentProps<typeof SheetPrimitive.Close>;7071function BottomSheetClose(props: BottomSheetCloseProps) {72 return <SheetPrimitive.Close data-slot="bottom-sheet-close" {...props} />;73}7475type BottomSheetOverlayProps = HTMLMotionProps<"div">;7677function BottomSheetOverlay({ className, ...props }: BottomSheetOverlayProps) {78 return (79 <SheetPrimitive.Overlay asChild forceMount>80 <motion.div81 animate={{ opacity: 1 }}82 className={cn(83 "fixed inset-0 z-50 bg-background/40 backdrop-blur-sm",84 className85 )}86 data-slot="bottom-sheet-overlay"87// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from Sora UI
All 97 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | Sora UI | Components | Free | 2 deps | |
| Border Trailborder-trail | Sora UI | Components | Free | 1 dep | |
| Cursor Bubblecursor-bubble | Sora UI | Components | Free | 2 deps | |
| Cursor Trail Revealcursor-trail-reveal | Sora UI | Components | Free | 1 dep | |
| Custom Cursorcustom-cursor | Sora UI | Components | Free | 2 deps | |
| Accordion Demodemo-accordion | Sora UI | Components | Free | no deps | |
| Border Trail Demodemo-border-trail | Sora UI | Components | Free | no deps | |
| Border Trail Loading Card Demodemo-border-trail-loading | Sora UI | Components | Free | no deps |
