Dialog Message para Quasar

🇺🇸 English | 🇧🇷 Versão em português

npm version license Vue Quasar TypeScript Node

Extensión Quasar para diálogos modales de mensaje (alertas y confirmación) en apps Vue 3 + Quasar, con API imperativa basada en composable.

Tabla de contenidos

En 30 segundos

Flujo base recomendado:

  1. Instalar la extensión en tu app Quasar (quasar ext add).
  2. Asegurar que el boot de Pinia del host corre antes que el boot de esta extensión.
  3. Importar useDialogMessage() donde muestres feedback al usuario.
  4. Llamar await message.success() (preset i18n) o await message.success({ text: '...' }); confirm: const ok = await message.confirm({ text: '...' }).

La extensión registra boots y CSS en el proyecto host automáticamente tras quasar ext add.

Qué es y qué incluye

Diálogo modal global controlado por useDialogMessage() — no es un componente embebible.

Requisitos y compatibilidad

Item Valor
Node >= 20.0.0
Quasar ^2.6.0
Vue ^3.4.18
Pinia ^2.0.11 | ^3.0.0
Formato del paquete ES modules
CLI recomendado @quasar/app-vite ^2.x o ^3.x

El boot de Pinia del host debe ejecutarse antes del boot de esta extensión.

Instalación en app Quasar

quasar ext add @benjaminor-dev/dialog-message

Remover:

quasar ext remove @benjaminor-dev/dialog-message

Tras quasar ext add, la extensión registra boots y CSS en tu app automáticamente. No necesitas pasos adicionales en una instalación normal desde npm.

Qué agrega la extensión al host

Recursos que instala o registra la extensión:

Recurso Ruta npm
Boot del diálogo ~@benjaminor-dev/quasar-app-extension-dialog-message/boot/dialog
Estilos ~@benjaminor-dev/quasar-app-extension-dialog-message/main.css
Defaults boot (host) src/boot/bor/bor-dialog-message-defaults.ts — creado en install; Skip/Overwrite si ya existe

Install (quasar ext add / invoke): crea src/boot/bor/bor-dialog-message-defaults.ts (o .js) y lo registra en quasar.configboot: [] automáticamente. No hace falta editarlo a mano en una instalación normal. El boot de paquete (boot/dialog) y main.css los inyecta la extensión en cada dev/build (no aparecen como entradas cortas en quasar.config).

Remove (quasar ext remove): elimina el defaults boot y su entrada en quasar.config.

Orden de boots mínimo:

1. Pinia (host)
2. Dialog Message — boot/dialog
3. bor/bor-dialog-message-defaults (host)

En quasar.config solo verás bor/bor-dialog-message-defaults; el boot boot/dialog lo añade el runner al compilar.

El boot monta el diálogo en el documento y conecta la store de Pinia del host. No necesitas importar DialogMessage en App.vue.

Defaults globales (boot)

Evita repetir títulos, iconos, labels y medidas en cada llamada. Prioridad: opciones por llamada → boot del host → i18n (locale / $q.lang / en).

Tras quasar ext add, revisa src/boot/bor/bor-dialog-message-defaults.ts — plantilla con instrucciones de idioma en el comentario del archivo.

// src/boot/bor/bor-dialog-message-defaults.ts
import { configureDialogMessageDefaults } from "@benjaminor-dev/quasar-app-extension-dialog-message";

configureDialogMessageDefaults({
  // locale: "es", // descomenta para fijar un idioma concreto en 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",
    },
  },
});

Idioma (i18n)

Built-in en, es y pt para títulos, textos y labels de presets (success, info, warn, error, confirm). Por defecto sigue $q.lang; sin idioma Quasar, cae en en.

Resolución de locale: boot locale → prefijo de $q.lang.isoName (es*es, pt*pt) → en.

Resolución de textos: opciones por llamada → boot presets.<variant> → boot messages → catálogo built-in → en. Iconos y colores default vienen de visuales built-in; override visual en boot presets.

Opción Cuándo usarla
framework.lang en quasar.config.ts Recomendado — alinea Dialog Message con Quasar
locale: 'es' en boot Fijar un idioma concreto (en | es | pt); ignora cambios de $q.lang
messages / presets en boot Override parcial (un preset o un label)

Ejemplo español en toda la app:

// quasar.config.ts
framework: {
  lang: "es",
},

Override de un preset (visual + texto):

configureDialogMessageDefaults({
  presets: {
    confirm: { title: "¿Eliminar registro?", acceptLabel: "Eliminar" },
  },
});

Override i18n sin cambiar iconos:

configureDialogMessageDefaults({
  messages: {
    acceptLabel: "Entendido",
    presets: { warn: { title: "Atención", text: "Revisa los datos" } },
  },
});

configureDialogMessage es alias de configureDialogMessageDefaults.

