NavigationBar
The NavigationBar component provides a flexible, responsive navigation bar with customizable content areas. It includes built-in support for system status, language switching, onboarding restart, and optional app switching, plus multiple slot areas for complete customization of the navigation layout.
Features
- Flexible Slot System: Multiple slots for left, center, and right sections
- System Status: Built-in system status indicator
- Language Switcher: Built-in language selection component
- System Status: Built-in system status indicator (shows only when offline)
- Onboarding Restart: Built-in button to restart the onboarding tour
- App Switcher: Optional app switcher when
otherAppsprop is provided - Toggle Visibility: Control individual built-in components via props
- Default Branding: App name displayed by default on the left
- Nested Slot Support: Fine-grained control over right section items
- Responsive Design: Adapts to mobile, tablet, and desktop screens
- i18n Integration: Automatic integration with Vue i18n
- Accessibility: Fully keyboard accessible with proper structure
Props
| Prop | Type | Default | Description |
|---|---|---|---|
otherApps | AppSwitcherApp[] | — | List of other apps to display in the AppSwitcher. If omitted, no AppSwitcher is shown. |
showAppSwitcher | boolean | true | Whether to show the AppSwitcher (requires otherApps to be provided). |
showSystemStatus | boolean | true | Whether to show the built-in SystemStatus component. |
showLanguageSelect | boolean | true | Whether to show the built-in LanguageSelect component. |
showOnboardingRestart | boolean | true | Whether to show the built-in OnboardingRestartButton component. |
AppSwitcherApp Type
interface AppSwitcherApp {
name: string;
/** Router path (internal SPA nav) or absolute URL (full app switch). */
to: string;
/** Nuxt Icon name, e.g. "i-lucide-mail". Takes precedence over `image`. */
icon?: string;
/** URL or public/ path to a raster image. Used only when `icon` is unset. */
image?: string;
/** Optional alt text for the image; defaults to `name`. */
alt?: string;
}Slots
| Slot | Description | Default Content |
|---|---|---|
left | Content for the left section of the navigation bar | App name from navigation.app translation |
center | Content for the center section | Empty |
right | Complete override of the right section | SystemStatus + LanguageSelect + OnboardingRestartButton + AppSwitcher (conditional) + nested slots |
rightPreItems | Items to appear before the system status (within default right section) | Empty |
rightPostItems | Items to appear after the app switcher (within default right section) | Empty |
Usage
Basic Implementation
Simple navigation bar with default elements:
<template>
<NavigationBar />
</template>This displays:
- App name on the left (from
navigation.apptranslation) - System status indicator on the right
- Language switcher on the right
- Onboarding restart button on the right
Hiding Built-in Components
Control which built-in components are visible using the boolean props:
<template>
<NavigationBar
:show-system-status="false"
:show-language-select="false"
:show-onboarding-restart="false"
/>
</template>With App Switcher
Provide a list of apps to display the AppSwitcher:
<script setup lang="ts">
import type { AppSwitcherApp } from "@dcc-bs/common-ui.bs.js/components";
const otherApps: AppSwitcherApp[] = [
{ name: "App A", url: "https://app-a.example.com" },
{ name: "App B", url: "https://app-b.example.com" },
];
</script>
<template>
<NavigationBar :other-apps="otherApps" />
</template>To hide the AppSwitcher while keeping other defaults:
<template>
<NavigationBar :other-apps="otherApps" :show-app-switcher="false" />
</template>With Custom Left Content
Replace the default app name with custom branding:
<template>
<NavigationBar>
<template #left>
<div class="flex items-center gap-3 ml-4">
<img src="/logo.svg" alt="Logo" class="h-8 w-8" />
<span class="text-xl font-bold">My App</span>
</div>
</template>
</NavigationBar>
</template>With Center Content
Add navigation links in the center:
<template>
<NavigationBar>
<template #center>
<nav class="flex items-center gap-4">
<NuxtLink to="/" class="hover:underline">Home</NuxtLink>
<NuxtLink to="/about" class="hover:underline">About</NuxtLink>
<NuxtLink to="/contact" class="hover:underline">Contact</NuxtLink>
</nav>
</template>
</NavigationBar>
</template>With Right Pre Items
Add items before the system status:
<template>
<NavigationBar>
<template #rightPreItems>
<AppSwitcher
:apps="apps"
footer-to="https://about.example.com/products/"
footer-label="More" />
</template>
</NavigationBar>
</template>With Right Post Items
Add items after the app switcher:
<script setup lang="ts">
import type { DropdownMenuItem } from '#ui/types';
import { SettingsButton } from '@dcc-bs/common-ui.bs.js/components';
const settingsItems = [
{
label: "Test Settings",
icon: "i-lucide-shield-check"
}
] as DropdownMenuItem[];
</script>
<template>
<NavigationBar>
<template #rightPostItems>
<SettingsButton :items="settingsItems" />
</template>
</NavigationBar>
</template>Complete Customization
Use all slots together:
<script setup lang="ts">
const { t } = useI18n();
</script>
<template>
<NavigationBar :other-apps="apps">
<template #left>
<div class="flex items-center gap-2 ml-4">
<img src="/logo.png" alt="Logo" class="h-10" />
<span class="text-xl font-bold">{{ t("app.name") }}</span>
</div>
</template>
<template #center>
<nav class="flex gap-6">
<NuxtLink to="/" class="font-medium">Dashboard</NuxtLink>
<NuxtLink to="/projects" class="font-medium">Projects</NuxtLink>
</nav>
</template>
<template #rightPreItems>
<UButton variant="ghost" icon="i-lucide-bell" size="sm" />
</template>
<template #rightPostItems>
<SettingsButton :items="settingsItems" />
</template>
</NavigationBar>
</template>Override Right Section Completely
Replace the entire right section if you don't want the default components:
<template>
<NavigationBar>
<template #right>
<div class="flex items-center gap-4 mr-4">
<span>Custom Right Content</span>
<button>Login</button>
<button>Sign Up</button>
</div>
</template>
</NavigationBar>
</template>WARNING
When you override the right slot, the rightPreItems and rightPostItems slots are not rendered, and you lose the default SystemStatus, LanguageSelect, OnboardingRestartButton, and AppSwitcher components unless you add them manually. The show* props also have no effect in this case.
i18n Configuration
Set up the required translation keys:
{
"en": {
"navigation": {
"app": "My Application"
}
},
"de": {
"navigation": {
"app": "Meine Anwendung"
}
},
"fr": {
"navigation": {
"app": "Mon Application"
}
}
}Layout Integration
Default Layout
Use in your layout for consistent navigation:
<!-- layouts/default.vue -->
<template>
<div class="min-h-screen flex flex-col">
<NavigationBar>
<template #center>
<nav><!-- Your nav items --></nav>
</template>
<template #rightPostItems>
<SettingsButton :items="settingsItems" />
</template>
</NavigationBar>
<main class="flex-1 container mx-auto p-4">
<slot />
</main>
</div>
</template>Sticky Navigation
Make the navigation bar stick to the top:
<template>
<div>
<div class="sticky top-0 z-50 bg-white shadow">
<NavigationBar>
<template #center>
<!-- Navigation content -->
</template>
</NavigationBar>
</div>
<main class="container mx-auto p-4">
<slot />
</main>
</div>
</template>Component Structure
The NavigationBar uses a flexbox layout with three main sections:
<div class="flex justify-between gap-2 px-4 py-2 w-full z-50">
<!-- Left Section -->
<slot name="left">
<!-- Default: App name -->
</slot>
<!-- Center Section -->
<slot name="center" />
<!-- Right Section -->
<slot name="right">
<div class="flex items-center gap-2">
<slot name="rightPreItems" />
<SystemStatus v-if="props.showSystemStatus" />
<LanguageSelect v-if="props.showLanguageSelect" />
<OnboardingRestartButton v-if="props.showOnboardingRestart" />
<AppSwitcher
v-if="props.showAppSwitcher && props.otherApps"
:apps="props.otherApps"
/>
<slot name="rightPostItems" />
</div>
</slot>
</div>Slot Behavior
Default Left Content
If you don't provide a left slot, the component displays:
<div class="text-xl font-bold">
{{ t("navigation.app") }}
</div>Default Right Content
The default right slot includes (in order):
- Content from
rightPreItemsslot - SystemStatus (if
showSystemStatusistrue) - LanguageSelect (if
showLanguageSelectistrue) - OnboardingRestartButton (if
showOnboardingRestartistrue) - AppSwitcher (if
showAppSwitcheristrueandotherAppsis provided) - Content from
rightPostItemsslot
Nested Slots vs Complete Override
- Use
rightPreItemsandrightPostItems: When you want to keep the default SystemStatus, LanguageSelect, OnboardingRestartButton, and AppSwitcher - Use
rightslot: When you want complete control over the entire right section
Styling
The component uses utility classes for layout:
flex justify-between: Distributes space between sectionsgap-2: Spacing between elementspx-4 py-2: Horizontal and vertical padding around the barw-full: Full widthz-50: High z-index for layering
