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: '&#xe88a;', text: 'Home', ariaLabel: 'Home' },
  { id: 'search', to: '/search', icon: '&#xe8b6;', text: 'Search', ariaLabel: 'Search' },
  { id: 'profile', to: '/profile', icon: '&#xe853;', 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

PropTypeDefaultDescription
itemsINavItem[]one Home item linking to /Items: { id, to, icon, text?, ariaLabel }.
activeItemstring | null—Active item id or path.
asstring | object'a'Link component ('a', 'router-link', NuxtLink).
islandbooleanfalseIsland variant.
frostedbooleanfalseFrosted-glass effect.
indicatorTabbooleanfalseTab-style active indicator.
indicatorFrostedbooleanfalseFrosted 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);
}
VariableDefaultControls
--cffy-navigation-bar-bg-color--cffy-surface-navigationBar background
--cffy-navigation-bar-shadow--cffy-shadow-mdBar shadow
--cffy-navigation-bar-item-color--cffy-muted-a10Item label and icon
--cffy-navigation-bar-item-active-color / --cffy-navigation-bar-item-hover-color--cffy-primary-a10 / the active colorActive and hovered item
--cffy-navigation-bar-font-size / --cffy-navigation-bar-icon-size0.65rem / 1.35remLabel and icon size
--cffy-navigation-bar-indicator-color / --cffy-navigation-bar-indicator-radiusprimary tint / --cffy-radius-xlActive item indicator
--cffy-navigation-bar-easing / --cffy-navigation-bar-duration--cffy-ease-overshoot-soft / --cffy-duration-600Indicator slide
Copyright © 2026