Side Sheets
Описание
Side Sheets отображают дополнительный контент, прикрепленный к боковой части экрана.
Подробнее об использовании элемента читайте на официальном сайте
Примеры
Компонент
Компонент можно сохранить в src/shared/ui/SideSheet.tsx. Обратите внимание на необходимые зависимости: Title.
Так же данный компонент использует @radix-ui/react-dialog компонент.
yarn add @radix-ui/react-dialog
Напомню, что в качестве иконок я использую iconoir
yarn add iconoir-react
"use client"import * as React from "react"import * as SheetPrimitive from "@radix-ui/react-dialog"import { cva, type VariantProps } from "class-variance-authority"import { Cancel } from "iconoir-react"import Title from "../typography/Title"import { cn } from "@/lib/cn"const Sheet = SheetPrimitive.Rootconst SheetTrigger = SheetPrimitive.Triggerconst SheetClose = SheetPrimitive.Closeconst SheetPortal = ({className,...props}: SheetPrimitive.DialogPortalProps) => (<SheetPrimitive.Portal className={cn(className)} {...props} />)SheetPortal.displayName = SheetPrimitive.Portal.displayNameconst SheetOverlay = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Overlay>,React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>>(({ className, ...props }, forwardedRef) => (<SheetPrimitive.OverlayclassName={cn("fixed inset-0 z-50 bg-scrim/20 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",className)}{...props}ref={forwardedRef}/>))SheetOverlay.displayName = SheetPrimitive.Overlay.displayNameconst sheetVariants = cva("fixed z-50 flex flex-col py-6 rounded-l-extra-large shadow-elevation1 bg-surfaceContainerLow transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",{variants: {side: {top: "inset-x-0 top-0 data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",bottom:"inset-x-0 bottom-0 data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",left: "inset-y-0 left-0 h-full min-w-[320px] max-w-[400px] data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left",right:"inset-y-0 right-0 h-full min-w-[320px] max-w-[400px] data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",},},defaultVariants: {side: "right",},})interface SheetContentPropsextends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,VariantProps<typeof sheetVariants> {}const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>,SheetContentProps>(({ side = "right", className, children, ...props }, forwardedRef) => (<SheetPortal><SheetOverlay /><SheetPrimitive.Contentref={forwardedRef}className={cn(sheetVariants({ side }), className)}{...props}>{children}</SheetPrimitive.Content></SheetPortal>))SheetContent.displayName = SheetPrimitive.Content.displayNameconst SheetHeader = ({className,children,...props}: React.HTMLAttributes<HTMLDivElement>) => (<divclassName={cn("flex items-center gap-3 text-left px-6 mb-6", className)}{...props}>{children}<SheetPrimitive.Close className="ml-auto text-onSurfaceVariant rounded-sm opacity-100 transition-opacity hover:opacity-70"><Cancel /></SheetPrimitive.Close></div>)SheetHeader.displayName = "SheetHeader"const SheetFooter = ({className,...props}: React.HTMLAttributes<HTMLDivElement>) => (<div className="mt-auto"><div className="h-px w-full bg-outline" /><divclassName={cn("flex items-center gap-2 h-[72px] pt-4 px-6", className)}{...props}/></div>)SheetFooter.displayName = "SheetFooter"const SheetTitle = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Title>,React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>>(({ className, children, ...props }, forwardedRef) => (<SheetPrimitive.Titleref={forwardedRef}className={cn("text-onSurfaceVariant", className)}{...props}asChild><Title size="large">{children}</Title></SheetPrimitive.Title>))SheetTitle.displayName = SheetPrimitive.Title.displayNameexport {Sheet,SheetTrigger,SheetClose,SheetContent,SheetHeader,SheetFooter,SheetTitle,}
Использование
Данный файл экспортирует 7 компонентов
Sheet - компонент, содержащий стейт о том, открыт сейчас dialog или нет
SheetTrigger - кнопка, открывающая dialog
SheetHeader - хедер, содержит в себе заголовок и кнопку закрытия
SheetTitle - просто заголовок, помещается внутри SheetHeader
SheetClose - компонент, внутрь которого можно поместить любой React элемент. Нажатие будет тригерить событие закрытия
SheetContent - весь контент будет располагаться здесь. Не забудьте добавить padding для компонента: px-6
SheetFooter - футер с кнопками. Если необходимо закрывать SideSheet при нажатии на кнопки, оборачиваем их в SheetClose
Ниже - код для примера в начале страницы.
<Sheet><SheetTrigger asChild><Button appearance="filled">Open</Button></SheetTrigger><SheetContent><SheetHeader><SheetTitle>Заголовок</SheetTitle></SheetHeader><div className="flex flex-col px-6"><Body className="text-onSurface">Ваш контент будет находиться здесь</Body></div><SheetFooter><SheetClose asChild><Button appearance="filled">Сохранить</Button></SheetClose><SheetClose asChild><Button appearance="outlined">Отменить</Button></SheetClose></SheetFooter></SheetContent></Sheet>