{
  "tag": "ed-dialog",
  "kind": "component",
  "summary": "Dialogs, sometimes called \"modals\", appear above the page and block it until they are answered — or,\nwith `non-modal`, sit above it while the page keeps working.",
  "status": "experimental",
  "level": "molecule",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/dialog/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/dialog/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-button",
    "ed-icon"
  ],
  "use": [
    "A short, focused task or decision that must be resolved before the user continues — a form in an overlay, a detail view, or a confirmation",
    "Content important enough to justify blocking the rest of the page and pulling full attention to one thing",
    "A small, self-contained form (name a folder, pick a date range, edit a booking text) that does not warrant its own page",
    "An edit view or a detail view"
  ],
  "notFor": [
    {
      "when": "A severity-coded, decision-forcing confirm/cancel prompt with an icon and tone",
      "instead": "[Alert Dialog](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/alert-dialog)"
    },
    {
      "when": "A side panel of secondary content, settings, or details that sits alongside the page",
      "instead": "[Drawer](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/drawer)"
    },
    {
      "when": "A low-stakes, transient status message that needs no response",
      "instead": "a [Toast](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/toast-item) (or an inline [Notification](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/notification))"
    },
    {
      "when": "Small contextual content anchored to a trigger, like a hint or a menu",
      "instead": "a [Popover](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/popover) or [Dropdown](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/dropdown)"
    },
    {
      "when": "A long, multi-step, sequential process hand-built out of raw dialog content",
      "instead": "a [Wizard](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/wizard) hosted inside the dialog"
    }
  ],
  "rules": [
    {
      "id": "dialog/only-when-blocking-is-justified",
      "rule": "Reach for a dialog only when the message or task genuinely requires immediate attention and blocking the rest of the page is justified. For anything that can live inline, in a side panel, or as a passing notification, use a lighter surface instead.",
      "why": "A modal interrupts the user and takes over the screen."
    },
    {
      "id": "dialog/descriptive-title",
      "rule": "Give every dialog a descriptive title that names the specific context, never a generic \"Dialog\" or \"Hinweis\".",
      "check": "error"
    },
    {
      "id": "dialog/way-out",
      "rule": "Decide first what closing the dialog means. Where closing is the same as going back — a form, a message, a confirmation such as \"Delete order 2024-0842?\" with \"Delete order\" and \"Cancel\" — give it every way back: a Cancel button in the footer, Escape and `light-dismiss`. A footer button with `data-dialog=\"close\"` takes the place of the close button in the header, which the dialog then leaves out. Where the dialog asks for a decision between two paths that both lead on — \"Start the onboarding now?\" with \"Start onboarding\" and \"Skip onboarding\" — give it none of them, only the two labeled choices: set `without-close`, and cancel `ed-hide` until one of the two has been chosen — Escape, a click outside and `open = false` all report the dialog itself as `event.detail.source`, so the source cannot tell them apart. Never leave a dialog with no way out at all; one that blocks for a required loading step closes itself when the work finishes.",
      "why": "Closing that means going back loses nothing, so every way back works, as it does for the browser's own `confirm()`, where Escape answers Cancel. A dialog whose two answers both lead somewhere cannot be left without choosing one, and Escape would choose for the user. The WAI-ARIA dialog pattern lists \"Escape: Closes the dialog\"; the decision dialog departs from it on purpose, and is rare for that reason.",
      "check": "warning"
    },
    {
      "id": "dialog/footer-buttons",
      "rule": "Place the action that completes the dialog's task first, as the footer's accent button, so it renders leftmost in the right-aligned footer; every other footer button is `outlined`, and one of lower emphasis `plain`. For the accent limit and the explicit appearance see [`button/one-accent-per-scope`](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/button/usage#rule-button-one-accent-per-scope) — the open dialog is a scope of its own — and [`button/explicit-secondary-appearance`](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/button/usage#rule-button-explicit-secondary-appearance).",
      "check": "error"
    },
    {
      "id": "dialog/header-actions",
      "rule": "Keep icon-only to previous/next and help in the `header-actions` slot, beside the close button, each with an [`ed-tooltip`](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/tooltip) and an accessible name; every other dialog action carries a visible label."
    },
    {
      "id": "dialog/single-purpose",
      "rule": "Keep content to a single focused purpose that fits comfortably without scrolling where possible.",
      "check": "warning"
    },
    {
      "id": "dialog/unsaved-changes",
      "rule": "Warn the user with a secondary confirmation before closing a dialog that holds unsaved changes to records — never silently discard them, whichever way the dialog closes. The values of a bulk edit count, though nothing is written before they are applied. A dialog that only sets up an action — an export, a filter, a print — closes without asking: dropping its entries cancels the action and changes nothing."
    },
    {
      "id": "dialog/room-to-breathe",
      "rule": "Give the dialog room to breathe — wide enough that fields and labels are not cramped, never so narrow that labels wrap awkwardly and forms feel cramped.",
      "check": "warning"
    },
    {
      "id": "dialog/built-in-focus",
      "rule": "Don't add your own focus code for opening and closing — the component does it: focus moves into the dialog on open and back to the trigger on close.",
      "check": "warning"
    },
    {
      "id": "dialog/no-stacking",
      "rule": "Never open a dialog on top of another dialog. The unsaved-changes warning is the only accepted exception.",
      "why": "Nested or stacked modals disorient users.",
      "check": "error"
    },
    {
      "id": "dialog/no-toast-only-action",
      "rule": "Never put an action the user must be able to take only in a toast while the dialog is open — surface that action inside the dialog too.",
      "why": "A toast is easy to miss."
    },
    {
      "id": "dialog/draggable-needs-header",
      "rule": "Never combine a draggable dialog with a hidden header — the header is the drag handle.",
      "check": "error",
      "covered": true
    },
    {
      "id": "dialog/non-modal",
      "rule": "Never make a dialog `non-modal` when the page behind it must not be touched until the user answers.",
      "why": "Without the backdrop and the focus trap, nothing stops them.",
      "check": "warning"
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "open",
        "property": "open",
        "type": "boolean",
        "default": "false",
        "description": "Indicates whether the dialog is open. Toggle this attribute to show and hide the dialog."
      },
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The dialog's title as displayed in the header. You should always include a relevant title, as it is required for\nproper accessibility. If you need to display HTML, use the `label` slot instead. Not `title`: that global\nattribute shows a browser tooltip over the whole dialog."
      },
      {
        "name": "sublabel",
        "property": "sublabel",
        "type": "string",
        "default": "''",
        "description": "The dialog's subtitle. If you need to display HTML, use the `sublabel` slot instead."
      },
      {
        "name": "aria-label",
        "property": "ariaLabel",
        "type": "null | string",
        "default": "null",
        "description": "The dialog's accessible name, overriding the visible title. Mirrored onto the internal\nnative `<dialog>`, where the dialog role lives — an aria-label left on the host alone would\nsit on a role-less element and be ignored by assistive tech (house pattern: ed-checkbox)."
      },
      {
        "name": "dialog-role",
        "property": "dialogRole",
        "type": "null | 'alertdialog'",
        "default": "null",
        "description": "The role of the internal native `<dialog>`, overriding its implicit `dialog` role — set\n`alertdialog` for an interruption the user has to answer before continuing. It lands on the\nnative element rather than the host, where a second role would announce the dialog twice\n(`rules/api-design.md`), and it is applied in render(), so it is in place before showModal()\nruns — a role stamped afterwards can miss the announcement."
      },
      {
        "name": "dialog-description",
        "property": "dialogDescription",
        "type": "null | string",
        "default": "null",
        "description": "A description announced when the dialog opens, wired to the native `<dialog>` through\n`aria-describedby`. Use it when the describing text sits outside this element's shadow root,\nwhere an ID reference cannot reach it — a wrapper composing ed-dialog is the case. A dialog\nwhose own body carries the text needs nothing here."
      },
      {
        "name": "without-header",
        "property": "withoutHeader",
        "type": "boolean",
        "default": "false",
        "description": "Disables the header. This will also remove the default close button."
      },
      {
        "name": "without-close",
        "property": "withoutClose",
        "type": "boolean",
        "default": "false",
        "description": "Disables default close button."
      },
      {
        "name": "light-dismiss",
        "property": "lightDismiss",
        "type": "boolean",
        "default": "false",
        "description": "When enabled, the dialog will be closed when the user clicks outside of it. Has no effect on a\n`non-modal` dialog: the click lands on the page, which has no backdrop to catch it."
      },
      {
        "name": "non-modal",
        "property": "nonModal",
        "type": "boolean",
        "default": "false",
        "description": "Opens the dialog without blocking the page: no backdrop, no scroll lock, no focus trap, and the\ncontent behind it keeps taking clicks and keyboard focus. Use it for something the user works\n*with* the page on — a tool palette, a running log — rather than something they have to answer.\n\nThe dialog still lives in the top layer, so it is never covered by page content. `fullscreen`\nignores this: a dialog filling the viewport leaves nothing behind it to reach. `light-dismiss`\nstops working, because the UA sheet gives a popover's backdrop `pointer-events: none !important`\n(HTML Rendering, `:popover-open::backdrop`) and a click outside therefore reaches the page, not\nthe dialog."
      },
      {
        "name": "header-alignment",
        "property": "headerAlignment",
        "type": "'stacked' | 'inline'",
        "default": "'stacked'",
        "description": "This is for convenience to switch between stacked and inline headers when using a sublabel"
      },
      {
        "name": "resizable",
        "property": "resizable",
        "type": "boolean",
        "default": "false",
        "description": "Indicates whether the dialog is resizable"
      },
      {
        "name": "draggable",
        "property": "draggable",
        "type": "boolean",
        "default": "false",
        "description": "Indicates whether the dialog is draggable. The drag-handle is the header, so make sure to add one if draggable is used"
      },
      {
        "name": "fullscreen",
        "property": "fullscreen",
        "type": "boolean",
        "default": "false",
        "description": "Indicates whether the dialog is displayed fullscreen, occupying the entire viewport. While `fullscreen` is active,\n`resizable` and `draggable` are ignored; toggling it off restores their behavior."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [],
    "methods": [
      {
        "name": "connectedMoveCallback",
        "description": "An atomic move (`moveBefore`) runs this instead of the disconnect/reconnect pair. Engines\ndisagree on what it does to a modal `<dialog>` inside a shadow root, which this one always is:\nChromium 149 keeps it `:modal`, Firefox 151 leaves it `open` but no longer modal, with no\n`close` event — the page behind it live again, Escape and the toast stack gone with it. A\npopover survives the move in both. Reopen only what the move broke: reopening an intact dialog\nemits a native `close` and drops it out of the top layer for a frame."
      },
      {
        "name": "center",
        "description": "Returns the dialog to the middle of the viewport, where the CSS keeps it centered until it is\ndragged again — including while its content is still growing. A dialog that has not been dragged\nis already there, and a modal one is centered by the same rules, so this is a no-op for both."
      },
      {
        "name": "getPropertyDescriptor",
        "static": true,
        "parameters": [
          {
            "name": "name",
            "type": "PropertyKey"
          },
          {
            "name": "key",
            "type": "string | symbol"
          },
          {
            "name": "options",
            "type": "PropertyDeclaration"
          }
        ],
        "returns": "PropertyDescriptor | undefined",
        "description": "Wraps the accessor of reflected properties so they always hold a valid value, as a native\nreflected IDL attribute does (`button.type = undefined` reads `submit`):\n\n- A property that declares `useDefault` takes the first value set on an element for its\n  default. That value is its field initializer's: the constructor has finished before markup,\n  a framework or any other code can set anything. Every later `null` or `undefined` means what\n  a dropped prop means on a native element — the attribute is removed: with the attribute\n  there, it is removed and Lit's `useDefault` restores the default without writing it; without\n  one, the property is set to the default. A value set and cleared again before the element\n  updates still writes the default once, from the pending reflection.\n- A Boolean is coerced with `Boolean()`, so `undefined` is `false`.\n\nLit's `useDefault` keeps the initial default out of the DOM. Setting the default explicitly\nwrites it, as `button.type = 'submit'` writes `type`."
      }
    ],
    "events": [
      {
        "name": "ed-show",
        "react": "onEdShow",
        "description": "Emitted when the dialog opens. Cancelable; calling `preventDefault()` keeps it closed."
      },
      {
        "name": "ed-after-show",
        "react": "onEdAfterShow",
        "description": "Emitted after the dialog opens and all animations are complete."
      },
      {
        "name": "ed-hide",
        "react": "onEdHide",
        "type": "{ source: Element }",
        "description": "Emitted before the dialog closes. You can inspect `event.detail.source` to see which element caused the dialog to close. If the source is the dialog element itself, the user has pressed [[Escape]] or the dialog has been closed programmatically. Avoid using this unless closing the dialog will result in destructive behavior such as data loss. Cancelable; calling `preventDefault()` keeps it open."
      },
      {
        "name": "ed-after-hide",
        "react": "onEdAfterHide",
        "description": "Emitted after the dialog closes and all animations are complete."
      }
    ],
    "slots": [
      {
        "name": "",
        "description": "The dialog's main content."
      },
      {
        "name": "label",
        "description": "The dialog's title. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "sublabel",
        "description": "The dialog's subtitle. Alternatively, you can use the `sublabel` attribute."
      },
      {
        "name": "header-actions",
        "description": "Optional actions to add to the header. Works best with `<ed-button>`."
      },
      {
        "name": "footer",
        "description": "The dialog's footer, usually one or more buttons representing various options."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-dialog-spacing",
        "default": "var(--ed-panel-spacing)",
        "description": "The amount of space around and between the dialog's content."
      },
      {
        "name": "--ed-dialog-width",
        "description": "The preferred width of the dialog. Note that the dialog will shrink to accommodate smaller screens."
      },
      {
        "name": "--ed-dialog-min-width",
        "default": "15rem",
        "description": "The width the dialog does not shrink below, resized or on a small screen; never wider than the screen minus its margin."
      },
      {
        "name": "--ed-show-duration",
        "default": "var(--ed-transition-normal)",
        "description": "The animation duration when showing the dialog."
      },
      {
        "name": "--ed-hide-duration",
        "default": "var(--ed-transition-normal)",
        "description": "The animation duration when hiding the dialog."
      },
      {
        "name": "--ed-dialog-backdrop-filter",
        "description": "A CSS filter, e.g. `blur(4px)`, applied to the backdrop element behind the dialog."
      }
    ],
    "parts": [
      {
        "name": "panel",
        "description": "The dialog's surface, its native `<dialog>` element. Carries the frame, background and shadow."
      },
      {
        "name": "header",
        "description": "The dialog's header. This element wraps the title and header actions."
      },
      {
        "name": "header-actions",
        "description": "Optional actions to add to the header. Works best with `<ed-button>`."
      },
      {
        "name": "title",
        "description": "The dialog's title."
      },
      {
        "name": "subtitle",
        "description": "The dialog's subtitle."
      },
      {
        "name": "close-button",
        "description": "The close button, a `<ed-button>`."
      },
      {
        "name": "close-button__base",
        "description": "The close button's exported `base` part."
      },
      {
        "name": "body",
        "description": "The dialog's body."
      },
      {
        "name": "footer",
        "description": "The dialog's footer."
      }
    ],
    "states": []
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/dialog/dialog.js';",
  "react": {
    "component": "EdDialog",
    "import": "import EdDialog from '@eurodata/eurodata-ui/dist/react/dialog/index.js';"
  }
}
