import { Button } from "@/registry/components/button/react/button";import { Dialog, DialogClose, DialogContent, DialogDescription, DialogTitle, DialogTrigger,} from "@/registry/components/dialog/react/dialog";// import "@/registry/components/dialog/react/dialog.css";import "@/registry/components/button/button.css";import "@/registry/examples/button-secondary.css";
export function DialogDemo() { return ( <Dialog> <DialogTrigger asChild> <Button>Open Dialog</Button> </DialogTrigger> <DialogContent className="flow"> <DialogTitle>Edit profile</DialogTitle> <DialogDescription className="flow-space-2xs"> Make changes to your profile here. Click save when you're done. </DialogDescription> <div className="cluster justify-end gap-2xs"> <DialogClose data-variant="secondary">Close</DialogClose> <Button data-variant="primary">Confirm</Button> </div> </DialogContent> </Dialog> );}
You can add the dialog component in two ways:
- During project initialization:
pnpm dlx make-sugarcube@latest init
npx make-sugarcube@latest init
yarn make-sugarcube@latest init
bunx --bun make-sugarcube@latest init
Then select the dialog component when prompted.
- After initialization:
pnpm dlx make-sugarcube@latest components dialog --framework react
npx make-sugarcube@latest components dialog --framework react
yarn make-sugarcube@latest components dialog --framework react
bunx --bun make-sugarcube@latest components dialog --framework react
When you add the button component, you get:
dialog.tsx
- The React component implementationdialog.css
- The base styles for the dialogdialog.tokens.json
- The CSS variables that map to your design tokens@clsx
- Theclsx
utility for conditional classes
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";import cn from "clsx";import type * as React from "react";
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) { return <DialogPrimitive.Root {...props} />;}
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) { return <DialogPrimitive.Trigger {...props} />;}
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) { return <DialogPrimitive.Portal {...props} />;}
function DialogClose({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) { return <DialogPrimitive.Close className={cn("button", className)} {...props} />;}
function DialogBackdrop({ className, ...props}: React.ComponentProps<typeof DialogPrimitive.Overlay>) { return <DialogPrimitive.Overlay className={cn("dialog-backdrop", className)} {...props} />;}
function DialogContent({ className, children, ...props}: React.ComponentProps<typeof DialogPrimitive.Content>) { return ( <DialogPortal> <DialogBackdrop /> <DialogPrimitive.Content className={cn("dialog", className)} {...props}> {children} </DialogPrimitive.Content> </DialogPortal> );}
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) { return <DialogPrimitive.Title className={cn("dialog-title", className)} {...props} />;}
function DialogDescription({ className, ...props}: React.ComponentProps<typeof DialogPrimitive.Description>) { return ( <DialogPrimitive.Description className={cn("dialog-description", className)} {...props} /> );}
export { Dialog, DialogTrigger, DialogPortal, DialogBackdrop, DialogContent, DialogClose, DialogTitle, DialogDescription,};
.dialog:has(.command) { padding: 0; border: none;}
.dialog-backdrop { position: fixed; inset: 0; z-index: 50; background-color: var(--dialog-backdrop); animation: dialog-fade-out var(--duration-200) var(--ease-out);}
.dialog-backdrop[data-state="open"] { animation: dialog-fade-in var(--duration-200) var(--ease-out);}
.dialog { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 51; max-width: calc(100vw - 2rem); width: var(--dialog-width); background-color: var(--dialog-bg); padding: var(--dialog-padding); box-shadow: var(--dialog-shadow); border-radius: var(--dialog-radius); animation: dialog-close var(--duration-200) var(--ease-out);}
.dialog[data-state="open"] { animation: dialog-open var(--duration-200) var(--ease-out);}
.dialog-title { font-size: var(--dialog-title-font-size); font-weight: var(--dialog-title-font-weight); color: var(--dialog-title-color);}
.dialog-description { font-size: var(--dialog-description-font-size); color: var(--dialog-description-color);}
@keyframes dialog-fade-in { from { opacity: 0; } to { opacity: 1; }}
@keyframes dialog-fade-out { from { opacity: 1; } to { opacity: 0; }}
@keyframes dialog-open { from { opacity: 0; transform: translate(-50%, -48%) scale(0.95); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); }}
@keyframes dialog-close { from { opacity: 1; transform: translate(-50%, -50%) scale(1); } to { opacity: 0; transform: translate(-50%, -48%) scale(0.95); }}
{ "dialog": { "bg": { "$value": "{color.bg}" }, "shadow": { "$value": "{shadow.md}" }, "radius": { "$value": "{radius.panel}" }, "width": { "$type": "dimension", "$value": { "value": 26, "unit": "rem" } }, "padding": { "$value": "{space.md}" }, "backdrop": { "$value": "{color.overlay}" }, "title": { "font-size": { "$value": "{text.lg}" }, "font-weight": { "$value": "{font.weight.semibold}" }, "line-height": { "$value": "{leading.none}" }, "color": { "$value": "{color.text.title}" } }, "description": { "font-size": { "$value": "{text.sm}" }, "color": { "$value": "{color.text.secondary}" } } }}
:::note The following examples show how to use data attributes for variants. This is just one possible approach. See the principles section for more information on how to approach component variants. :::