Dialog Message for Quasar
🇪🇸 Versión en español | 🇧🇷 Versão em português
Quasar extension for modal message dialogs (alerts and confirmation) in Vue 3 + Quasar apps, with an imperative composable-based API.
Table of contents
- In 30 seconds
- What it is and what it includes
- Requirements and compatibility
- Install in a Quasar app
- What the extension adds to the host
- Global defaults (boot)
- Language (i18n)
- Quick start
- TypeScript in your IDE
- Public API
- Visual presets
- Icon and buttons by theme
- Alerts vs confirmation
- Exported TypeScript types
- Public entrypoints
- Troubleshooting
In 30 seconds
Recommended flow:
- Install the extension in your Quasar app (
quasar ext add). - Ensure the host Pinia boot runs before this extension’s boot.
- Import
useDialogMessage()where you show feedback to the user. - Call
await message.success()(i18n preset) orawait message.success({ text: '...' }); for confirm:const ok = await message.confirm({ text: '...' }).
The extension registers boots and CSS in the host project automatically after quasar ext add.
What it is and what it includes
Global modal dialog controlled by useDialogMessage() — not an embeddable component.
- Alert presets —
success,info,warn,error(single Accept button). - Confirmation —
confirm()with two buttons (Cancel / Confirm) andPromise<boolean>. - Defaults per preset in the host boot (
title,icon,iconColor, labels). - Built-in i18n
en,es,pt— presets and buttons follow$q.lang; boot overrides (locale,messages,presets). - Light / dark theme —
iconColor: { light, dark }and global or per-presetbuttonStyle. - Per-call override —
title,text,icon, colors, button variants, and labels. onAccept/onCancel— optional side-effects when buttons are pressed.hide()— imperative close without running callbacks.persistent— prevents closing via backdrop or Esc (configurable in boot).
Requirements and compatibility
| Item | Value |
|---|---|
| Node | >= 20.0.0 |
| Quasar | ^2.6.0 |
| Vue | ^3.4.18 |
| Pinia | ^2.0.11 | ^3.0.0 |
| Package format | ES modules |
| Recommended CLI | @quasar/app-vite ^2.x or ^3.x |
The host Pinia boot must run before this extension’s boot.
Install in a Quasar app
quasar ext add @benjaminor-dev/dialog-message
Remove:
quasar ext remove @benjaminor-dev/dialog-message
After quasar ext add, the extension registers boots and CSS in your app automatically. No extra steps are needed for a normal npm install.
What the extension adds to the host
Resources installed or registered by the extension:
| Resource | npm path |
|---|---|
| Dialog boot | ~@benjaminor-dev/quasar-app-extension-dialog-message/boot/dialog |
| Styles | ~@benjaminor-dev/quasar-app-extension-dialog-message/main.css |
| Boot defaults (host) | src/boot/bor/bor-dialog-message-defaults.ts — created on install; Skip/Overwrite if it already exists |
Install (quasar ext add / invoke): creates src/boot/bor/bor-dialog-message-defaults.ts (or .js) and registers it in quasar.config → boot: [] automatically. No manual editing needed in a normal install. Package boot (boot/dialog) and main.css are injected on every dev/build (they do not appear as short entries in quasar.config).
Remove (quasar ext remove): removes the defaults boot and its quasar.config entry.
Minimum boot order:
1. Pinia (host)
2. Dialog Message — boot/dialog
3. bor/bor-dialog-message-defaults (host)
In quasar.config you only see bor/bor-dialog-message-defaults; the package boot/dialog is added by the extension runner at compile time.
The boot mounts the dialog in the document and connects the host Pinia store. You do not need to import DialogMessage in App.vue.
Global defaults (boot)
Avoid repeating titles, icons, labels, and measurements on every call. Priority: per-call options → host boot → i18n (locale / $q.lang / en).
After quasar ext add, review src/boot/bor/bor-dialog-message-defaults.ts — template with language instructions in the file comment.
// src/boot/bor/bor-dialog-message-defaults.ts
import { configureDialogMessageDefaults } from "@benjaminor-dev/quasar-app-extension-dialog-message";
configureDialogMessageDefaults({
// locale: "es", // uncomment to pin a specific language for Dialog Message
width: "420px",
persistent: true,
zIndex: 7000,
gap: "1rem",
actionsGap: "2rem",
font: {
family: "Arial, sans-serif",
sizeTitle: "1.4rem",
sizeText: "1.2rem",
},
buttonStyle: {
light: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "primary",
cancelVariant: "outline",
},
dark: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "white",
cancelVariant: "outline",
},
},
});
Language (i18n)
Built-in en, es, and pt for preset titles, texts, and labels (success, info, warn, error, confirm). By default follows $q.lang; without a Quasar language, falls back to en.
Locale resolution: boot locale → $q.lang.isoName prefix (es* → es, pt* → pt) → en.
Text resolution: per-call options → boot presets.<variant> → boot messages → built-in catalog → en. Icons and default colors come from built-in visuals; override visuals in boot presets.
| Option | When to use it |
|---|---|
framework.lang in quasar.config.ts |
Recommended — aligns Dialog Message with Quasar |
locale: 'es' in boot |
Pin a specific language (en | es | pt); ignores $q.lang changes |
messages / presets in boot |
Partial override (one preset or one label) |
Spanish across the whole app:
// quasar.config.ts
framework: {
lang: "es",
},
Override a single preset (visual + text):
configureDialogMessageDefaults({
presets: {
confirm: { title: "Delete record?", acceptLabel: "Delete" },
},
});
Override i18n strings without changing icons:
configureDialogMessageDefaults({
messages: {
acceptLabel: "Got it",
presets: { warn: { title: "Heads up", text: "Check your input" } },
},
});
configureDialogMessage is an alias of configureDialogMessageDefaults.
| Boot option | Built-in default | Description |
|---|---|---|
locale |
(follows $q.lang) |
Fixes en | es | pt for preset texts |
messages |
(per locale) | Partial i18n override (presets.success.title, …) |
acceptLabel |
"OK" (i18n) |
Global fallback for the Accept button |
cancelLabel |
"No" (i18n) |
Global fallback for the Cancel button in confirm |
width |
"420px" |
Maximum card width |
persistent |
true |
Blocks close via backdrop / Esc |
zIndex |
7000 |
Dialog layer relative to the rest of the UI |
gap |
"1rem" |
Spacing icon ↔ title ↔ text |
actionsGap |
"2rem" |
Spacing text block ↔ buttons |
font.sizeTitle |
"1.4rem" |
CSS font-size for the title |
font.sizeText |
"1.2rem" |
CSS font-size for the body |
font.family |
"Arial, sans-serif" |
CSS font-family for title and text |
buttonStyle |
See boot template | Button colors and variants per theme (light / dark) |
presets.<variant> |
(i18n + icons) | Override title, text, icon, iconColor, labels |
Each preset includes title, text, and labels per language. Boot presets can override both text and visuals (icon, iconColor, button styles); boot messages overrides text only.
Preset variants: success, info, warn, error, confirm.
Per-field priority: call → preset (boot) → i18n → global (boot). Within buttons, buttonStyle.<theme> wins over flat acceptColor / cancelColor at the same level.
Quick start
<script setup lang="ts">
import { useDialogMessage } from "@benjaminor-dev/quasar-app-extension-dialog-message";
const message = useDialogMessage();
async function onSave() {
try {
await api.save(formData);
await message.success(); // i18n preset (title + text)
// await message.success({ text: "Record saved" });
} catch (error) {
await message.error({ text: "Could not save" });
}
}
async function onDelete(item: { id: string }) {
const confirmed = await message.confirm({
title: "Delete record",
text: "The selected record will be deleted. Do you want to continue?",
});
if (!confirmed) return;
await api.delete(item.id);
await message.success({ text: "Record deleted" });
}
</script>
<template>
<q-btn label="Save" @click="onSave" />
<q-btn label="Delete" color="negative" @click="onDelete({ id: '1' })" />
</template>
Alert with a one-off title and icon override:
await message.info({
title: "Important notice",
text: "Review the data before continuing",
icon: "campaign",
iconColor: "warning",
});
Confirm with button override only in dark mode:
const ok = await message.confirm({
text: "Do you want to continue?",
buttonStyle: {
dark: { cancelColor: "grey-4" },
},
});
if (!ok) return;
Side-effect on accept (e.g. logout):
await message.warn({
text: "Your session will expire in 5 minutes",
onAccept: async () => {
await auth.refreshSession();
},
});
TypeScript in your IDE
Do not memorize the API — let autocomplete guide you.
useDialogMessage()returnsDialogMessageApi— methods and refs appear when you typemessage..- In
configureDialogMessageDefaults({ ... }), Ctrl+Space / Cmd+Space listspresets,buttonStyle,gap,font,zIndex, etc. - Inside
presets.success,presets.confirm, etc., the IDE suggeststitle,text,icon,iconColor,acceptLabel,cancelLabel,buttonStyle. - In
font, the IDE suggestsfamily,sizeTitle,sizeText. iconColoraccepts a plain string or{ light, dark };buttonStylegroups button colors and variants per theme.success/info/warn/erroraccept optionalDialogMessageOptions;confirmaccepts optionalDialogMessageConfirmOptions(addscancelLabel,cancelColor,cancelVariant,onCancel).- In boot,
localeaccepts"en" \| "es" \| "pt";messagesaccepts partialDialogMessageI18nMessages(global labels and nestedpresets.<variant>). confirm()resolvesPromise<boolean>; alert presets resolvePromise<void>when Accept is pressed.- Hover over a method: the tooltip shows parameters and JSDoc.
If something does not appear in autocomplete, it is usually a non-existent prop or a wrong import — check the main entrypoint before searching the README.
Public API
Entry point: useDialogMessage().
import { useDialogMessage } from "@benjaminor-dev/quasar-app-extension-dialog-message";
const message = useDialogMessage();
Methods
| Method | Return | Description |
|---|---|---|
success(options?) |
Promise<void> |
Success alert (success preset; optional options) |
info(options?) |
Promise<void> |
Informational alert |
warn(options?) |
Promise<void> |
Warning alert |
error(options?) |
Promise<void> |
Error alert |
confirm(options?) |
Promise<boolean> |
Confirmation with two buttons; true = confirm |
hide() |
void |
Closes without onAccept; on confirm resolves false |
Reactive state (read-only)
| Ref | Description |
|---|---|
visible |
Whether the dialog is visible |
Per-call options (DialogMessageOptions)
| Field | Description |
|---|---|
title? |
Title; omit → boot preset; "" hides the title |
text? |
Message body |
icon? |
Material Icons icon (Quasar) |
iconColor? |
Icon color: string or { light?, dark? } |
acceptLabel? |
Primary button label |
acceptColor? |
Quasar color for the primary button (flat; both themes) |
acceptVariant? |
Quasar variant: flat | outline | unelevated | push |
buttonStyle? |
Partial override { light?, dark? } of button colors/variants |
onAccept? |
Callback when Accept / Confirm is pressed |
DialogMessageConfirmOptions extends the above with:
| Field | Description |
|---|---|
cancelLabel? |
Cancel button label |
cancelColor? |
Quasar color for the Cancel button (flat) |
cancelVariant? |
Quasar variant for the Cancel button |
onCancel? |
Callback when Cancel is pressed |
Visual presets
Configure each preset in boot presets (or use the built-ins). Texts follow i18n; icons and default colors are locale-independent unless you override them in boot.
| Preset | Typical use | Default icon | Default color |
|---|---|---|---|
success |
Operation completed | check_circle |
positive |
info |
Neutral notice | info |
primary |
warn |
Attention / caution | warning |
warning |
error |
Failure or error | error |
negative |
confirm |
Yes/no question before acting | back_hand |
primary |
Exported constant: DIALOG_MESSAGE_VARIANTS — list of valid variants.
Icon and buttons by theme
The dialog resolves colors based on $q.dark.isActive (light / dark).
Icon — iconColor
In boot (per preset) or per call:
iconColor: { light: "negative", dark: "red-4" }
// or flat (same color in both themes):
iconColor: "positive"
Buttons — buttonStyle
Global in boot (applies to all presets) or partial per preset / call:
buttonStyle: {
light: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "primary",
cancelVariant: "outline",
},
dark: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "white",
cancelVariant: "outline",
},
}
Per-theme fields in buttonStyle: acceptColor, acceptVariant, cancelColor, cancelVariant.
Built-in variants: Accept → unelevated, Cancel → outline.
Alerts vs confirmation
| Aspect | Alerts (success … error) |
Confirm (confirm) |
|---|---|---|
| Buttons | One (Accept) | Two (Cancel + Confirm) |
| Promise | void on accept |
boolean (true / false) |
| UX order (LTR) | — | Cancel left, Confirm right |
hide() |
Closes without callback | Resolves false |
| Default labels | presets.<variant>.acceptLabel (e.g. "OK") |
presets.confirm.acceptLabel / cancelLabel |
Only one dialog can be visible at a time. A new call closes the previous session (pending confirm resolves false).
Exported TypeScript types
From the main entrypoint:
import {
useDialogMessage,
resolveDialogMessageMessages,
resolveExtensionLocale,
type DialogMessageApi,
type DialogMessageOptions,
type DialogMessageConfirmOptions,
type DialogMessageDefaults,
type DialogMessagePresetConfig,
type DialogMessagePresetsDefaults,
type DialogMessageFontDefaults,
type DialogMessageI18nMessages,
type PartialDialogMessageI18nMessages,
type DialogMessageButtonStyleConfig,
type DialogMessageButtonThemeStyle,
type DialogMessageButtonVariant,
type DialogMessageThemeColor,
type DialogMessageThemeColorValue,
type DialogMessageThemeMode,
type DialogMessageVariant,
type ExtensionLocale,
type ResolvedDialogMessageDefaults,
configureDialogMessageDefaults,
BUILTIN_DIALOG_MESSAGE_DEFAULTS,
DIALOG_MESSAGE_VARIANTS,
} from "@benjaminor-dev/quasar-app-extension-dialog-message";
| Type | Use |
|---|---|
DialogMessageApi |
Return type of useDialogMessage() |
ExtensionLocale |
"en" | "es" | "pt" — boot locale |
DialogMessageI18nMessages |
Shape of boot messages (labels + nested presets) |
PartialDialogMessageI18nMessages |
Partial boot messages override |
DialogMessageOptions |
Argument of success, info, warn, error |
DialogMessageConfirmOptions |
Argument of confirm() |
DialogMessageDefaults |
Options for configureDialogMessageDefaults |
DialogMessagePresetConfig |
Fields of each entry in presets |
DialogMessagePresetsDefaults |
Partial presets map |
DialogMessageFontDefaults |
{ family?, sizeTitle?, sizeText? } |
DialogMessageButtonStyleConfig |
{ light?, dark? } with button styles |
DialogMessageButtonThemeStyle |
Button colors/variants in one theme |
DialogMessageButtonVariant |
"flat" | "outline" | "unelevated" | "push" |
DialogMessageThemeColor |
{ light?, dark? } for per-theme colors |
DialogMessageThemeColorValue |
string or DialogMessageThemeColor (iconColor) |
DialogMessageThemeMode |
"light" | "dark" |
DialogMessageVariant |
"success" | "info" | "warn" | "error" | "confirm" |
ResolvedDialogMessageDefaults |
Merged defaults (reference / advanced) |
Also exported: configureDialogMessage (alias), resolveDialogMessageMessages, resolveExtensionLocale, BUILTIN_DIALOG_MESSAGE_DEFAULTS, and DIALOG_MESSAGE_API_KEY (boot provide key for advanced integrations).
Public entrypoints
What you import in your code:
| Entrypoint | Purpose |
|---|---|
@benjaminor-dev/quasar-app-extension-dialog-message |
useDialogMessage, configureDialogMessageDefaults, i18n helpers (resolveDialogMessageMessages, resolveExtensionLocale), types, and DIALOG_MESSAGE_VARIANTS |
Boot (boot/dialog) and styles (main.css) are registered by the extension in quasar.config on install — no manual import needed for a normal install.
Troubleshooting
I see titles or buttons in English and want Spanish (or Portuguese)
Without configuring Quasar, built-in presets are in English. Pick one option:
// quasar.config.ts — recommended
framework: {
lang: "es",
},
// src/boot/bor/bor-dialog-message-defaults.ts — pin Dialog Message locale only
configureDialogMessageDefaults({ locale: "es" });
Boots or styles do not appear in quasar.config
Under normal conditions, install registers the defaults boot in boot: [] and the runner injects boot/dialog + CSS at compile time. If the defaults boot is missing:
npx quasar ext invoke @benjaminor-dev/dialog-message
Error: Pinia not initialized
- Verify a Pinia boot in the host (
app.use(pinia)or equivalent). - In
quasar.config, the Pinia boot must run before this extension’sdialogboot.
useDialogMessage() outside setup
Call it inside setup, another composable, or <script setup>. The boot must have run (app mounted).
The dialog does not show a title
- Check if you passed
title: ""(hides the title on purpose). - If you omit
title,presets.<variant>.titlefrom boot is used.
confirm() always resolves false
- Check that you are not calling
hide()or opening another dialog before pressing a button. - A second call while the first is open closes the previous one with
false.
The dialog stays behind another overlay
Adjust zIndex in boot (default 7000) according to your app’s layer hierarchy.
I changed presets in boot and nothing updates
Restart the dev server. Confirm you are editing src/boot/bor/bor-dialog-message-defaults.ts in the host, not only the extension template.
MIT © Benjamín Olvera R.