1import { Button } from "~/components/ui/button";2import {3 Dialog,4 DialogContent,5 DialogDescription,6 DialogFooter,7 DialogHeader,8 DialogTitle,9 DialogTrigger,10} from "~/components/ui/dialog";11import {12 TextField,13 TextFieldInput,14 TextFieldLabel,15} from "~/components/ui/text-field";16
17export default function DialogDemo() {18 return (19 <Dialog>20 <DialogTrigger as={Button<"button">}>Edit Profile</DialogTrigger>21 <DialogContent class="sm:max-w-[425px]">22 <DialogHeader>23 <DialogTitle>Edit profile</DialogTitle>24 <DialogDescription>25 Make changes to your profile here. Click save when you're done.26 </DialogDescription>27 </DialogHeader>28 <div class="grid gap-4 py-4">29 <TextField class="grid grid-cols-4 items-center gap-4">30 <TextFieldLabel class="text-right">Name</TextFieldLabel>31 <TextFieldInput32 value="Pedro Duarte"33 class="col-span-3"34 type="text"35 />36 </TextField>37 <TextField class="grid grid-cols-4 items-center gap-4">38 <TextFieldLabel class="text-right">Username</TextFieldLabel>39 <TextFieldInput value="@peduarte" class="col-span-3" type="text" />40 </TextField>41 </div>42 <DialogFooter>43 <Button type="submit">Save changes</Button>44 </DialogFooter>45 </DialogContent>46 </Dialog>47 );48}
npx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dialog.json
yarn shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dialog.json
pnpm dlx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dialog.json
bunx --bun shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dialog.json
Install the following dependencies
npm install @kobalte/core
yarn add @kobalte/core
pnpm add @kobalte/core
bun add @kobalte/core
Install the following component dependencies
Copy and paste the following code into your project
1import type { PolymorphicProps } from "@kobalte/core/polymorphic";2import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js";3
4import { splitProps } from "solid-js";5import * as DialogPrimitive from "@kobalte/core/dialog";6import XIcon from "lucide-solid/icons/x";7
8import { cn } from "~/lib/utils";9import { buttonVariants } from "./button";10
11const Dialog = (props: DialogPrimitive.DialogRootProps) => {12 return <DialogPrimitive.Root data-slot="dialog" {...props} />;13};14
15const DialogTrigger = <T extends ValidComponent = "button">(16 props: PolymorphicProps<T, DialogPrimitive.DialogTriggerProps<T>>,17) => {18 return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;19};20
21const DialogPortal: Component<DialogPrimitive.DialogPortalProps> = (props) => {22 const [, rest] = splitProps(props, ["children"]);23 return (24 <DialogPrimitive.Portal data-slot="dialog-portal" {...rest}>25 <div class="fixed inset-0 z-50 flex items-start justify-center sm:items-center">26 {props.children}27 </div>28 </DialogPrimitive.Portal>29 );30};31
32type DialogOverlayProps<T extends ValidComponent = "div"> =33 DialogPrimitive.DialogOverlayProps<T> & { class?: string | undefined };34
35const DialogOverlay = <T extends ValidComponent = "div">(36 props: PolymorphicProps<T, DialogOverlayProps<T>>,37) => {38 const [, rest] = splitProps(props as DialogOverlayProps, ["class"]);39 return (40 <DialogPrimitive.Overlay41 data-slot="dialog-overlay"42 class={cn(43 "fixed inset-0 z-50 bg-overlay ui-expanded:animate-in ui-expanded:fade-in-0 ui-closed:animate-out ui-closed:fade-out-0",44 props.class,45 )}46 {...rest}47 />48 );49};50
51type DialogContentProps<T extends ValidComponent = "div"> =52 DialogPrimitive.DialogContentProps<T> & {53 class?: string | undefined;54 children?: JSX.Element;55 };56
57const DialogContent = <T extends ValidComponent = "div">(58 props: PolymorphicProps<T, DialogContentProps<T>>,59) => {60 const [, rest] = splitProps(props as DialogContentProps, [61 "class",62 "children",63 ]);64 return (65 <DialogPortal>66 <DialogOverlay />67 <DialogPrimitive.Content68 data-slot="dialog-content"69 class={cn(70 "fixed top-1/2 left-1/2 z-50 grid max-h-screen w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto border-2 border-border bg-background p-6 shadow-shadow duration-200 sm:rounded-lg ui-expanded:animate-in ui-expanded:fade-in-0 ui-expanded:zoom-in-95 ui-closed:animate-out ui-closed:fade-out-0 ui-closed:zoom-out-95",71 props.class,72 )}73 {...rest}74 >75 {props.children}76 <DialogPrimitive.CloseButton77 data-slot="dialog-close-button"78 class={cn(79 buttonVariants({80 variant: "neutral",81 size: "icon",82 }),83 "absolute top-2 right-3 size-8",84 )}85 >86 <XIcon class="size-4" />87 <span class="sr-only">Close</span>88 </DialogPrimitive.CloseButton>89 </DialogPrimitive.Content>90 </DialogPortal>91 );92};93
94const DialogHeader: Component<ComponentProps<"div">> = (props) => {95 const [, rest] = splitProps(props, ["class"]);96 return (97 <div98 data-slot="dialog-header"99 class={cn(100 "flex flex-col space-y-1.5 text-center sm:text-left",101 props.class,102 )}103 {...rest}104 />105 );106};107
108const DialogFooter: Component<ComponentProps<"div">> = (props) => {109 const [, rest] = splitProps(props, ["class"]);110 return (111 <div112 data-slot="dialog-footer"113 class={cn(114 "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",115 props.class,116 )}117 {...rest}118 />119 );120};121
122type DialogTitleProps<T extends ValidComponent = "h2"> =123 DialogPrimitive.DialogTitleProps<T> & {124 class?: string | undefined;125 };126
127const DialogTitle = <T extends ValidComponent = "h2">(128 props: PolymorphicProps<T, DialogTitleProps<T>>,129) => {130 const [, rest] = splitProps(props as DialogTitleProps, ["class"]);131 return (132 <DialogPrimitive.Title133 data-slot="dialog-title"134 class={cn(135 "text-lg leading-none font-semibold tracking-tight",136 props.class,137 )}138 {...rest}139 />140 );141};142
143type DialogDescriptionProps<T extends ValidComponent = "p"> =144 DialogPrimitive.DialogDescriptionProps<T> & {145 class?: string | undefined;146 };147
148const DialogDescription = <T extends ValidComponent = "p">(149 props: PolymorphicProps<T, DialogDescriptionProps<T>>,150) => {151 const [, rest] = splitProps(props as DialogDescriptionProps, ["class"]);152 return (153 <DialogPrimitive.Description154 data-slot="dialog-description"155 class={cn("text-sm text-muted-foreground", props.class)}156 {...rest}157 />158 );159};160
161export {162 Dialog,163 DialogTrigger,164 DialogContent,165 DialogHeader,166 DialogFooter,167 DialogTitle,168 DialogDescription,169};
Update the import paths to match your project setup.
1import {2 Dialog,3 DialogContent,4 DialogDescription,5 DialogFooter,6 DialogHeader,7 DialogTitle,8 DialogTrigger,9} from "~/components/ui/dialog";
1<Dialog>2 <DialogTrigger>Open</DialogTrigger>3 <DialogContent>4 <DialogHeader>5 <DialogTitle>Dialog Title</DialogTitle>6 <DialogDescription>This is a description of the dialog.</DialogDescription>7 </DialogHeader>8 <p>This is the content of the dialog.</p>9 </DialogContent>10</DialogContent>