@anfo/nuxt-dialogs-plugin

Nuxt module that auto-scans a directory for Vue dialog/drawer components and exposes them through a fully type-safe virtual module (virtual:dialogs). Dialog apps automatically inherit the Nuxt app context (Pinia, i18n, UI libraries, global components).
Install
npm install @anfo/nuxt-dialogs-plugin
Latest Version:1.0.2
Vue:3
License:MIT
Last Updated:Sep 9, 2026
Links: npm
Maintainer: longjiahui

@anfo/nuxt-dialogs-plugin

A Nuxt module that auto-scans a directory for Vue dialog/drawer components and exposes them through a fully type-safe virtual module (virtual:dialogs). Dialogs are mounted programmatically into isolated Vue app instances — no <Teleport> boilerplate, no global store, automatic cleanup on close.

Nuxt-native extras — dialog apps automatically inherit the Nuxt app's context, so Pinia, i18n, UI libraries, global components and directives work inside dialogs with zero wiring. dialogs and the runtime composables are auto-imported.

This is the Nuxt counterpart of @anfo/vite-dialogs-plugin — it is a standalone package and does not depend on it.

Installation

npm install -D @anfo/nuxt-dialogs-plugin

Quick Start

1. Register the module — nuxt.config.ts

export default defineNuxtConfig({
  modules: ["@anfo/nuxt-dialogs-plugin"],

  // Optional — these are the defaults
  dialogs: {
    dir: "dialogs", // relative to srcDir
    // pattern: /(Dialog|Drawer)\.vue$/,
    // inheritNuxtApp: true,
  },
});

2. Create a dialog component

Every .vue file whose name ends with Dialog.vue or Drawer.vue inside your dir becomes a key on the dialogs object. No tsconfig changes are needed — the module generates the type declarations for you.

<!-- dialogs/ConfirmDialog.vue -->
<script setup lang="ts">
import {
  useDialogContext,
  createDialogExpose,
  type DialogExposed,
} from "@anfo/nuxt-dialogs-plugin/runtime";

defineProps<{ message: string }>();

const { resolve, reject } = useDialogContext<boolean>();

defineExpose<DialogExposed<boolean>>(createDialogExpose<boolean>());
</script>

<template>
  <div class="overlay">
    <div class="box">
      <p>{{ message }}</p>
      <button @click="resolve(true)">Confirm</button>
      <button @click="resolve(false)">Cancel</button>
    </div>
  </div>
</template>

3. Open dialogs from anywhere

dialogs is auto-imported — no import statement needed:

<script setup lang="ts">
const result = await dialogs.ConfirmDialog({ message: "Delete this item?" });
if (result.type === "resolve" && result.value) {
  // confirmed
}

// Or chain callbacks
dialogs
  .ConfirmDialog({ message: "Are you sure?" })
  .resolve((value) => console.log("resolved:", value))
  .reject((reason) => console.log("rejected:", reason));
</script>

Context inheritance — why dialogs "just work"

Each dialog is mounted into its own isolated createApp() instance. By default (inheritNuxtApp: true) the module captures the Nuxt app and clones its context — global components, directives and provides — onto every dialog app. That means everything your Nuxt app registered is available inside dialogs automatically:

  • Pinia stores (@pinia/nuxt)
  • i18n (@nuxtjs/i18n — $t, translations)
  • UI libraries (Element Plus, PrimeVue, Vuetify… registered via Nuxt plugins)
  • Global components and directives
  • The nuxtApp itself — useNuxtApp(), useRoute()… work inside dialogs

Set inheritNuxtApp: false to keep dialogs fully isolated (parity with plain Vite projects), and register exactly what you need with configureDialogs():

// plugins/dialogs.ts
export default defineNuxtPlugin((nuxtApp) => {
  configureDialogs({
    use: [
      (app) => {
        app.config.globalProperties.$something = "...";
      },
    ],
  });
});

Both plugin objects ({ install(app) {} }) and plain (app) => void functions are accepted.

Module Options

Option Type Default Description
dir string "dialogs" Directory containing dialog components; relative paths resolve against srcDir.
pattern RegExp /(Dialog|Drawer)\.vue$/ RegExp to identify which files are dialogs.
inheritNuxtApp boolean true Dialog apps inherit the Nuxt app's context (components, directives, provides).

Auto-imports

Name From Description
dialogs virtual:dialogs Open dialogs — dialogs.ConfirmDialog(props).
useDialogContext ./runtime Get { resolve, reject } inside a dialog component.
createDialogExpose ./runtime Typed expose helper for defineExpose.
configureDialogs ./runtime Register extra plugins for every dialog app.

Package Exports

Specifier Contents
@anfo/nuxt-dialogs-plugin Nuxt module
@anfo/nuxt-dialogs-plugin/runtime Types, useDialogContext, createDialogExpose, configureDialogs, DialogExposed

SSR

Dialogs are DOM-only. Calling dialogs.* during server-side rendering is safe — it warns and settles as { type: "reject", reason } instead of crashing the render. Open dialogs from event handlers or onMounted.

Do not import virtual:dialogs from Nitro server code (server/api, server/routes) — the virtual module is only available in the app build.

Project Structure

<srcDir>/
├── dialogs/              ← your dialog components (configurable)
│   ├── ConfirmDialog.vue
│   ├── AlertDialog.vue
│   └── UserDrawer.vue
└── nuxt.config.ts

How It Works

  1. On startup the module registers a Vite plugin, a tiny runtime plugin (context capture), auto-imports and a type template.
  2. The Vite plugin generates a virtual module (virtual:dialogs) that imports each component through the #dialogs-components alias and wraps it in mountDialog().
  3. mountDialog() creates an isolated createApp() instance per call, inherits the Nuxt app context, provides a DialogController, mounts it into a temporary <div>, and returns a Promise-based handle.
  4. When the component calls resolve(value) or reject(reason), the app is unmounted and the host element removed automatically.
  5. A .d.ts type template is written into .nuxt/ so every dialogs.* entry is typed end-to-end — props, return value, and callbacks. It regenerates when dialog files are added or removed during dev.

See SKILL.md for step-by-step examples covering all dialog patterns.

License

MIT

Related Packages

nuxt-yup

yup implementation for nuxt

2,981 4
nuxt-google-auth

Google Identity Services integration for Nuxt 3 & 4 with a simple composable and...

19,921 3
@ciphera-net/pulse-nuxt

Add Pulse Analytics — privacy-first web analytics — to a Nuxt site with one modu...

505 0
@unocss/nuxt

Nuxt module for UnoCSS

3,181,743 18,982
nuxt-tawk-to

Nuxt module for integrating Tawk.to live chat widget.

1,519 8

Version History

Version Released Vue License
1.0.2 ^3.3.0 MIT
1.0.1 ^3.3.0 MIT
1.0.0 ^3.3.0 MIT