Aleya James
Suggested for you
A tab bar for the bottom of a phone screen.
<script setup lang="ts">
import { BottomNav, BottomNavItem } from "@/components/ui/bottom-nav";
import { ref } from "vue";
const current = ref("home");
</script>
<template>
<BottomNav v-model="current">
<BottomNavItem value="home" label="Home" icon="solar:home-linear" active-icon="solar:home-bold" />
<BottomNavItem value="explore" label="Explore" icon="solar:compass-linear" active-icon="solar:compass-bold" />
<BottomNavItem value="profile" label="Profile" icon="solar:user-circle-linear" active-icon="solar:user-circle-bold" />
</BottomNav>
</template>Keep labels to one short word. A longer label gets cut off.
Set labelDisplay to none. Screen readers still get the label.
Default is frosted, solid is opaque, floating sits above the bottom edge, and glass is a clear capsule.
A clear capsule over the content, with a solid pill behind the active item. Use it with indicator set to pill.
With labels under the icons, the pill covers the icon and its label.
Set labelPlacement to beside and labelDisplay to active. The pill grows to fit the label.
Keep the action button outside BottomNav, next to the bar.
Every preview has a light and dark switch next to the replay button. This one opens in dark.
Pill and bar slide to the item you tap.
Small is 48px tall. Medium is 56px and the default.
Pass a number for a count or true for a dot.
Put an avatar in the icon slot. The slot gets active, so the avatar can dim while another tab is selected.
Give each item a value and bind v-model.
Set hideOnScroll to hide the bar when you scroll down. It comes back when you scroll up.
Tap the active item to scroll back to the top. A fixed bar scrolls the page. In a container, set scrollTarget.
The bar is fixed by default and hides from lg up. Use absolute inside a container, or static to keep it in the page flow.
The bar adds the bottom safe area under its 56px. Set --safe-area-inset-bottom on a parent to use your own value.
<!-- Pinned to the viewport on phones, hidden from lg up -->
<BottomNav v-model="current">...</BottomNav>
<!-- Inside a container that sets its own safe area -->
<div class="relative h-dvh overflow-hidden [--safe-area-inset-bottom:1.25rem]">
<BottomNav v-model="current" position="absolute">...</BottomNav>
</div>Bars from app designs, built with BottomNav and Tailwind classes. Icons are Solar by 480 Design, licensed under CC BY 4.0.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | - | Value of the active item. Use with v-model. |
variant | "default" | "solid" | "floating" | "glass" | "default" | Surface style. glass is a clear floating capsule, made for indicator pill. |
indicator | "none" | "pill" | "bar" | "dot" | "none" | Marks the active item. Pill and bar slide between items. |
size | "sm" | "md" | "md" | Bar height: 48px or 56px. |
labelDisplay | "always" | "active" | "none" | "always" | Which labels to show. |
labelPlacement | "below" | "beside" | "below" | Label under or next to the icon. With beside, items grow to fit their label. |
position | "fixed" | "absolute" | "static" | "fixed" | fixed hides the bar from lg up. |
hideOnScroll | boolean | false | Hides the bar on scroll down and shows it on scroll up. |
scrollTarget | HTMLElement | string | null | null | Element or selector for hideOnScroll and scroll to top. Without it, hideOnScroll watches the window and only a fixed bar scrolls to the top. |
ariaLabel | string | "Bottom navigation" | Name of the nav landmark. |
class | string | - | Extra classes, merged with cn(). |
| Event | Description |
|---|---|
update:modelValue | Fires when you tap an item that has a value. |
| Slot | Description |
|---|---|
default | BottomNavItem children. |
| Prop | Type | Default | Description |
|---|---|---|---|
to | string | - | Renders a NuxtLink. External URLs open in a new tab. |
icon | string | - | Iconify icon name. |
activeIcon | string | - | Icon for the active state, usually the filled version. The item then keeps one color in every state. |
label | string | - | Item label. |
badge | number | boolean | - | A number shows a count, capped at 99+. true shows a dot. |
exact | boolean | false | Match the route exactly instead of by prefix. |
active | boolean | false | Forces the active state. |
value | string | number | - | Matches the modelValue of the parent BottomNav. |
as | string | "button" | Element to render when to is not set. |
class | string | - | Extra classes, merged with cn(). |
| Event | Description |
|---|---|
select | Fires on click. |
| Slot | Description |
|---|---|
icon | Custom icon content, such as an avatar. Gets { active }. |
Keyboard shortcuts and ARIA behavior.
| Shortcut | Description |
|---|---|
| Tab | Moves focus between items. |
| Enter | Opens the focused item. |
| Space | Opens the focused item. |
Social app
Aleya James
Suggested for you
Liam Parker
Lisbon, Portugal
Ava Collins
Suggested for you