Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.2 KiB
4.2 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Teleport Preserves Logical Component Hierarchy | LOW | Understanding that Teleport only changes DOM structure, not Vue's component tree | best-practice |
|
Teleport Preserves Logical Component Hierarchy
Impact: LOW - A common misconception is that Teleport breaks the Vue component relationship. In reality, <Teleport> only alters the rendered DOM structure, not the logical hierarchy. Props, events, provide/inject, and Vue Devtools all work as if the component wasn't teleported.
Task Checklist
- Continue using props and events normally with teleported components
- Use provide/inject across teleported boundaries
- Check Vue Devtools for component location (shows logical parent, not DOM location)
Key Concept:
<!-- ParentComponent.vue -->
<template>
<div class="parent">
<Teleport to="body">
<!-- ChildComponent is logically still a child of ParentComponent -->
<!-- even though it renders in <body> -->
<ChildComponent
:message="parentMessage"
@update="handleUpdate"
/>
</Teleport>
</div>
</template>
<script setup>
import { provide, ref } from 'vue'
const parentMessage = ref('Hello from parent')
// Provide still works across teleport
provide('theme', 'dark')
function handleUpdate(value) {
// Events bubble up through logical hierarchy, not DOM
console.log('Received from teleported child:', value)
}
</script>
<!-- ChildComponent.vue -->
<template>
<div class="modal">
<p>{{ message }}</p>
<p>Theme: {{ theme }}</p>
<button @click="$emit('update', 'new value')">Update</button>
</div>
</template>
<script setup>
import { inject } from 'vue'
// Props work normally
defineProps(['message'])
// Inject works across teleport boundary
const theme = inject('theme')
// Emit works normally
defineEmits(['update'])
</script>
What Teleport Changes vs. Preserves
| Aspect | Changed? | Notes |
|---|---|---|
| DOM position | Yes | Content moves to to target |
| CSS inheritance | Yes | Styles inherit from new DOM parent |
| Props | No | Work exactly as without Teleport |
| Events (emit) | No | Bubble through logical hierarchy |
| Provide/Inject | No | Work across teleport boundaries |
| Vue Devtools | No | Shows logical component tree |
| Slots | No | Work normally |
| Template refs | No | Parent can ref teleported content |
Practical Example: Modal with Form
<!-- ModalForm.vue -->
<template>
<Teleport to="body">
<div v-if="visible" class="modal-overlay">
<form @submit.prevent="handleSubmit" class="modal-form">
<!-- Slot content receives parent's scope -->
<slot :formData="formData" />
<button type="submit">Submit</button>
<button type="button" @click="$emit('close')">Cancel</button>
</form>
</div>
</Teleport>
</template>
<script setup>
import { reactive } from 'vue'
defineProps(['visible'])
const emit = defineEmits(['close', 'submit'])
const formData = reactive({})
function handleSubmit() {
emit('submit', formData)
}
</script>
<!-- ParentPage.vue -->
<template>
<button @click="showModal = true">Add User</button>
<!-- Events and slots work as expected despite teleportation -->
<ModalForm
:visible="showModal"
@close="showModal = false"
@submit="handleFormSubmit"
>
<template #default="{ formData }">
<input v-model="formData.name" placeholder="Name" />
<input v-model="formData.email" placeholder="Email" />
</template>
</ModalForm>
</template>
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
function handleFormSubmit(data) {
console.log('Form submitted:', data)
showModal.value = false
}
</script>
Vue Devtools Behavior
In Vue Devtools, teleported components appear under their logical parent:
App
└── ParentPage
└── ModalForm <-- Shows here (logical parent)
└── form content
Not under their DOM location:
// This is NOT how it appears in Devtools
body
└── ModalForm <-- Does NOT show here