kosori

Dialog

A popup that opens on top of the entire page.

Dialog wraps the Base UI Dialog primitive, composes Button and its scrollable panel through Base UI's render prop, and marks each part with data-slot. It is a client component: it uses a portal, manages focus, and animates with tw-animate-css.

Installation

npx shadcn@latest add @kosori/dialog

Example

dialog-example.tsx
dialog-example
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPanel,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import { Field, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';

const DialogExample = () => (
  <Dialog>
    <DialogTrigger render={<Button variant='outline' />}>
      Open parent
    </DialogTrigger>
    <DialogPopup>
      <DialogHeader>
        <DialogTitle>Manage team member</DialogTitle>
        <DialogDescription>
          View and manage a user in your team.
        </DialogDescription>
      </DialogHeader>
      <DialogPanel className='grid gap-4'>
        <div className='grid gap-1'>
          <p className='text-muted-foreground text-sm'>Name</p>
          <p className='font-medium text-sm'>Bora Baloglu</p>
        </div>
        <div className='grid gap-1'>
          <p className='text-muted-foreground text-sm'>Email</p>
          <p className='font-medium text-sm'>bora@example.com</p>
        </div>
      </DialogPanel>
      <DialogFooter>
        <DialogClose render={<Button variant='ghost' />}>Cancel</DialogClose>
        <Dialog>
          <DialogTrigger render={<Button variant='outline' />}>
            Edit details
          </DialogTrigger>
          <DialogPopup>
            <DialogHeader>
              <DialogTitle>Edit details</DialogTitle>
              <DialogDescription>
                Make changes to the member&apos;s information.
              </DialogDescription>
            </DialogHeader>
            <DialogPanel className='grid gap-4'>
              <Field>
                <FieldLabel>Name</FieldLabel>
                <Input defaultValue='Bora Baloglu' type='text' />
              </Field>
              <Field>
                <FieldLabel>Email</FieldLabel>
                <Input defaultValue='bora@example.com' type='text' />
              </Field>
            </DialogPanel>
            <DialogFooter>
              <DialogClose render={<Button variant='ghost' />}>
                Cancel
              </DialogClose>
              <Button>Save changes</Button>
            </DialogFooter>
          </DialogPopup>
        </Dialog>
      </DialogFooter>
    </DialogPopup>
  </Dialog>
);

export default DialogExample;

Usage

import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';

const DialogDemo = () => (
  <Dialog>
    <DialogTrigger render={<Button variant='outline' />}>
      Open dialog
    </DialogTrigger>
    <DialogPopup>
      <DialogHeader>
        <DialogTitle>Manage team member</DialogTitle>
        <DialogDescription>View and manage a team member.</DialogDescription>
      </DialogHeader>
      <DialogFooter>
        <DialogClose render={<Button variant='outline' />}>Cancel</DialogClose>
        <Button>Save changes</Button>
      </DialogFooter>
    </DialogPopup>
  </Dialog>
);

On this page