vuejs_dialogs_modals 18 Q&As

Vue.js Dialogs Modals FAQ & Answers

18 expert Vue.js Dialogs Modals answers researched from official documentation. Every answer cites authoritative sources you can verify.

unknown

18 questions
A

Teleport renders component content outside current DOM hierarchy, essential for modals to avoid CSS stacking issues. Basic implementation:

. The to attribute accepts CSS selector (to="body", to="#app", to=".modal-container"). Why needed: modals defined deep in component tree inherit parent CSS (overflow: hidden, z-index stacking contexts), Teleport moves modal to document body, escaping these constraints. Vue 3.5+ features: (1) defer prop: waits for target to mount (useful for dynamic containers), (2) disabled prop: conditionally disable (render inline on mobile, teleport on desktop). Multiple teleports to same target: order preserved via append. Combine with Transition:
...
for animated modals. Always teleport modals to avoid z-index hell.

95% confidence
A

Accessible confirmation dialogs must support standard keyboard shortcuts per WCAG 2.1 guidelines. Required shortcuts: (1) Escape key: close dialog (most critical), (2) Tab/Shift+Tab: cycle focus within dialog (focus trap), (3) Enter key: activate focused button (typically 'Confirm'), (4) Space key: activate focused button. Implementation with Vue 3 Composition API: onMounted(() => { window.addEventListener('keydown', handleKeydown); }); onUnmounted(() => { window.removeEventListener('keydown', handleKeydown); }); const handleKeydown = (e: KeyboardEvent) => { if (e.key === 'Escape') close(false); if (e.key === 'Enter' && focusedElement === confirmButton) confirm(); }. Best practices: (1) Focus 'Cancel' button by default (safer, prevents accidental confirmation), (2) Highlight focused button visibly (outline, background color), (3) Arrow keys for button navigation (left/right). Avoid: requiring mouse for any action, keyboard traps user cannot escape, no visible focus indicators.

95% confidence
A

Z-index stacking context determines layering order of positioned elements. New stacking contexts created by: position (absolute/relative/fixed) + z-index, transform, opacity < 1, filter, will-change. Problem: z-index only works within same stacking context, child with z-index: 9999 cannot appear above parent's sibling with z-index: 2. Modal solution: use Teleport to move modal outside parent stacking contexts:

. Z-index strategy: define CSS variables: --z-dropdown: 100; --z-sticky: 200; --z-modal: 1000; --z-tooltip: 2000; --z-notification: 3000. Avoid random high values (z-index: 999999), causes maintenance nightmare. Debug stacking: browser DevTools shows stacking context hierarchy. Best practice: (1) Minimize positioned elements, (2) Use Teleport for overlays, (3) Document z-index scale in CSS comments, (4) Use CSS custom properties for consistency. If modal appears below content, check parent transform/opacity creating new stacking context.

95% confidence
A

Custom dialogs provide superior UX and functionality over native alert(). Key benefits: (1) Non-blocking: native alert() blocks JavaScript execution and UI rendering, custom dialogs use async/await without blocking, (2) Customizable: full control over styling, branding, animations, layout vs fixed browser chrome, (3) Accessibility: add ARIA attributes, focus management, keyboard navigation, screen reader support, (4) Rich content: include forms, images, complex HTML vs plain text only, (5) Consistent UX: same look across all browsers/OS vs native browser styling, (6) Better mobile experience: responsive design, touch-friendly buttons vs tiny native buttons, (7) Testable: easy to unit test custom components vs difficulty testing native alerts. Technical advantages: promise-based API (cleaner code), can programmatically close, support multiple simultaneous dialogs, integrate with state management (Pinia/Vuex). Native alert() only acceptable for quick debugging, never production code.

95% confidence
A

Use Vue 3 Composition API with onMounted/onUnmounted for proper event listener cleanup. Pattern: onMounted(() => { window.addEventListener('keydown', handleKeydown); }); onUnmounted(() => { window.removeEventListener('keydown', handleKeydown); }); const handleKeydown = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); }. Key modifiers in templates: @keydown.enter="submit", @keydown.esc="close", @keydown.ctrl.s.prevent="save" (Ctrl+S). System modifiers: .ctrl, .alt, .shift, .meta (Cmd on Mac). Exact modifier: @keydown.ctrl.exact prevents trigger when other keys pressed. VueUse composables: import { onKeyStroke } from '@vueuse/core'; onKeyStroke('Escape', () => close()); automatically handles cleanup. Global vs component listeners: window.addEventListener for app-wide shortcuts, @keydown on specific elements for component-scoped. Performance: use event.key (modern) not event.keyCode (deprecated). Prevent default: e.preventDefault() stops browser default behavior. Best practice: always remove listeners in onUnmounted to prevent memory leaks.

95% confidence
A

defineProps and defineEmits provide cleaner syntax and better TypeScript support in . Parent usage: Content then modal.value.open(). Benefits: built-in browser features (backdrop, Escape key handling, focus management), better accessibility than div-based modals. For complex use cases, use promise-based libraries like vue3-promise-dialog: const result = await openDialog(ConfirmDialog, { message: 'Delete?' }). Avoid native alert() because: blocks UI thread, not customizable, poor UX, no async/await support. Production pattern: combine

for simple modals + promise-based dialogs for async workflows.

95% confidence
A

Implement dialog queue system to prevent multiple overlapping modals. Strategy 1: Single dialog instance with queue. Use reactive queue: const dialogQueue = ref<DialogConfig[]>([]); const currentDialog = computed(() => dialogQueue.value[0]); function openDialog(config) { dialogQueue.value.push(config); } function closeDialog() { dialogQueue.value.shift(); }. Only render when currentDialog exists. Strategy 2: Disable trigger buttons when dialog open. Track open state: const isDialogOpen = ref(false);

95% confidence
A

Props and slots serve different purposes in modal components. Props: pass configuration data (title, size, closable, variant), typically simple types (string, boolean, number). Example: . Use props for: behavior flags, styling variants, static content. Slots: pass complex HTML content, child components, dynamic rendering. Example: <template #header>Custom Header<template #body>. Named slots provide flexibility: header, body, footer, actions slots for different modal sections. Default slot: simplest use case Simple content. Best practice: combine both - props for configuration, slots for content: <template #actions><button @click="confirm">Delete. Scoped slots: pass data from modal to parent: <template #footer="{ close }"><button @click="close">Done. Props = what the modal does, Slots = what the modal shows. This separation makes modals highly reusable.

95% confidence
A

Always remove event listeners in onUnmounted hook to prevent memory leaks. Leak pattern: onMounted(() => { window.addEventListener('resize', handleResize); }); // LEAK! No cleanup. Fixed pattern: const handleResize = () => { /* logic */ }; onMounted(() => { window.addEventListener('resize', handleResize); }); onUnmounted(() => { window.removeEventListener('resize', handleResize); }); // Cleanup. Important: use same function reference in add/remove (avoid anonymous functions). Best solution: VueUse's useEventListener: import { useEventListener } from '@vueuse/core'; useEventListener(window, 'resize', handleResize); // Auto cleanup! Other leak sources: (1) Intervals: const id = setInterval(() => {}, 1000); onUnmounted(() => clearInterval(id)); (2) Timeouts: const id = setTimeout(() => {}, 1000); onUnmounted(() => clearTimeout(id)); (3) Third-party libraries: onUnmounted(() => { chart.destroy(); map.remove(); }). Detect leaks: Chrome DevTools → Memory → Take heap snapshot before/after component mount/unmount, check for detached DOM nodes. Production best practice: use VueUse composables which handle cleanup automatically.

95% confidence
A

Use