diff --git a/apps/www/components/examples/index.tsx b/apps/www/components/examples/index.tsx index 4e21f011c9..216fc3ef0e 100644 --- a/apps/www/components/examples/index.tsx +++ b/apps/www/components/examples/index.tsx @@ -39,6 +39,9 @@ import { RadioGroupDemo } from "@/components/examples/radio-group/demo" import { ScrollAreaDemo } from "@/components/examples/scroll-area/demo" import { SelectDemo } from "@/components/examples/select/demo" import { SeparatorDemo } from "@/components/examples/separator/demo" +import { SheetDemo } from "@/components/examples/sheet/demo" +import { SheetPosition } from "@/components/examples/sheet/position" +import { SheetSize } from "@/components/examples/sheet/size" import { SliderDemo } from "@/components/examples/slider/demo" import { SwitchDemo } from "@/components/examples/switch/demo" import { TabsDemo } from "@/components/examples/tabs/demo" @@ -116,6 +119,9 @@ export const examples = { ScrollAreaDemo, SelectDemo, SeparatorDemo, + SheetDemo, + SheetSize, + SheetPosition, SliderDemo, SwitchDemo, TabsDemo, diff --git a/apps/www/components/examples/sheet/demo.tsx b/apps/www/components/examples/sheet/demo.tsx new file mode 100644 index 0000000000..7beac41df3 --- /dev/null +++ b/apps/www/components/examples/sheet/demo.tsx @@ -0,0 +1,49 @@ +"use client" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" + +export function SheetDemo() { + return ( + + + + + + + Edit profile + + Make changes to your profile here. Click save when you're done. + + +
+
+ + +
+
+ + +
+
+ + + +
+
+ ) +} diff --git a/apps/www/components/examples/sheet/position.tsx b/apps/www/components/examples/sheet/position.tsx new file mode 100644 index 0000000000..6fbe1b84d3 --- /dev/null +++ b/apps/www/components/examples/sheet/position.tsx @@ -0,0 +1,75 @@ +"use client" + +import { useState } from "react" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" + +const SHEET_POSITIONS = ["top", "right", "bottom", "left"] as const + +type SheetPosition = typeof SHEET_POSITIONS[number] + +export function SheetPosition() { + const [position, setPosition] = useState("right") + return ( +
+ setPosition(value as SheetPosition)} + > +
+ {SHEET_POSITIONS.map((position, index) => ( +
+ + +
+ ))} +
+
+ + + + + + + Edit profile + + Make changes to your profile here. Click save when you're done. + + +
+
+ + +
+
+ + +
+
+ + + +
+
+
+ ) +} diff --git a/apps/www/components/examples/sheet/size.tsx b/apps/www/components/examples/sheet/size.tsx new file mode 100644 index 0000000000..de9f0e63e7 --- /dev/null +++ b/apps/www/components/examples/sheet/size.tsx @@ -0,0 +1,75 @@ +"use client" + +import { useState } from "react" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet" + +const SHEET_SIZES = ["sm", "default", "lg", "xl", "full", "content"] as const + +type SheetSize = typeof SHEET_SIZES[number] + +export function SheetSize() { + const [size, setSize] = useState("default") + return ( +
+ setSize(value as SheetSize)} + > +
+ {SHEET_SIZES.map((size, index) => ( +
+ + +
+ ))} +
+
+ + + + + + + Edit profile + + Make changes to your profile here. Click save when you're done. + + +
+
+ + +
+
+ + +
+
+ + + +
+
+
+ ) +} diff --git a/apps/www/components/ui/sheet.tsx b/apps/www/components/ui/sheet.tsx new file mode 100644 index 0000000000..75545b74ab --- /dev/null +++ b/apps/www/components/ui/sheet.tsx @@ -0,0 +1,234 @@ +"use client" + +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { VariantProps, cva } from "class-variance-authority" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const portalVariants = cva("fixed inset-0 z-50 flex", { + variants: { + position: { + top: "items-start", + bottom: "items-end", + left: "justify-start", + right: "justify-end", + }, + }, + defaultVariants: { position: "right" }, +}) + +interface SheetPortalProps + extends SheetPrimitive.DialogPortalProps, + VariantProps {} + +const SheetPortal = ({ + position, + className, + children, + ...props +}: SheetPortalProps) => ( + +
{children}
+
+) +SheetPortal.displayName = SheetPrimitive.Portal.displayName + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 scale-100 gap-4 bg-white p-6 opacity-100 dark:bg-slate-900", + { + variants: { + position: { + top: "animate-in slide-in-from-top w-full duration-300", + bottom: "animate-in slide-in-from-bottom w-full duration-300", + left: "animate-in slide-in-from-left h-full duration-300", + right: "animate-in slide-in-from-right h-full duration-300", + }, + size: { + content: "", + default: "", + sm: "", + lg: "", + xl: "", + full: "", + }, + }, + compoundVariants: [ + { + position: ["top", "bottom"], + size: "content", + class: "max-h-screen", + }, + { + position: ["top", "bottom"], + size: "default", + class: "h-1/3", + }, + { + position: ["top", "bottom"], + size: "sm", + class: "h-1/4", + }, + { + position: ["top", "bottom"], + size: "lg", + class: "h-1/2", + }, + { + position: ["top", "bottom"], + size: "xl", + class: "h-5/6", + }, + { + position: ["top", "bottom"], + size: "full", + class: "h-screen", + }, + { + position: ["right", "left"], + size: "content", + class: "max-w-screen", + }, + { + position: ["right", "left"], + size: "default", + class: "w-1/3", + }, + { + position: ["right", "left"], + size: "sm", + class: "w-1/4", + }, + { + position: ["right", "left"], + size: "lg", + class: "w-1/2", + }, + { + position: ["right", "left"], + size: "xl", + class: "w-5/6", + }, + { + position: ["right", "left"], + size: "full", + class: "w-screen", + }, + ], + defaultVariants: { + position: "right", + size: "default", + }, + } +) + +export interface DialogContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + DialogContentProps +>(({ position, size, className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetTrigger, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/apps/www/config/docs.ts b/apps/www/config/docs.ts index e3ea5f8155..a503b1ba58 100644 --- a/apps/www/config/docs.ts +++ b/apps/www/config/docs.ts @@ -177,6 +177,11 @@ export const docsConfig: DocsConfig = { href: "/docs/primitives/separator", items: [], }, + { + title: "Sheet", + href: "/docs/primitives/sheet", + items: [], + }, { title: "Slider", href: "/docs/primitives/slider", diff --git a/apps/www/content/docs/primitives/sheet.mdx b/apps/www/content/docs/primitives/sheet.mdx new file mode 100644 index 0000000000..12261f12df --- /dev/null +++ b/apps/www/content/docs/primitives/sheet.mdx @@ -0,0 +1,77 @@ +--- +title: Sheet +description: Extension of Dialog component that displays content that complements the main content of the screen, or a list of actions that affect the main content of the screen. +radix: + link: https://www.radix-ui.com/docs/primitives/components/dialog + api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference +--- + + + + + +## Installation + +1. Install the `@radix-ui/react-dialog` component from radix-ui: + +```bash +npm install @radix-ui/react-dialog +``` + +2. Copy and paste the following code into your project. + + + + + +This is the `` primitive. You can place it in a file at `components/ui/sheet.tsx`. + + + +## Usage + +```tsx +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/dialog" +``` + +```tsx + + Open + + + Are you sure absolutely sure? + + This action cannot be undone. This will permanently delete your account + and remove your data from our servers. + + + + +``` + +## Examples + +### Position + +Pass the `position` property to `` to indicate the edge of the screen where the component will appear. The values can be `top`, `right`, `bottom` or `left`. + + + + + +--- + +### Size + +Pass the `size` property to `` if you need to adjust the size of the sheet. The values can be `sm`, `default`, `lg`, `xl`, `full` or `content`. + + + +