Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Enforces Vue 3 Composition API best practices with script setup, TypeScript, Pinia, and Vite.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/component-teleport.md
1---2title: Teleport Component Best Practices3impact: MEDIUM4impactDescription: Teleport renders content outside the component's DOM position, which is essential for overlays but affects styling and layout5type: best-practice6tags: [vue3, teleport, modal, overlay, positioning, responsive]7---89# Teleport Component Best Practices1011**Impact: MEDIUM** - `<Teleport>` renders part of a component's template in a different place in the DOM while preserving the Vue component hierarchy. Use it for overlays (modals, toasts, tooltips) or any UI that must escape stacking contexts, overflow, or fixed positioning constraints.1213## Task List1415- Teleport overlays to `body` or a dedicated container outside the app root16- Keep a shared target for similar UI (`#modals`, `#notifications`) and control layering with order or z-index17- Use `:disabled` for responsive layouts that should render inline on small screens18- Remember props, emits, and provide/inject still work through teleport19- Avoid relying on parent stacking contexts or transforms for teleported UI2021## Teleport Overlays Out of Transformed Containers2223When an ancestor has `transform`, `filter`, or `perspective`, fixed-position overlays can behave like they are locally positioned. Teleport escapes that context.2425**BAD:**26```vue27<template>28<div class="animated-container">29<button @click="open = true">Open</button>3031<!-- Broken: fixed positioning is scoped to the transformed parent -->32<div v-if="open" class="modal">Modal</div>33</div>34</template>3536<style>37.animated-container {38transform: translateZ(0);39}4041.modal {42position: fixed;43inset: 0;44z-index: 9999;45}46</style>47```4849**GOOD:**50```vue51<template>52<div class="animated-container">53<button @click="open = true">Open</button>5455<Teleport to="body">56<div v-if="open" class="modal">Modal</div>57</Teleport>58</div>59</template>60```6162## Responsive Layouts with `disabled`6364Use `:disabled` to render inline on mobile and teleport on larger screens:6566```vue67<script setup>68import { useMediaQuery } from '@vueuse/core'6970const isMobile = useMediaQuery('(max-width: 768px)')71</script>7273<template>74<Teleport to="body" :disabled="isMobile">75<nav class="sidebar">Navigation</nav>76</Teleport>77</template>78```7980## Logical Hierarchy Is Preserved8182Teleport changes DOM position, not the Vue component tree. Props, emits, slots, and provide/inject still work:8384```vue85<template>86<Teleport to="body">87<ChildPanel :message="message" @close="open = false" />88</Teleport>89</template>90```9192## Multiple Teleports to the Same Target9394Teleports to the same target append in declaration order:9596```vue97<template>98<Teleport to="#notifications">99<div>First</div>100</Teleport>101102<Teleport to="#notifications">103<div>Second</div>104</Teleport>105</template>106```107108Use a shared container to keep stacking predictable, and apply z-index only when you need explicit layering.109