import { Dialog as Primitive } from "@base-ui/react/dialog"; import { mergeClassName, type StateClassName } from "./class-name.ts"; import { CloseGlyph } from "./glyphs.tsx"; // The parts, straight through. Base UI already does focus trap, escape, outside-dismiss, // scroll lock, focus return and the aria wiring, and a wrapper around any of these would only // add a class name — so they are re-exported, not re-implemented. export const Dialog = Primitive.Root; export const DialogTrigger = Primitive.Trigger; export const DialogTitle = Primitive.Title; export const DialogDescription = Primitive.Description; export const DialogClose = Primitive.Close; export const DialogPortal = Primitive.Portal; export const DialogBackdrop = Primitive.Backdrop; export const DialogPopup = Primitive.Popup; export type DialogContentProps = Primitive.Popup.Props & { /** * Accessible name, for a dialog with no visible `DialogTitle`. With a title, leave this * out: Base UI points the popup's `aria-labelledby` at it, and an `aria-label` here would * override the words the user can actually see. */ label?: string; /** * Label for the built-in close button. REQUIRED to render the button: passing the label is the * only way to render the button, so an unlabelled close button cannot be written. There is no * default string, because a default would be English. */ closeLabel?: string; backdropClassName?: StateClassName; /** Where the portal mounts. Defaults to ``. */ container?: Primitive.Portal.Props["container"]; }; /** * Portal + backdrop + popup as one part, so a scrimless dialog is not a thing a caller can * ship by forgetting a line. The popup owns the scroll (`overflow-y-auto` plus * `overscroll-contain`, so reaching the end of a long dialog does not start scrolling the * page behind it) and is capped to the viewport, so a tall dialog is never taller than the * screen it opens on. * * Padding, radius, shadow and type all belong to the product. What is here is what makes the * primitive work. */ export function DialogContent({ className, backdropClassName, container, label, closeLabel, children, ...rest }: DialogContentProps) { return ( {/* `outline-none` belongs on a popup and almost nowhere else: this element takes programmatic focus the moment it opens, and a focus ring is meant to answer a keyboard, not to frame every dialog that appears. Controls inside keep theirs. */} {children} {closeLabel === undefined ? null : ( )} ); }