Components
Navigation Bar
A data-driven bottom / island navigation bar.
UiNavigationBar renders a navigation bar from an array of items — ideal for mobile bottom navigation or an island-style bar.
Add a navigation bar
<script setup lang="ts">
import type { INavItem } from '@colorffy/ui'
import { NuxtLink } from '#components'
const items: INavItem[] = [
{ id: 'home', to: '/', icon: '', text: 'Home', ariaLabel: 'Home' },
{ id: 'search', to: '/search', icon: '', text: 'Search', ariaLabel: 'Search' },
{ id: 'profile', to: '/profile', icon: '', text: 'Profile', ariaLabel: 'Profile' },
]
</script>
<template>
<UiNavigationBar :as="NuxtLink" :items="items" active-item="home" />
</template>
Style as a frosted island
<template>
<UiNavigationBar :items="items" island frosted indicator-tab />
</template>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | INavItem[] | one Home item linking to / | Items: { id, to, icon, text?, ariaLabel }. |
activeItem | string | null | — | Active item id or path. |
as | string | object | 'a' | Link component ('a', 'router-link', NuxtLink). |
island | boolean | false | Island variant. |
frosted | boolean | false | Frosted-glass effect. |
indicatorTab | boolean | false | Tab-style active indicator. |
indicatorFrosted | boolean | false | Frosted active indicator. |
The indicator is positioned and animated with pure CSS anchor positioning, following the link the router marks exactly active or the one
activeItem marks with aria-current="page", with no JavaScript. On a page that matches no item it fades out. To keep a section active on its sub-pages (/projects/42 under Projects), pass activeItem the first path segment. The slide is skipped under prefers-reduced-motion: reduce and covers up to 8 items. Browsers without anchor positioning hide the indicator entirely, but the active item stays clear on its own — its label and icon take the primary colour and the label goes bold, regardless of support.CSS variables
Set these on :root, or on any wrapper to restyle only the navigation bar inside it. The frosted style keeps its glass background, and the tab indicator its own color and corners.
:root {
--cffy-navigation-bar-item-active-color: var(--cffy-accent-a10);
--cffy-navigation-bar-indicator-radius: var(--cffy-radius-md);
}
| Variable | Default | Controls |
|---|---|---|
--cffy-navigation-bar-bg-color | --cffy-surface-navigation | Bar background |
--cffy-navigation-bar-shadow | --cffy-shadow-md | Bar shadow |
--cffy-navigation-bar-item-color | --cffy-muted-a10 | Item label and icon |
--cffy-navigation-bar-item-active-color / --cffy-navigation-bar-item-hover-color | --cffy-primary-a10 / the active color | Active and hovered item |
--cffy-navigation-bar-font-size / --cffy-navigation-bar-icon-size | 0.65rem / 1.35rem | Label and icon size |
--cffy-navigation-bar-indicator-color / --cffy-navigation-bar-indicator-radius | primary tint / --cffy-radius-xl | Active item indicator |
--cffy-navigation-bar-easing / --cffy-navigation-bar-duration | --cffy-ease-overshoot-soft / --cffy-duration-600 | Indicator slide |