# Feature: Dialog Runtime

## Intent

Problem: CSS can style Dialog markup but cannot provide production-ready open/close state, focus containment, keyboard dismissal, or lifecycle cleanup.
Users or stakeholders: legacy applications, server-rendered pages, QA, keyboard users, and future framework package maintainers.
Desired outcome: implement Dialog as the first complex runtime controller using the shared core and accessibility utilities.
Non-goals: redefine `.sui-dialog` styling, create a full modal framework, or manage application-specific form submission.

## Scope

In scope: trigger wiring, open/close state, cancellable events, focus trap, focus restoration, Escape dismissal, outside/backdrop dismissal, ARIA synchronization, and cleanup.
Out of scope: visual transitions, CSS tokens, generated dialog markup, and product-specific dialog copy.
Assumptions: `@seventh-ui/css` owns `.sui-dialog` classes and layout; this package enhances existing semantic dialog markup.

## Markup Hooks

- Root: `[data-sui-dialog]` or `[data-sui-component="dialog"]`.
- Trigger: `[data-sui-trigger="dialog"]` with `data-sui-target`.
- Close control: `[data-sui-dialog-close]` or `[data-sui-trigger="dialog-close"]`.
- State: native `open` when using `<dialog>`, otherwise `hidden`, `aria-hidden`, `aria-modal`, and `data-sui-state`.

## Behavior

1. Opening dispatches `sui:dialog:before-open`; cancellation blocks the open.
2. Closing dispatches `sui:dialog:before-close`; cancellation blocks the close.
3. Successful state changes dispatch `sui:dialog:open` and `sui:dialog:close`.
4. Open dialogs trap focus and restore focus to the trigger on close.
5. Escape closes the dialog unless disabled by option or hook.
6. Outside/backdrop dismissal is opt-in or driven by documented hooks.
7. Cleanup removes document listeners, focus traps, and trigger listeners.

## Accessibility

Align with WAI-ARIA dialog guidance. Prefer native `<dialog>` when markup provides it; otherwise maintain `role="dialog"`, `aria-modal`, hidden state, and labelled relationships without removing native semantics.

## Acceptance Examples

Scenario: trigger opens dialog
Given a trigger points at a dialog root
When the trigger is activated
Then the dialog opens, focus moves inside, and `sui:dialog:open` is emitted.

Scenario: blocked close
Given a listener prevents `sui:dialog:before-close`
When Escape is pressed
Then the dialog remains open and focus stays inside.
