Components
- Accordion new
- ActionSheet new
- Alert new
- Alert Dialog new
- Angle Slider new
- Autocomplete new
- Avatar new
- Badge new
- Breadcrumb new
- Button new
- Button Group new
- Card new
- Carousel new
- Checkbox new
- Clipboard new
- Collapsible new
- Color Picker new
- Date Input new
- Date Picker new
- Dialog new
- DialogCaller new
- Drawer beta
- Editable new
- Empty new
- Field new
- Fieldset new
- File Upload new
- Filters new
- Floating Panel new
- Hover Card new
- Image new
- Image Cropper new
- Input new
- Input Group new
- Json Tree View new
- Kbd new
- Listbox new
- Marquee new
- Menu new
- Number Input new
- Pagination new
- Password Input new
- PhoneField new
- Pin Input new
- Popover new
- Progress Circular new
- Progress Linear new
- Qr Code new
- Radio Group new
- Rating Group new
- Scroll Area new
- ScrollSpy new
- Segment Group new
- Select new
- Separator new
- Sidebar new
- Signature Pad new
- Skeleton new
- Slider new
- Splitter new
- Steps new
- Switch new
- Table new
- Tabs new
- Tags Input new
- Textarea new
- Timeline new
- Timer new
- Toast new
- Toc new
- Toggle new
- Toggle Group new
- Tooltip new
- Tour new
- Tree View new
- Typography new
Features
- Programmatic API — Register a component once with
useDialogCaller(), thenawait caller.call(props)from any handler - Promise-based results — Components finish calls with
call.resolve()orcall.reject(); the outer promise always resolves (shape configurable) - Stack support — Nested and concurrent dialogs mount as separate stack entries with automatic z-index layering
- Optional dialog shell —
DialogCaller.DialogShellwires open state and external dismiss for Ark UI dialogs
Installation
Install from the Vuzeno registry:
bunx --bun shadcn-vue@latest add https://vuzeno.com/r/dialog-caller.json
npx shadcn-vue@latest add https://vuzeno.com/r/dialog-caller.json
yarn dlx shadcn-vue@latest add https://vuzeno.com/r/dialog-caller.json
pnpm dlx shadcn-vue@latest add https://vuzeno.com/r/dialog-caller.json
Setup
Mount the host once in your app root:
<script setup lang="ts">
import { DialogCaller } from "@/components/ui/dialog-caller";
</script>
<template>
<NuxtPage />
<DialogCaller.Host />
</template>
Usage
Register a dialog component once, then call it imperatively:
<script setup lang="ts">
import { useDialogCaller } from "@/components/ui/dialog-caller";
import DeleteConfirmDialog from "./DeleteConfirmDialog.vue";
const deleteDialog = useDialogCaller(DeleteConfirmDialog, {
exitDuration: 250,
resultShape: "cancelled",
});
async function onDelete(item: Item) {
const result = await deleteDialog.call({ name: item.name });
if (!result.cancelled && result.data) {
await api.delete(item.id);
}
}
</script>
Inside the called component, use useDialogCallerContext() and assign it to call:
<script setup lang="ts">
const props = defineProps<{ name: string }>();
const call = useDialogCallerContext<boolean>();
</script>
<template>
<DialogCaller.DialogShell>
<Dialog.Content>
<Dialog.Title>Delete {{ props.name }}?</Dialog.Title>
<Dialog.Actions>
<Button @click="call.reject('cancel')">Cancel</Button>
<Button @click="call.resolve(true)">Delete</Button>
</Dialog.Actions>
</Dialog.Content>
</DialogCaller.DialogShell>
</template>
Composition
DialogCaller.Host
└── (dynamic stack entries)
DialogCaller.Provider
└── custom host wiring via useDialogCallerHost()
DialogCaller.DialogShell
└── Dialog.Content
└── your dialog UI
Examples
Delete confirmation
Use a single useDialogCaller registration for the whole table — no dialog duplicated per row:
Nested dialogs
Edit the form, then cancel with unsaved changes. The confirmation dialog stacks on top while the form stays mounted:
API
useDialogCaller(component, options?)
Returns { call(props), reject() }.
| Option | Type | Default | Description |
|---|---|---|---|
id | string | component name | Registry key for idempotent registration |
exitDuration | number | 200 | Milliseconds to keep the instance mounted after resolve/reject (exit animation) |
resultShape | "cancelled" | "data" | "raw" | "cancelled" | Shape of the value returned by call() |
defaultRejectValue | unknown | null | Value returned on reject when resultShape is "raw" |
useDialogCallerContext()
Returns { props, phase, resolve, reject, id }. Assign to call and use call.resolve() / call.reject() without destructuring.
Result shapes
resultShape | After call.resolve(data) | After call.reject(reason?) |
|---|---|---|
"cancelled" | { cancelled: false, data, reason: null } | { cancelled: true, data: null, reason? } |
"data" | { data } | { data: null } |
"raw" | data | defaultRejectValue |
Notes
- Each
call()mounts a new stack entry. For HTTP-heavy dialogs, fetch data from props (e.g. withwatch) rather than inonMounted. DialogCaller.Hostmust be mounted before callingcall()— otherwise an error is thrown.