SPB Git

Repository Public

sheet.tsx 2.2 KB 53 lines tsx

1'use client';2import * as React from 'react';3import * as D from '@radix-ui/react-dialog';4import { X } from 'lucide-react';5import { cn } from '@/lib/cn';6import { useBreakpoint } from '@/hooks/use-viewport';7import { BottomSheet } from './bottom-sheet';89/** Edge-anchored panel (drawer). `side="bottom"` is the mobile sheet. */10export function Sheet({11  open, onOpenChange, title, side = 'right', children, className, headerExtra,12}: {13  open: boolean;14  onOpenChange: (open: boolean) => void;15  title: string;16  side?: 'left' | 'right' | 'bottom';17  children: React.ReactNode;18  className?: string;19  headerExtra?: React.ReactNode;20}) {21  const bp = useBreakpoint();22  if (side === 'bottom' || (bp === 'mobile' && side === 'right')) {23    return (24      <BottomSheet open={open} onOpenChange={onOpenChange} title={title} headerExtra={headerExtra} className={className}>25        {children}26      </BottomSheet>27    );28  }29  const pos = {30    right: 'anim-slide-right right-0 top-0 h-full w-[min(480px,100vw)] border-l',31    left: 'anim-slide-left left-0 top-0 h-full w-[min(360px,88vw)] border-r',32    bottom: 'anim-slide-up bottom-0 left-0 max-h-[85dvh] w-full rounded-t-lg border-t',33  }[side];34  return (35    <D.Root open={open} onOpenChange={onOpenChange}>36      <D.Portal>37        <D.Overlay className="anim-fade fixed inset-0 z-50 bg-scrim" />38        <D.Content className={cn('fixed z-50 flex flex-col border-card-line bg-surface shadow-pop focus:outline-none', pos, className)}>39          <div className={cn('flex items-center gap-2 border-b border-line px-4 py-2.5', 'pt-[max(10px,env(safe-area-inset-top))]')}>40            <D.Title className="min-w-0 flex-1 truncate text-sm font-semibold">{title}</D.Title>41            <D.Description className="sr-only">{title}</D.Description>42            {headerExtra}43            <D.Close aria-label="Close" className="inline-flex size-7 items-center justify-center rounded-sm text-muted hover:bg-surface-2 hover:text-text pointer-coarse:size-11">44              <X className="size-4" />45            </D.Close>46          </div>47          <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain pb-[env(safe-area-inset-bottom)]">{children}</div>48        </D.Content>49      </D.Portal>50    </D.Root>51  );52}53
Files main
Menu

Theme