# useImperativeDialog

## Usage

Hook for showing a dialog without managing open state. Call `dialog.show(content, options)` to open and `dialog.hide()` to close. Render `dialog.Host` once in your template.

```ts
import { useImperativeDialog } from '@astryx-vue/core/Dialog'
```

```vue
<script setup lang="ts">
import { DialogHeader, useImperativeDialog } from '@astryx-vue/core/Dialog'
import { h } from 'vue'

const dialog = useImperativeDialog({ width: 400 })
const DialogHost = dialog.Host

function askToDelete(): void {
  dialog.show(
    () => h(DialogHeader, { title: 'Delete project?', hasCloseButton: true }),
    { purpose: 'form' },
  )
}
</script>

<template>
  <button type="button" @click="askToDelete">
    Delete project
  </button>
  <DialogHost />
</template>
```

## Examples

Common configurations, variations, and states.

### Dialog — Confirmation

Asks the user to confirm a destructive action before it happens. Use before deleting projects, removing team members, revoking API keys, or any irreversible operation.

```vue
<script setup lang="ts">
import { Dialog, useImperativeDialog } from '@astryx-vue/core/Dialog'
import { h } from 'vue'
import ConfirmBody from './confirm-body.vue'

const dialog = useImperativeDialog({ width: 400, purpose: 'form' })

function openDialog() {
  dialog.show(() => h(ConfirmBody, { requestClose: () => dialog.hide() }))
}
</script>

<template>
  <Dialog is-open is-inline :width="400" purpose="form">
    <ConfirmBody :request-close="openDialog" />
  </Dialog>
  <component :is="dialog.Host" />
</template>
```

### Dialog — Form

Collects user input without navigating away from the page. Uses purpose form so clicking the backdrop won't close it. Use for editing profiles, creating items, or updating settings inline.

```vue
<script setup lang="ts">
import { Dialog, useImperativeDialog } from '@astryx-vue/core/Dialog'
import { h } from 'vue'
import FormBody from './form-body.vue'

const dialog = useImperativeDialog({ purpose: 'form', width: 480 })

function openDialog() {
  dialog.show(() => h(FormBody, { requestClose: () => dialog.hide() }))
}
</script>

<template>
  <Dialog is-open is-inline purpose="form" :width="480">
    <FormBody :request-close="openDialog" />
  </Dialog>
  <component :is="dialog.Host" />
</template>
```

### Dialog — Required

Cannot be dismissed by Escape or backdrop click; the user must explicitly choose an action. Uses purpose required. Use for ownership transfers, legal acknowledgements, or critical decisions where skipping is not an option.

```vue
<script setup lang="ts">
import { Dialog, useImperativeDialog } from '@astryx-vue/core/Dialog'
import { h } from 'vue'
import RequiredBody from './required-body.vue'

const dialog = useImperativeDialog({ purpose: 'required' })

function openDialog() {
  dialog.show(() => h(RequiredBody, { requestClose: () => dialog.hide() }))
}
</script>

<template>
  <Dialog is-open is-inline purpose="required">
    <RequiredBody :request-close="openDialog" />
  </Dialog>
  <component :is="dialog.Host" />
</template>
```

### Dialog — Scrollable

Constrains the dialog height and scrolls the body when content overflows. Use for terms and conditions, license agreements, changelogs, or any long-form content the user needs to review before accepting.

```vue
<script setup lang="ts">
import { Dialog, useImperativeDialog } from '@astryx-vue/core/Dialog'
import { h } from 'vue'
import ScrollBody from './scroll-body.vue'

const dialog = useImperativeDialog({ maxHeight: '50dvh' })

function openDialog() {
  dialog.show(() => h(ScrollBody, { requestClose: () => dialog.hide() }))
}
</script>

<template>
  <Dialog is-open is-inline :max-height="360">
    <ScrollBody :request-close="openDialog" />
  </Dialog>
  <component :is="dialog.Host" />
</template>
```

## Parameters

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultOptions` | `ImperativeDialogOptions` | `{}` | Options used by every `show()` call: the same as `Dialog` props minus `isOpen`. A call can pass its own options, which are merged over these. |

## Returns

| Name | Type | Description |
| --- | --- | --- |
| `show` | `(content: () => VNodeChild, options?: ImperativeDialogOptions) => void` | Show the dialog with the given content. Options are the same as `Dialog` props minus `isOpen` and the content. |
| `hide` | `() => void` | Hide the dialog. |
| `isOpen` | `Readonly<Ref<boolean>>` | Whether the dialog is currently open. |
| `Host` | `Component` | The dialog element. Render it once in your template: `<component :is="dialog.Host" />`. |

## Options

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `width` | `number \| string` | — | Preferred width. Numbers are pixels, strings are used as-is. The fullscreen variant ignores it. |
| `maxHeight` | `number \| string` | — | Maximum height. Numbers are pixels, strings are used as-is. The fullscreen variant ignores it. |
| `position` | `DialogPosition` | centered | Static position. Inline edges use `start` and `end`, which mirror under RTL. |
| `variant` | `'standard' \| 'fullscreen'` | `'standard'` | A standard dialog is sized by `width` and `maxHeight`; a fullscreen one fills the viewport. |
| `purpose` | `'info' \| 'form' \| 'required'` | `'info'` | How the dialog closes. `required` disables Escape and the backdrop; `form` keeps Escape and disables the backdrop; `info` allows both. |
| `padding` | `DialogPadding` | theme default | Padding step, matching the `--astryx-spacing-*` tokens. |