Opción boot Default built-in Descripción
locale (sigue $q.lang) Fija en | es | pt para textos de presets
messages (por locale) Override parcial i18n (presets.success.title, …)
acceptLabel "OK" (i18n) Fallback global del botón Aceptar
cancelLabel "No" (i18n) Fallback global del botón Cancelar en confirm
width "420px" Ancho máximo de la card
persistent true Bloquea cierre con backdrop / Esc
zIndex 7000 Capa del diálogo respecto al resto de la UI
gap "1rem" Espacio icono ↔ título ↔ texto
actionsGap "2rem" Espacio bloque de texto ↔ botones
font.sizeTitle "1.4rem" CSS font-size del título
font.sizeText "1.2rem" CSS font-size del cuerpo
font.family "Arial, sans-serif" CSS font-family del título y texto
buttonStyle Ver boot plantilla Colores y variantes de botones por tema (light / dark)
presets.<variant> (i18n + iconos) Override de title, text, icon, iconColor, labels

Cada preset incluye title, text y labels por idioma. Override en boot solo si necesitas personalizar iconos o textos de dominio.

Variantes de preset: success, info, warn, error, confirm.

Prioridad por campo: llamadapreset (boot)i18nglobal (boot). Dentro de botones, buttonStyle.<tema> gana sobre acceptColor / cancelColor planos del mismo nivel.

Uso rápido

<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(); // preset i18n (title + text)
    // await message.success({ text: "Se ha guardado el registro" });
  } catch (error) {
    await message.error({ text: "No se pudo guardar" });
  }
}

async function onDelete(item: { id: string }) {
  const confirmed = await message.confirm({
    title: "Eliminar registro",
    text: "Se eliminará el registro seleccionado. ¿Deseas continuar?",
  });
  if (!confirmed) return;

  await api.delete(item.id);
  await message.success({ text: "Registro eliminado" });
}
</script>

<template>
  <q-btn label="Guardar" @click="onSave" />
  <q-btn label="Eliminar" color="negative" @click="onDelete({ id: '1' })" />
</template>

Alerta con override puntual de título e icono:

await message.info({
  title: "Aviso importante",
  text: "Revisa los datos antes de continuar",
  icon: "campaign",
  iconColor: "warning",
});

Confirm con override de botones solo en dark:

const ok = await message.confirm({
  text: "¿Deseas continuar?",
  buttonStyle: {
    dark: { cancelColor: "grey-4" },
  },
});
if (!ok) return;

Side-effect al aceptar (p. ej. logout):

await message.warn({
  text: "Tu sesión expirará en 5 minutos",
  onAccept: async () => {
    await auth.refreshSession();
  },
});

TypeScript en tu IDE

No memorices la API: deja que el autocompletado te guíe.

Si algo no aparece en autocompletado, suele ser una prop inexistente o un import incorrecto — revisa el entrypoint principal antes de buscar en el README.

API pública

Punto de entrada: useDialogMessage().

import { useDialogMessage } from "@benjaminor-dev/quasar-app-extension-dialog-message";

const message = useDialogMessage();

Métodos

Método Retorno Descripción
success(options?) Promise<void> Alerta de éxito (preset success; options opcional)
info(options?) Promise<void> Alerta informativa
warn(options?) Promise<void> Alerta de advertencia
error(options?) Promise<void> Alerta de error
confirm(options?) Promise<boolean> Confirmación con dos botones; true = confirmar
hide() void Cierra sin onAccept; en confirm resuelve false

Estado reactivo (solo lectura)

Ref Descripción
visible Si el diálogo está visible

Opciones por llamada (DialogMessageOptions)

Campo Descripción
title? Título; omite → preset del boot; "" oculta el título
text? Cuerpo del mensaje
icon? Icono Material Icons (Quasar)
iconColor? Color del icono: string o { light?, dark? }
acceptLabel? Label del botón principal
acceptColor? Color Quasar del botón principal (plano; ambos temas)
acceptVariant? Variante Quasar: flat | outline | unelevated | push
buttonStyle? Override parcial { light?, dark? } de colores/variantes de botones
onAccept? Callback al pulsar Aceptar / Confirmar

DialogMessageConfirmOptions extiende lo anterior con:

Campo Descripción
cancelLabel? Label del botón Cancelar
cancelColor? Color Quasar del botón Cancelar (plano)
cancelVariant? Variante Quasar del botón Cancelar
onCancel? Callback al pulsar Cancelar

Presets visuales

Configura cada preset en presets del boot (o usa los built-in).

Preset Uso típico Icono default Color default
success Operación completada check_circle positive
info Aviso neutral info primary
warn Atención / precaución warning warning
error Fallo o error error negative
confirm Pregunta sí/no antes de actuar back_hand primary

Constante exportada: DIALOG_MESSAGE_VARIANTS — lista de variantes válidas.

