{"name":"dialog","title":"Dialog","description":"A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.","installCommand":"bunx marko-ui add dialog -y","usageTags":"<Dialog>","importSnippet":"import Dialog from \"@/components/ui/dialog/dialog.marko\";","usageSnippet":"<Dialog>\n  <@trigger|props|>\n    <button ...props>Open</button>\n  </@trigger>\n  <@title>Are you absolutely sure?</@title>\n  <@description>\n    This action cannot be undone. This will permanently delete your account\n    and remove your data from our servers.\n  </@description>\n</Dialog>","tags":["Dialog"],"parts":[{"name":"description"},{"name":"footer"},{"name":"title"},{"name":"trigger","param":"Record<string, unknown>"}],"props":[{"name":"aria-label","type":"string | undefined","required":false,"description":"Human readable label for the dialog, in event the dialog title is not rendered"},{"name":"closeOnEscape","type":"boolean | undefined","required":false,"default":"true","description":"Whether to close the dialog when the escape key is pressed"},{"name":"closeOnInteractOutside","type":"boolean | undefined","required":false,"default":"true","description":"Whether to close the dialog when the outside is clicked"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"default":"false","description":"The initial open state of the dialog when rendered.\nUse when you don't need to control the open state of the dialog."},{"name":"defaultTriggerValue","type":"string | null | undefined","required":false,"description":"The initial active trigger value when rendered.\nUse when you don't need to control the active trigger value."},{"name":"dir","type":"'ltr' | 'rtl' | undefined","required":false,"default":"ltr","description":"The document's text/writing direction."},{"name":"finalFocusEl","type":"(() => MaybeElement) | undefined","required":false,"description":"Element to receive focus when the dialog is closed"},{"name":"getRootNode","type":"(() => ShadowRoot | Document | Node) | undefined","required":false,"description":"A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron."},{"name":"ids","type":"ElementIds | undefined","required":false,"description":"The ids of the elements in the dialog. Useful for composition."},{"name":"initialFocusEl","type":"(() => MaybeElement) | undefined","required":false,"description":"Element to receive focus when the dialog is opened"},{"name":"modal","type":"boolean | undefined","required":false,"default":"true","description":"Whether to prevent pointer interaction outside the element and hide all content below it"},{"name":"open","type":"boolean | undefined","required":false,"description":"The controlled open state of the dialog"},{"name":"persistentElements","type":"(() => Element | null)[] | undefined","required":false,"description":"Returns the persistent elements that:\n- should not have pointer-events disabled\n- should not trigger the dismiss event"},{"name":"preventScroll","type":"boolean | undefined","required":false,"default":"true","description":"Whether to prevent scrolling behind the dialog when it's opened"},{"name":"restoreFocus","type":"boolean | undefined","required":false,"description":"Whether to restore focus to the element that had focus before the dialog was opened"},{"name":"role","type":"'dialog' | 'alertdialog' | undefined","required":false,"fixed":"dialog","description":"The dialog's role"},{"name":"showCloseButton","type":"boolean","required":false,"description":"Show the top-right close button. Defaults to true."},{"name":"trapFocus","type":"boolean | undefined","required":false,"default":"true","description":"Whether to trap focus inside the dialog when it's opened"},{"name":"triggerValue","type":"string | null | undefined","required":false,"description":"The controlled active trigger value"}],"events":[{"name":"onEscapeKeyDown","arg":"KeyboardEvent","description":"Function called when the escape key is pressed"},{"name":"onFocusOutside","arg":"FocusOutsideEvent","description":"Function called when the focus is moved outside the component"},{"name":"onInteractOutside","arg":"InteractOutsideEvent","description":"Function called when an interaction happens outside the component"},{"name":"onOpenChange","arg":"OpenChangeDetails","description":"Function to call when the dialog's open state changes"},{"name":"onPointerDownOutside","arg":"PointerDownOutsideEvent","description":"Function called when the pointer is pressed down outside the component"},{"name":"onRequestDismiss","arg":"LayerDismissEvent","description":"Function called when this layer is closed due to a parent layer being closed"},{"name":"onTriggerValueChange","arg":"TriggerValueChangeDetails","description":"Function to call when the active trigger changes"},{"name":"openChange","arg":"boolean"}],"keyboard":[{"keys":"Enter / Space","description":"Opens the dialog when focus is on the trigger."},{"keys":"Escape","description":"Closes the dialog (when `closeOnEscape` is true)."},{"keys":"Tab / Shift+Tab","description":"Cycles focus among the dialog's focusable elements; focus is trapped inside while open."}],"accessibilityNotes":["Rendered with `role=\"dialog\"` per the [WAI-ARIA Dialog (Modal) Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/); the title and description are linked to the content via `aria-labelledby`/`aria-describedby`, generated automatically from `@title`/`@description`.","Focus moves into the dialog on open and is trapped there until it closes; it's restored to the trigger element on close.","Both the Escape key and clicking outside the content close the dialog by default (`closeOnEscape`/`closeOnInteractOutside`, both `true`) — unlike `AlertDialog`, which disables both so the user must make an explicit choice."],"examples":[{"id":"dialog-demo","title":"Default","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\nimport TextInput from \"@marko-ui/shadcn/ui/input/input.marko\";\nimport Label from \"@marko-ui/shadcn/ui/label/label.marko\";\n\n<Dialog>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Edit Profile</Button>\n  </@trigger>\n  <@title>Edit profile</@title>\n  <@description>Make changes to your profile here. Click save when you're done.</@description>\n  <div class=\"grid gap-4\">\n    <div class=\"grid gap-2\">\n      <Label for=\"name-1\">Name</Label>\n      <TextInput id=\"name-1\" name=\"name\" value=\"Pedro Duarte\"/>\n    </div>\n    <div class=\"grid gap-2\">\n      <Label for=\"username-1\">Username</Label>\n      <TextInput id=\"username-1\" name=\"username\" value=\"@peduarte\"/>\n    </div>\n  </div>\n  <@footer>\n    <Button type=\"button\" variant=\"outline\">Cancel</Button>\n    <Button type=\"submit\">Save changes</Button>\n  </@footer>\n</Dialog>","description":"A dialog for editing profile details."},{"id":"dialog-close-button","title":"Custom close button","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\nimport TextInput from \"@marko-ui/shadcn/ui/input/input.marko\";\nimport Label from \"@marko-ui/shadcn/ui/label/label.marko\";\n\n<Dialog>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Share</Button>\n  </@trigger>\n  <@title>Share link</@title>\n  <@description>Anyone who has this link will be able to view this.</@description>\n  <div class=\"flex items-center gap-2\">\n    <div class=\"grid flex-1 gap-2\">\n      <Label for=\"link\" class=\"sr-only\">Link</Label>\n      <TextInput id=\"link\" value=\"https://example.com/docs/installation\" readonly/>\n    </div>\n  </div>\n  <@footer>\n    <Button type=\"button\">Close</Button>\n  </@footer>\n</Dialog>","description":"Replace the default close control with your own button in the footer."},{"id":"dialog-no-close-button","title":"No Close Button","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<Dialog showCloseButton=false>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">No Close Button</Button>\n  </@trigger>\n  <@title>No Close Button</@title>\n  <@description>This dialog doesn't have a close button in the top-right corner.</@description>\n</Dialog>","description":"Set `showCloseButton={false}` to hide the top-right close button."},{"id":"dialog-sticky-footer","title":"Sticky Footer","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<Dialog>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Sticky Footer</Button>\n  </@trigger>\n  <@title>Sticky Footer</@title>\n  <@description>This dialog has a sticky footer that stays visible while the content scrolls.</@description>\n  <div class=\"-mx-4 no-scrollbar max-h-[50vh] overflow-y-auto px-4\">\n    <for|index| of=Array.from({ length: 10 })>\n      <p class=\"mb-4 leading-normal\">\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do\n        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut\n        enim ad minim veniam, quis nostrud exercitation ullamco laboris\n        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in\n        reprehenderit in voluptate velit esse cillum dolore eu fugiat\n        nulla pariatur. Excepteur sint occaecat cupidatat non proident,\n        sunt in culpa qui officia deserunt mollit anim id est laborum.\n      </p>\n    </for>\n  </div>\n  <@footer>\n    <Button type=\"button\" variant=\"outline\">Close</Button>\n  </@footer>\n</Dialog>","description":"Keep actions visible while the content scrolls."},{"id":"dialog-scrollable-content","title":"Scrollable Content","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<Dialog>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"outline\">Scrollable Content</Button>\n  </@trigger>\n  <@title>Scrollable Content</@title>\n  <@description>This is a dialog with scrollable content.</@description>\n  <div class=\"-mx-4 no-scrollbar max-h-[50vh] overflow-y-auto px-4\">\n    <for|index| of=Array.from({ length: 10 })>\n      <p class=\"mb-4 leading-normal\">\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do\n        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut\n        enim ad minim veniam, quis nostrud exercitation ullamco laboris\n        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in\n        reprehenderit in voluptate velit esse cillum dolore eu fugiat\n        nulla pariatur. Excepteur sint occaecat cupidatat non proident,\n        sunt in culpa qui officia deserunt mollit anim id est laborum.\n      </p>\n    </for>\n  </div>\n</Dialog>","description":"Long content can scroll while the header stays in view."},{"id":"dialog-no-footer","title":"Without footer","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<Dialog>\n  <@trigger|props|>\n    <Button type=\"button\" ...props variant=\"destructive\">Delete account</Button>\n  </@trigger>\n  <@title>Are you absolutely sure?</@title>\n  <@description>This action cannot be undone. This will permanently delete your account and remove your data from our servers.</@description>\n</Dialog>","description":"The `@footer` tag is optional — omit it for a dialog with no actions row."},{"id":"dialog-rtl","title":"RTL","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\nimport TextInput from \"@marko-ui/shadcn/ui/input/input.marko\";\nimport Label from \"@marko-ui/shadcn/ui/label/label.marko\";\n\n<div dir=\"rtl\">\n  <Dialog dir=\"rtl\" class=\"sm:max-w-sm\">\n    <@trigger|props|>\n      <Button type=\"button\" ...props variant=\"outline\">فتح الحوار</Button>\n    </@trigger>\n    <@title>تعديل الملف الشخصي</@title>\n    <@description>قم بإجراء تغييرات على ملفك الشخصي هنا. انقر فوق حفظ عند الانتهاء.</@description>\n    <div class=\"grid gap-4\">\n      <div class=\"grid gap-2\">\n        <Label for=\"name-rtl\">الاسم</Label>\n        <TextInput id=\"name-rtl\" name=\"name\" value=\"Pedro Duarte\"/>\n      </div>\n      <div class=\"grid gap-2\">\n        <Label for=\"username-rtl\">اسم المستخدم</Label>\n        <TextInput id=\"username-rtl\" name=\"username\" value=\"@peduarte\"/>\n      </div>\n    </div>\n    <@footer>\n      <Button type=\"button\" variant=\"outline\">إلغاء</Button>\n      <Button type=\"submit\">حفظ التغييرات</Button>\n    </@footer>\n  </Dialog>\n</div>","description":"The `dir` prop is a native attribute pass-through — set it on `<Dialog>` to flip logical-property layout and typography for right-to-left languages. Every RTL example on this site does it the same way: a `dir=\"rtl\"` wrapper plus Arabic labels."},{"id":"dialog-controlled","title":"Controlled","source":"import Dialog from \"@marko-ui/shadcn/ui/dialog/dialog.marko\";\nimport Button from \"@marko-ui/shadcn/ui/button/button.marko\";\n\n<let/open=false/>\n\n<div class=\"flex items-center gap-4\">\n  <Dialog\n    open=open\n    openChange=(next) => { open = next; }\n  >\n    <@trigger|props|>\n      <Button type=\"button\" ...props variant=\"outline\">Open Dialog</Button>\n    </@trigger>\n    <@title>Controlled dialog</@title>\n    <@description>This dialog's open state is held in the parent and can be toggled from outside too.</@description>\n    <@footer>\n      <Button type=\"button\" variant=\"outline\" onClick=() => { open = false; }>Close</Button>\n    </@footer>\n  </Dialog>\n  <span class=\"text-sm text-muted-foreground\">open: ${String(open)}</span>\n</div>","description":"Zag machines are controlled: an `open` prop without a change handler never moves. Pair it with `openChange`.","essential":true}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","body":{},"nativeAttributes":"div","composition":"`<Dialog>` is one file exposing upstream's tree as slots: `@trigger` (render-prop, receives the trigger props to spread onto your own element — never nest a `<button>` inside it), `@title`, `@description`, the tag's own body (the content between the header and footer), and `@footer` (actions row). `@title`/`@description` are optional but recommended: omitting both drops the generated `dialog-header` wrapper entirely, and either one alone renders without the other. `showCloseButton` (default `true`) controls the generated top-right close button."}
