ui / overlay
PREVIEW READYDialog
A native modal dialog with backdrop dismissal and structured regions.
INSTALL / SOURCE REGISTRY
Add Dialog to your project
The command adds the component source and its DesignOS base dependency.
$
pnpm dlx shadcn@latest add https://designos.h4rithd.com/r/dialog.jsonregistry/default/ui/dialog.tsx
"use client"
import * as React from "react"
import { X } from "lucide-react"
import { clsx as cn } from "clsx"
import "@/components/designos/designos.css"
export type DialogProps = { trigger: React.ReactNode; title: React.ReactNode; description?: React.ReactNode; children: React.ReactNode; footer?: React.ReactNode; className?: string }
export function Dialog({ trigger, title, description, children, footer, className }: DialogProps) {
const ref = React.useRef<HTMLDialogElement>(null)
const titleId = React.useId()
const descriptionId = React.useId()
const close = () => ref.current?.close()
return <>
<button type="button" className="dos-button dos-button--secondary" onClick={() => ref.current?.showModal()}>{trigger}</button>
<dialog ref={ref} className={cn("dos-dialog", className)} aria-labelledby={titleId} aria-describedby={description ? descriptionId : undefined} onClick={(event) => { if (event.target === ref.current) close() }}>
<header className="dos-dialog__header"><div><h2 id={titleId} className="dos-card__title">{title}</h2>{description && <p id={descriptionId} className="dos-card__description">{description}</p>}</div><button className="dos-icon-button dos-button--ghost" aria-label="Close dialog" onClick={close}><X aria-hidden="true" /></button></header>
<div className="dos-dialog__body">{children}</div>
{footer && <footer className="dos-dialog__footer">{footer}</footer>}
</dialog>
</>
}
Component contract
- Source-owned after installation
- Dark and light theme variables
- Keyboard and visible-focus behavior
- Reduced-motion fallback
- Responsive from 320px upward
- IBM Plex Sans + JetBrains Mono hierarchy