itc-header-append
v1.0.0
Published
A Vue 3 component that teleports content to a header append slot using Vue's Teleport feature
Maintainers
Readme
Header Append Component
A lightweight Vue 3 component that uses Vue's Teleport feature to append content to a header slot. Perfect for adding dynamic content to your application header from anywhere in your component tree.
Features
- ✅ Vue 3 Teleport - Uses Vue's built-in Teleport component
- ✅ TypeScript Ready - Full TypeScript support
- ✅ Lightweight - Minimal footprint, no dependencies
- ✅ Slot Support - Pass any content via default slot
- ✅ SSR Safe - Handles mounting safely for server-side rendering
Installation
npm install @itc/header-append
# or
pnpm install @itc/header-appendRequirements
- Vue 3.x
- Quasar 2.x (optional, but recommended for Quasar projects)
These are peer dependencies and must be installed in your project.
Usage
Basic Example
First, ensure you have a target element with id headerAppend in your layout/header:
<!-- In your layout/header component -->
<template>
<q-header>
<q-toolbar>
<q-toolbar-title>My App</q-toolbar-title>
<!-- Target element for teleport -->
<div id="headerAppend"></div>
</q-toolbar>
</q-header>
</template>Then use the component anywhere in your app:
<script setup>
import { HeaderAppend } from '@itc/header-append'
</script>
<template>
<div>
<HeaderAppend>
<q-btn label="Action Button" color="primary" />
</HeaderAppend>
<!-- Rest of your content -->
<div>Your page content here</div>
</div>
</template>With Quasar Components
<template>
<HeaderAppend>
<q-btn-group>
<q-btn icon="search" color="primary" />
<q-btn icon="notifications" color="secondary" />
<q-btn icon="settings" color="accent" />
</q-btn-group>
</HeaderAppend>
</template>With Custom Content
<template>
<HeaderAppend>
<div class="custom-header-content">
<q-badge color="red" :label="notificationCount" />
<q-avatar>
<img src="avatar.jpg" />
</q-avatar>
</div>
</HeaderAppend>
</template>Conditional Rendering
<script setup>
import { ref } from 'vue'
import { HeaderAppend } from '@itc/header-append'
const showHeaderButton = ref(true)
</script>
<template>
<HeaderAppend v-if="showHeaderButton">
<q-btn label="Toggle" @click="showHeaderButton = false" />
</HeaderAppend>
</template>Props
This component doesn't accept any props. All content should be passed via the default slot.
Slots
Default Slot
The component wraps your content in its default slot. The content will be teleported to the #headerAppend target element.
<HeaderAppend>
<!-- Your content goes here -->
<q-btn label="Click me" />
</HeaderAppend>How It Works
- The component uses Vue's
Teleportfeature to move content to a target element - It waits for the component to mount before teleporting (SSR safe)
- Content is teleported to the element with id
headerAppend - The target element must exist in your DOM (typically in your layout/header)
Target Element Setup
You need to create a target element with id headerAppend in your application. Common places:
Quasar Layout
<template>
<q-layout view="hHh lpR fFf">
<q-header>
<q-toolbar>
<q-toolbar-title>My App</q-toolbar-title>
<div id="headerAppend"></div>
</q-toolbar>
</q-header>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>Custom Header
<template>
<header class="app-header">
<div class="header-content">
<h1>My App</h1>
<div id="headerAppend"></div>
</div>
</header>
</template>Examples
Navigation Menu in Header
<template>
<HeaderAppend>
<q-btn-dropdown label="Menu" color="primary">
<q-list>
<q-item clickable>
<q-item-section>Home</q-item-section>
</q-item>
<q-item clickable>
<q-item-section>About</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</HeaderAppend>
</template>User Profile in Header
<template>
<HeaderAppend>
<q-btn-dropdown flat>
<template v-slot:label>
<q-avatar size="32px">
<img src="user-avatar.jpg" />
</q-avatar>
<span class="q-ml-sm">John Doe</span>
</template>
<q-list>
<q-item clickable>
<q-item-section>Profile</q-item-section>
</q-item>
<q-item clickable>
<q-item-section>Settings</q-item-section>
</q-item>
<q-item clickable>
<q-item-section>Logout</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</HeaderAppend>
</template>Search Bar in Header
<template>
<HeaderAppend>
<q-input
v-model="searchText"
placeholder="Search..."
dense
outlined
style="min-width: 300px"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</HeaderAppend>
</template>Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues or questions, please visit: GitHub Issues
Development
Path Aliases
This template supports importing files using the src/ prefix without relative paths:
// ✅ Good - Using path alias
import { HEADER_APPEND_TARGET } from "src/consts";
import HeaderAppend from "src/components/HeaderAppend.vue";
// ❌ Avoid - Relative paths (still works, but not recommended)
import { HEADER_APPEND_TARGET } from "../consts";
import HeaderAppend from "./components/HeaderAppend.vue";Project Structure
├─ src/
│ ├─ components/ # Vue components
│ │ └─ HeaderAppend.vue
│ ├─ consts.ts # Constants
│ ├─ index.ts # Main export file
│ └─ vue-shim.d.ts # Vue type declarations
├─ dist/ # Build output (generated)
├─ package.json
├─ tsconfig.json
└─ vite.config.tsBuilding
Build for Production
pnpm run build
# or
npm run buildThis will:
- Compile TypeScript to JavaScript
- Bundle Vue components
- Generate both ES Modules (
.js) and CommonJS (.cjs) formats - Output to
dist/directory with preservedsrc/structure
Build Output Structure
dist/
└─ src/
├─ index.js # ES Module entry
├─ index.cjs # CommonJS entry
├─ components/
│ └─ ...
└─ ...Testing Locally
Option 1: Using pnpm link (Recommended)
In your plugin directory:
pnpm link --globalIn your test project:
pnpm link --global @itc/header-appendUse in your project:
<script setup> import { HeaderAppend } from "@itc/header-append"; </script>
Option 2: Using File Path
In your test project's
package.json:{ "dependencies": { "@itc/header-append": "file:../quasar-package-starter-kit-plugins-header-append" } }Install:
pnpm installUse in your project:
<script setup> import { HeaderAppend } from "@itc/header-append"; </script>
Development Workflow
For active development with auto-rebuild:
Run in watch mode:
pnpm run devChanges will rebuild automatically. Restart your test project's dev server to pick up changes.
Publishing to npm
Before Publishing
Update
package.json:- Set correct
name(must be unique on npm) - Update
version(follow semver) - Add
description,keywords,author,license - Verify
filesarray includes only what should be published:{ "files": ["dist", "README.md"] }
- Set correct
Build the package:
pnpm run buildTest the build locally (see Testing Locally section above)
Publishing Steps
Login to npm:
npm loginVerify you're logged in:
npm whoamiCheck what will be published:
npm pack --dry-runPublish:
npm publish --access public(Using
--access publicbecause it's a scoped package@itc/header-append)Verify on npm: Visit
https://www.npmjs.com/package/@itc/header-append
Version Management
Use npm version commands to bump versions:
# Patch version (1.0.0 → 1.0.1)
npm version patch
# Minor version (1.0.0 → 1.1.0)
npm version minor
# Major version (1.0.0 → 2.0.0)
npm version majorThen publish:
npm publish --access publicConfiguration
External Dependencies
By default, vue and quasar are marked as external (not bundled). To add more:
Update vite.config.ts:
rollupOptions: {
external: (id) => {
return (
id === "vue" ||
id === "quasar" ||
id.startsWith("@quasar/") ||
id.startsWith("quasar/") ||
id === "some-other-package"
); // Add here
};
}Build Formats
The template builds both ES Modules and CommonJS. To change formats:
Update vite.config.ts:
build: {
lib: {
formats: ["es", "cjs"]; // or ['es'], ['cjs'], etc.
}
}Troubleshooting
TypeScript Errors
- "Cannot find module 'src/...'": Restart TypeScript server
- "Cannot find module 'path'": Ensure
@types/nodeis installed - Path aliases not working: Check both
tsconfig.jsonandvite.config.tshave matching aliases
Build Errors
- "Rollup failed to resolve import": Add the package to
externalinvite.config.ts - "Preprocessor dependency not found": Install required preprocessors (e.g.,
sass-embeddedfor SCSS)
Import Errors in Test Project
- Ensure the package is built (
pnpm run build) - Check
package.jsonexports are correct - Verify the import path matches your exports
Component Not Appearing
- Ensure the target element with id
headerAppendexists in your DOM - Check that the component has mounted (it waits for
onMountedbefore teleporting) - Verify the target element is in the correct location (usually in your layout/header)
Happy coding! 🚀
