nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Mobile slide-up panel with drag handle, backdrop, and slide-up animation.
View the full component source code below.
"use client"
import * as React from "react"
import { XIcon } from "@/lib/icons"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
interface BottomSheetProps {
open: boolean
onClose: () => void
title?: string
children: React.ReactNode
className?: string
}
function BottomSheet({ open, onClose, title, children, className }: BottomSheetProps) {
const sheetRef = React.useRef<HTMLDivElement>(null)
const startY = React.useRef(0)
React.useEffect(() => {
if (open) {
document.body.style.overflow = "hidden"
} else {
document.body.style.overflow = ""
}
return () => {
document.body.style.overflow = ""
}
}, [open])
function handleTouchStart(e: React.TouchEvent) {
startY.current = e.touches[0].clientY
}
function handleTouchEnd(e: React.TouchEvent) {
const deltaY = e.changedTouches[0].clientY - startY.current
if (deltaY > 80) onClose()
}
if (!open) return null
return (
<div data-slot="bottom-sheet" data-portal="https://design.nyuchi.com/components/bottom-sheet" className="fixed inset-0 z-50">
<div
className="absolute inset-0 animate-in bg-black/50 duration-200 fade-in-0"
onClick={onClose}
aria-hidden
/>
<div
ref={sheetRef}
role="dialog"
aria-modal
aria-label={title ?? "Bottom sheet"}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
className={cn(
"absolute inset-x-0 bottom-0 flex max-h-[85vh] animate-in flex-col rounded-t-[var(--radius-lg,14px)] bg-card shadow-2xl ring-1 ring-foreground/5 duration-300 slide-in-from-bottom",
className
)}
>
<div className="flex items-center justify-center py-3">
<div className="h-1 w-10 rounded-full bg-muted-foreground/30" />
</div>
{title && (
<div className="flex items-center justify-between border-b border-border px-4 pb-3">
<h2 className="font-serif text-base font-medium">{title}</h2>
<Button variant="ghost" size="icon-sm" onClick={onClose} aria-label="Close">
<XIcon />
</Button>
</div>
)}
<div className="flex-1 overflow-y-auto p-4">{children}</div>
</div>
</div>
)
}
export { BottomSheet }
export type { BottomSheetProps }
npx shadcn@latest add https://mzizi.dev/api/v1/ui/bottom-sheetFetch this component's metadata and source code from the registry API.
/api/v1/ui/bottom-sheetcomponents/ui/bottom-sheet.tsx