Icono y botones por tema

El diálogo resuelve colores según $q.dark.isActive (light / dark).

Icono — iconColor

En boot (por preset) o por llamada:

iconColor: { light: "negative", dark: "red-4" }
// o plano (mismo color en ambos temas):
iconColor: "positive"

Botones — buttonStyle

Global en boot (aplica a todos los presets) o parcial por preset / llamada:

buttonStyle: {
  light: {
    acceptColor: "primary",
    acceptVariant: "unelevated",
    cancelColor: "primary",
    cancelVariant: "outline",
  },
  dark: {
    acceptColor: "primary",
    acceptVariant: "unelevated",
    cancelColor: "white",
    cancelVariant: "outline",
  },
}

Campos por tema en buttonStyle: acceptColor, acceptVariant, cancelColor, cancelVariant.

Built-in de variantes: Aceptar → unelevated, Cancelar → outline.

Alertas vs confirmación

Aspecto Alertas (successerror) Confirm (confirm)
Botones Uno (Aceptar) Dos (Cancelar + Confirmar)
Promise void al aceptar boolean (true / false)
Orden UX (LTR) Cancelar izquierda, Confirmar derecha
hide() Cierra sin callback Resuelve false
Labels default presets.<variant>.acceptLabel (p. ej. "OK") presets.confirm.acceptLabel / cancelLabel

Solo puede haber un diálogo visible a la vez. Una nueva llamada cierra la sesión anterior (confirm pendiente resuelve false).

Tipos TypeScript exportados

Desde el entrypoint principal:

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";
Tipo Uso
DialogMessageApi Retorno de useDialogMessage()
ExtensionLocale "en" | "es" | "pt" — boot locale
DialogMessageI18nMessages Forma de boot messages (labels + presets anidados)
PartialDialogMessageI18nMessages Override parcial de boot messages
DialogMessageOptions Argumento de success, info, warn, error
DialogMessageConfirmOptions Argumento de confirm()
DialogMessageDefaults Opciones de configureDialogMessageDefaults
DialogMessagePresetConfig Campos de cada entrada en presets
DialogMessagePresetsDefaults Mapa parcial presets
DialogMessageFontDefaults { family?, sizeTitle?, sizeText? }
DialogMessageButtonStyleConfig { light?, dark? } con estilos de botones
DialogMessageButtonThemeStyle Colores/variantes de botones en un tema
DialogMessageButtonVariant "flat" | "outline" | "unelevated" | "push"
DialogMessageThemeColor { light?, dark? } para colores por tema
DialogMessageThemeColorValue string o DialogMessageThemeColor (iconColor)
DialogMessageThemeMode "light" | "dark"
DialogMessageVariant "success" | "info" | "warn" | "error" | "confirm"
ResolvedDialogMessageDefaults Defaults mergeados (referencia / avanzado)

También se exportan configureDialogMessage (alias), resolveDialogMessageMessages, resolveExtensionLocale, BUILTIN_DIALOG_MESSAGE_DEFAULTS y DIALOG_MESSAGE_API_KEY (clave provide del boot para integraciones avanzadas).

Entrypoints públicos

Lo que importas en tu código:

Entrypoint Propósito
@benjaminor-dev/quasar-app-extension-dialog-message useDialogMessage, configureDialogMessageDefaults, helpers i18n (resolveDialogMessageMessages, resolveExtensionLocale), tipos y DIALOG_MESSAGE_VARIANTS

Boot (boot/dialog) y estilos (main.css) los registra la extensión en quasar.config al instalar — no hace falta importarlos a mano en una instalación normal.

Troubleshooting

Veo títulos o botones en inglés y quiero español (o portugués)

Sin configurar Quasar, los presets built-in están en inglés. Elige una opción:

// quasar.config.ts — recomendado
framework: {
  lang: "es",
},
// src/boot/bor/bor-dialog-message-defaults.ts — fijar solo el locale de Dialog Message
configureDialogMessageDefaults({ locale: "es" });

Boots o estilos no aparecen en quasar.config

En condiciones normales el install registra el defaults boot en boot: [] y el runner inyecta boot/dialog + CSS al compilar. Si falta el defaults boot:

npx quasar ext invoke @benjaminor-dev/dialog-message

Error: Pinia no inicializada

useDialogMessage() fuera de setup

Llámalo dentro de setup, otro composable o <script setup>. El boot debe haberse ejecutado (app montada).

El diálogo no muestra título

confirm() siempre resuelve false

El diálogo queda detrás de otro overlay

Ajusta zIndex en boot (default 7000) según la jerarquía de capas de tu app.

Cambié presets en boot y no se refleja

Reinicia el dev server. Confirma que editas src/boot/bor/bor-dialog-message-defaults.ts del host, no solo la plantilla de la extensión.


MIT © Benjamín Olvera R.