Low-level overlay primitive: a portalled, scroll-locked backdrop with a focus-trapped, centered panel. DialogPanel is the white rounded content container placed inside it.
Dialog is the lowest-level overlay in the family and expects Floating UI plumbing (context, getFloatingProps, a floating ref). Most code should not use it directly — reach for Modal / openModal (@uxf/ui/modal), which wraps Dialog, supplies that plumbing, and adds a controlled isOpen / onClose API plus the modal stack.
Use Dialog (or the useDialog hook) directly only for a bespoke overlay outside the modal stack. Use DialogPanel wherever you need the standard panel container — it is the usual child of a Modal.
The useDialog hook wires up Floating UI and returns everything Dialog needs. It lives in the same file but is not re-exported from index.ts, so import it from the file directly:
import { Button } from "@uxf/ui/button";
import { useDialog } from "@uxf/ui/dialog/dialog";
function Example() {
const { openDialog, DialogProvider, closeDialog } = useDialog();
return (
<>
<Button onClick={() => openDialog(<Button onClick={closeDialog}>Close</Button>)}>Open</Button>
<DialogProvider />
</>
);
}
useDialog returns:
openDialog(content) – shows content; called on an open dialog, it replaces the content. The dialog itself (portal,
overlay, focus trap, scroll lock) stays mounted, the content mounts afresh on every call, so no state carries over
from the previous content.closeDialog() – closes it and calls onDialogClose.DialogProvider – renders the dialog; accepts className, variant and style. It is the same component for the
lifetime of the hook. It renders what openDialog was given and ignores children.getFloatingElementProps – Floating UI reference props for an element that should toggle the dialog.Options: isBackdropCloseDisabled, isEscapeKeyCloseDisabled, onDialogClose.
DialogPanel gives content the standard panel styling and width:
import { DialogPanel } from "@uxf/ui/dialog";
<DialogPanel width="sm">Panel content</DialogPanel>;
Imported from @uxf/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
isOpen | boolean | — (required) | Whether the overlay is rendered. |
context | UseFloatingReturn["context"] | — (required) | Floating UI context (from useFloating). |
ref | Ref<HTMLDivElement> | — (required) | Floating element ref (refs.setFloating). |
getFloatingProps | (userProps?) => Partial<Record<string, unknown>> | — (required) | Floating UI interaction props getter. |
children | ReactNode | — | Overlay content, typically a DialogPanel. |
variant | DialogVariant | "default" | Visual variant (default, drawer-right). |
className | string | — | Extra class on the overlay. |
style | CSSProperties | — | Inline style on the overlay. |
Imported from @uxf/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
width | DialogPanelWidth | "default" | Panel max-width (see below). |
children | ReactNode | — | Panel content. |
className | string | — | Extra class on the panel. |
DialogVariant: default, drawer-right (right-anchored drawer on sm screens and up).
DialogPanelWidth maps to a max-width:
| Width | Max width |
|---|---|
xs | xs |
sm | sm |
default | lg |
lg | 3xl |
xl | 5xl |
Import the component stylesheet once in your global CSS:
@import url("@uxf/ui/css/dialog.css");
Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.