itc-breadcrumb
v1.0.1
Published
A flexible breadcrumb component with back button support for Vue 3 + Quasar applications
Maintainers
Readme
ITC Breadcrumb
A flexible breadcrumb component with back button support for Vue 3 + Quasar applications. Built on the Vue + Quasar Plugin Template with TypeScript, Vite, and path aliases support.
Features
- ✅ Vue 3 with Composition API
- ✅ Quasar Framework support
- ✅ TypeScript for type safety
- ✅ Vite for fast builds
- ✅ Path Aliases - Import without relative paths (e.g.,
src/components/...) - ✅ Dual Format Build - ES Modules and CommonJS
- ✅ Preserved Directory Structure - Maintains
src/structure in output - ✅ Breadcrumb Component - Customizable separator, color, gutter, alignment
- ✅ Back Button -
useBackButton()composable +<BackButton />render component - ✅ Common Store - Works with host project's store (boilerplate-quasar-v2) or package's own fallback store
- ✅ Plugin System -
app.use(itcBreadcrumb)for zero-config setup - ✅ Quasar Boot File - Drop-in support for Quasar CLI projects
Getting Started
Prerequisites
- Node.js 20.19+ or 22.12+
- pnpm (recommended) or npm/yarn
Installation
Clone or use this template:
git clone <your-repo-url> cd itc-breadcrumbInstall dependencies:
pnpm install # or npm installUpdate
package.json:- Change
nameto your package name - Update
version,description,author,license, andkeywords - Adjust
dependenciesanddevDependenciesas needed
- Change
Update
src/index.js:Export your main components/utilities:
export { default as Breadcrumb } from './components/Breadcrumb.vue' export { BackButton, useBackButton } from './utilities/backButton' export { useCommonStore, commonStoreActions, commonStoreGetters, commonStoreState } from './stores/common-store' export { itcBreadcrumb } from './plugin' export { DEFAULT_SEPARATOR, DEFAULT_COLOR } from './consts'
Peer Dependencies
This package requires Vue 3 and Quasar to be installed in your project:
npm install vue@^3.5.25 quasar@^2.18.6Consumer Installation
npm install itc-breadcrumb
# or
pnpm install itc-breadcrumb
# or
yarn add itc-breadcrumbUsage
Path Aliases
This template supports importing files using the src/ prefix without relative paths:
// ✅ Good - Using path alias
import { DEFAULT_SEPARATOR } from 'src/consts'
import Breadcrumb from 'src/components/Breadcrumb.vue'
import { useBackButton } from 'src/utilities/backButton'
// ❌ Avoid - Relative paths (still works, but not recommended)
import { DEFAULT_SEPARATOR } from '../consts'
import Breadcrumb from './components/Breadcrumb.vue'Adding More Path Aliases
To add additional path aliases (e.g., @/, @components/, etc.):
Update
tsconfig.json:{ "compilerOptions": { "baseUrl": ".", "paths": { "src/*": ["./src/*"], "@/*": ["./src/*"], "@components/*": ["./src/components/*"], "@utilities/*": ["./src/utilities/*"] } } }Update
vite.config.ts:resolve: { alias: { 'src': resolve(__dirname, './src'), '@': resolve(__dirname, './src'), '@components': resolve(__dirname, './src/components'), '@utilities': resolve(__dirname, './src/utilities') } }The
vite-tsconfig-pathsplugin will automatically read fromtsconfig.json, but explicit aliases in Vite config ensure build-time resolution works correctly.Restart your TypeScript server (in VS Code/Cursor: Cmd+Shift+P → "TypeScript: Restart TS Server")
Quick Start
Basic Breadcrumb:
<template>
<Breadcrumb :items="breadcrumbItems" />
</template>
<script setup>
import { Breadcrumb } from 'itc-breadcrumb'
const breadcrumbItems = [
{ label: 'Home', to: { name: 'home' } },
{ label: 'Products', to: { name: 'products' } },
{ label: 'Product Details' }
]
</script>With Back Button:
<script setup>
import { Breadcrumb, useBackButton } from 'itc-breadcrumb'
// Show back button in header — navigates to home on click
useBackButton({ name: 'home' })
const breadcrumbItems = [
{ label: 'Home', to: { name: 'home' } },
{ label: 'Details' }
]
</script>
<template>
<Breadcrumb :items="breadcrumbItems" />
</template>With Plugin (Recommended):
// main.js
import { createApp } from 'vue'
import { Quasar } from 'quasar'
import { itcBreadcrumb } from 'itc-breadcrumb'
import App from './App.vue'
const app = createApp(App)
app.use(Quasar, {})
app.use(itcBreadcrumb)
app.mount('#app')With Quasar Boot File:
boot: ['itc-breadcrumb']// src/boot/itc-breadcrumb.js
import { boot } from 'quasar/wrappers'
import { itcBreadcrumb } from 'itc-breadcrumb'
export default boot(({ app }) => {
app.use(itcBreadcrumb)
})API Reference
Breadcrumb Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| items | BreadcrumbItem[] | required | Array of breadcrumb items |
| separator | String | '/' | Separator character between items |
| color | String | 'primary' | Text color (Quasar color name) |
| activeColor | String | same as color | Active (last) item color |
| gutter | String | 'xs' | Spacing between items (none, xs, sm, md, lg, xl) |
| align | String | 'left' | Alignment (left, center, right, between, around, evenly) |
| customClass | String | '' | Custom CSS class for the breadcrumb |
| style | String \| Object | {} | Inline style |
| enableBackButton | Boolean | false | Enable back button directly from the component |
| routerParams | any | undefined | Router params for back navigation |
BreadcrumbItem
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| label | String | Yes | Display text |
| icon | String | No | Material icon name |
| to | String \| Object | No | Router link (string path or route object) |
| disable | Boolean | No | Disable the item |
useBackButton Composable
useBackButton(routerParams)| Param | Type | Description |
|-------|------|-------------|
| routerParams | any | Route params for back navigation. Supports { name: 'route' }, '/path', or { routerParams: ... } format |
Behavior:
- On mount: sets
commonStore.backButton = { show: true, routerParams } - On unmount: resets
commonStore.backButton = null - Works with host project's store or package's fallback store
BackButton Component
Render-function component. Place once in your layout header/toolbar.
<BackButton />- Shows an
arrow_backicon button whenuseBackButton()is active - Clicking navigates via vue-router (or falls back to
window.history.back()) - Includes a "Go Back" tooltip
Usage Examples
Example 1: Simple Breadcrumb
<template>
<Breadcrumb
:items="items"
separator=">"
color="grey-8"
active-color="primary"
/>
</template>
<script setup>
import { Breadcrumb } from 'itc-breadcrumb'
const items = [
{ label: 'Home', icon: 'home', to: '/' },
{ label: 'Settings', to: '/settings' },
{ label: 'Profile' }
]
</script>Example 2: Back Button in Layout
Layout:
<template>
<q-layout view="hHh lpR fFf">
<q-header elevated>
<q-toolbar>
<BackButton />
<q-toolbar-title>My App</q-toolbar-title>
</q-toolbar>
</q-header>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
<script setup>
import { BackButton } from 'itc-breadcrumb'
</script>Page:
<template>
<q-page class="q-pa-md">
<Breadcrumb :items="breadcrumbItems" />
<div class="text-h5 q-mt-md">Product Details</div>
</q-page>
</template>
<script setup>
import { Breadcrumb, useBackButton } from 'itc-breadcrumb'
// Back button appears in header, navigates to products list
useBackButton({ name: 'products' })
const breadcrumbItems = [
{ label: 'Home', to: '/' },
{ label: 'Products', to: '/products' },
{ label: 'Details' }
]
</script>Example 3: With Host Project's Common Store (boilerplate-quasar-v2)
If your project already has a Pinia common-store with backButton state and showBackButton() action:
// main.js
import { itcBreadcrumb } from 'itc-breadcrumb'
import { useCommonStore } from 'stores/common-store' // your project's store
const app = createApp(App)
app.use(pinia)
app.use(itcBreadcrumb)
// Override with your project's store
app.provide('itcCommonStore', useCommonStore())
app.mount('#app')Now useBackButton() will use your project's common store — the same store your layout reads from.
Example 4: enableBackButton Prop
Instead of calling useBackButton() separately, use the prop directly:
<template>
<Breadcrumb
:items="items"
enable-back-button
:router-params="{ name: 'home' }"
/>
</template>
<script setup>
import { Breadcrumb } from 'itc-breadcrumb'
const items = [
{ label: 'Home', to: { name: 'home' } },
{ label: 'Current Page' }
]
</script>Exports
// Main component
import { Breadcrumb } from 'itc-breadcrumb'
// Back button
import { BackButton, useBackButton } from 'itc-breadcrumb'
// Plugin
import { itcBreadcrumb } from 'itc-breadcrumb'
// Store utilities
import {
useCommonStore,
commonStoreActions,
commonStoreGetters,
commonStoreState
} from 'itc-breadcrumb'
// Constants
import { DEFAULT_SEPARATOR, DEFAULT_COLOR } from 'itc-breadcrumb'Constants
DEFAULT_SEPARATOR: Default breadcrumb separator ('/')DEFAULT_COLOR: Default breadcrumb color ('primary')
Project Structure
itc-breadcrumb/
├─ src/
│ ├─ components/
│ │ └─ Breadcrumb.vue # Main breadcrumb component
│ ├─ utilities/
│ │ └─ backButton.js # BackButton component + useBackButton composable
│ ├─ stores/
│ │ └─ common-store.js # Fallback reactive store
│ ├─ types/
│ │ └─ breadcrumb.ts # TypeScript type definitions
│ ├─ boot/
│ │ └─ itc-breadcrumb.js # Quasar boot file
│ ├─ examples/
│ │ └─ basicBreadcrumb.js # Example breadcrumb schemas
│ ├─ consts.js # Constants
│ ├─ plugin.js # Vue plugin
│ ├─ index.js # 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
├─ consts.js / .cjs
├─ plugin.js / .cjs
├─ components/
│ └─ Breadcrumb.vue.js / .cjs
├─ utilities/
│ └─ backButton.js / .cjs
└─ stores/
└─ common-store.js / .cjsTesting Locally
Option 1: Using pnpm link (Recommended)
In your plugin directory:
pnpm link --globalIn your test project:
pnpm link --global itc-breadcrumbUse in your project:
<script setup> import { Breadcrumb } from 'itc-breadcrumb' // or import { Breadcrumb } from 'itc-breadcrumb/src/components/Breadcrumb.vue' </script>
Option 2: Using File Path
In your test project's
package.json:{ "dependencies": { "itc-breadcrumb": "file:../path/to/itc-breadcrumb" } }Install:
pnpm installUse in your project:
<script setup> import { Breadcrumb } from 'itc-breadcrumb' </script>
Unlinking After Local Development
When you're done with local development and want to switch back to the published version (or remove the link):
For Option 1 (pnpm/npm link):
In your test project, unlink the package:
# For pnpm pnpm unlink --global itc-breadcrumb # For npm npm unlink itc-breadcrumbReinstall the package from npm (or your registry):
pnpm install itc-breadcrumb # or npm install itc-breadcrumbOptionally, unlink from global (in your plugin directory):
# For pnpm pnpm unlink --global # For npm npm unlink -gNote: This step is optional. The global link can remain for future development sessions.
For Option 2 (File Path):
Remove the file path dependency from your test project's
package.json:{ "dependencies": { // Remove or comment out: // "itc-breadcrumb": "file:../path/to/itc-breadcrumb" } }Reinstall the package from npm:
pnpm install itc-breadcrumb # or npm install itc-breadcrumb
Troubleshooting Unlinking
If you encounter issues after unlinking:
Clear
node_modulesand reinstall:rm -rf node_modules pnpm install # or npm installCheck for leftover symlinks:
# Check if symlink still exists ls -la node_modules/itc-breadcrumb # If it's still a symlink, remove it manually rm node_modules/itc-breadcrumb pnpm installVerify package source:
# Check where the package is coming from pnpm why itc-breadcrumb # or npm ls itc-breadcrumb
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"] }- 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 publishFor scoped packages (e.g.,
@itc/breadcrumb):npm publish --access publicVerify on npm:
Visit
https://www.npmjs.com/package/itc-breadcrumb
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 publishConfiguration
External Dependencies
By default, vue, quasar, and vue-router are marked as external (not bundled). To add more:
Update vite.config.ts:
rollupOptions: {
external: (id) => {
return (
id === 'vue' ||
id === 'quasar' ||
id === 'vue-router' ||
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.
}
}Handling External Dependencies
Using Quasar Extras and Icon Sets
If your plugin requires dependencies like @quasar/extras, FontAwesome icons, or other Quasar-related packages that may not be present in the target project, you should declare them as peer dependencies rather than regular dependencies.
Why Peer Dependencies?
- Smaller bundle size: External dependencies aren't bundled into your package
- Version control: Consumers control which versions to install
- Avoid conflicts: Prevents duplicate packages in the consumer's project
- Best practice: Standard approach for library/plugin packages
Step 1: Add Peer Dependencies
Update your package.json to include peer dependencies:
{
"peerDependencies": {
"quasar": "^2.18.6",
"vue": "^3.5.25",
"@quasar/extras": "^1.0.0"
},
"peerDependenciesMeta": {
"@quasar/extras": {
"optional": true
}
}
}Notes:
peerDependencies: Required dependencies that consumers must installpeerDependenciesMeta: Mark dependencies as optional if they're not always needed- Keep
quasarandvueindevDependenciesfor development, but also list them inpeerDependenciesfor consumers
Step 2: Ensure Externalization in Build Config
Your vite.config.ts should already externalize @quasar/ packages (this is already configured):
rollupOptions: {
external: (id) => {
return (
id === 'vue' ||
id === 'quasar' ||
id === 'vue-router' ||
id.startsWith('@quasar/') || // ✅ Already covers @quasar/extras
id.startsWith('quasar/')
)
}
}If you need to externalize additional packages, add them to the external function:
rollupOptions: {
external: (id) => {
return (
id === 'vue' ||
id === 'quasar' ||
id === 'vue-router' ||
id.startsWith('@quasar/') ||
id.startsWith('quasar/') ||
id === 'some-other-package' || // Add specific packages
id.startsWith('@some-scope/') // Or entire scopes
)
}
}Step 3: Document for Consumers
Add installation instructions to your README for consumers:
npm install itc-breadcrumb @quasar/extras
# or
pnpm install itc-breadcrumb @quasar/extrasQuasar Configuration:
For Quasar CLI projects (quasar.conf.js):
module.exports = function (ctx) {
return {
extras: [
'fontawesome-v6',
'material-icons-outlined'
]
}
}For Vite projects (quasar.config.js):
export default {
extras: [
'fontawesome-v6',
'material-icons-outlined'
]
}Step 4: Handle Missing Dependencies Gracefully (Optional)
If you want to provide fallbacks when dependencies aren't available, you can check for them:
<script setup>
import { computed } from 'vue'
const props = defineProps({
icon: { type: String, default: 'close' }
})
// Example: Fallback to Material Icons if FontAwesome not available
const safeIcon = computed(() => {
if (props.icon?.startsWith('fa-') || props.icon?.startsWith('fas ')) {
return props.icon
}
return props.icon
})
</script>Best Practices:
- ✅ Use peer dependencies for packages that should be provided by the consumer
- ✅ Use regular dependencies only for packages that are internal to your plugin
- ✅ Document all peer dependencies in your README
- ✅ Use Material Icons by default (built into Quasar) when possible
- ✅ Only require
@quasar/extraswhen you specifically need FontAwesome, Material Symbols, etc. - ❌ Don't bundle large dependencies like icon sets into your package
- ❌ Don't assume consumers have specific Quasar extras installed
Styling
The component uses Quasar's built-in styling. No additional CSS imports are required. The component will automatically use your Quasar theme.
Customization
You can customize the appearance by:
- Using Quasar theme variables in your
quasar.config.js - Props:
color,activeColor,gutter,align,customClass,style - Scoped styles in your parent component
- Quasar utility classes for layout adjustments
TypeScript
Full TypeScript support is included. Type definitions are in src/types/breadcrumb.ts:
import type {
BreadcrumbItem,
BackButtonState,
CommonStoreState,
CommonStoreContract
} from 'itc-breadcrumb/src/types/breadcrumb'
const items: BreadcrumbItem[] = [
{ label: 'Home', to: '/' },
{ label: 'Products' }
]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
Back Button Not Showing
- Ensure
<BackButton />is placed in your layout header - Verify
useBackButton()is called in your page component - Check that
itcBreadcrumbplugin is installed (app.use(itcBreadcrumb)) - If using host store, ensure
app.provide('itcCommonStore', useCommonStore())is called
Component Not Rendering
- Ensure Quasar is properly installed and configured
- Check that Vue 3 is being used (not Vue 2)
- Verify the import path:
import { Breadcrumb } from 'itc-breadcrumb'
Navigation Not Working on Back Button Click
- Ensure Vue Router is properly configured
- Check that
routerParamsis correctly set (e.g.,{ name: 'home' }) - Verify router instance is available
Styling Issues
- Ensure Quasar CSS is imported in your project
- Check Quasar theme configuration
- Verify no CSS conflicts with parent components
License
MIT
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Build and test locally
- Submit a pull request
Happy coding! 🚀
