Back to catalog
Component detail entry
Navigation
@vean/ui
STreeNav

TreeNav

TreeNav belongs to the Navigation category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

TreeNav

Overview

TreeNav is a data-driven horizontal navigation bar with a persistent selection state: top-level entries sit in a row, branch entries open dropdown popups (hover by default), and selecting any leaf keeps the whole ancestor chain highlighted.

STreeNav is the horizontal counterpart of STreeMenu: both consume the same tree-shaped items data (TreeNavOptionData) and derive highlights from the selected value, but TreeNav renders branches as DropdownMenu popups instead of collapsible sections. Logic and accessibility semantics live in the Aria TreeNavCompact; styles are injected through an scv() recipe.

Unlike Menubar (a transient “which menu is open” command-menu model), TreeNav models selection: opening a popup never marks anything active — only selection does. Selected leaves carry data-selected, and ancestors of the selected leaf carry data-child-selected.

Features

  • Persistent selection — bind modelValue (v-model) or seed with defaultValue; selection survives closing popups and page interactions.
  • Highlight derivation — the selected leaf renders data-selected="true", and every ancestor in its path renders data-child-selected; derivation reuses the shared tree-path helper, so highlighting works at any depth.
  • Hover-first popups — branch popups open on hover by default (trigger="click" to override), tuned via delayDuration / skipDelayDuration.
  • Familiar data shape — pass one items array (TreeNavOptionData: value / label / icon / children / href / to / disabled …), aligned with TreeMenu’s option model; item customization beyond these fields (badges, tags, actions…) is provided via slots instead of extra data fields.
  • Link top-level items — items with href / to render as links that also update the selection on click.
  • Overflow collapsing — with collapsible, trailing top-level items merge into a trailing “more” popup so the bar always fits its container; customize via moreLabel / moreIcon / moreProps / the more-trigger slot.
  • Navigation semantics — root renders as <nav> (as overridable); popup trigger semantics (aria-haspopup / aria-expanded, Escape handling) are inherited from the DropdownMenu layer.
  • Keyboard navigation — the top level is a single roving tab stop: ←/→ roam all entries alike (skipping disabled, no wrap), Home/End jump to the first/last entry; branch popups open through the explicit keys — Enter/Space (native button semantics) or ArrowDown — and once a popup is open its keys are owned by the Menu machinery.
  • Per-item and whole-bar disabling — item.disabled makes a single entry inert; the bar-level disabled disables everything.
  • Hidden items — item.hidden drops the entry and its subtree from the bar and its popup; a branch whose children are all hidden renders as a plain leaf.
  • Six sizes & two variants — size (xs…2xl) plus variant="default" (subtle card surface) or variant="nav" (bare bar).
  • Slot passthrough — item / item-leading / item-trailing / item-trigger-icon / item-link-icon forward into both the top level and popups.
  • Aria composition — import from @vean/aria/tree-nav for unstyled data-driven usage; popup options reuse MenuOptionsCompact.

Usage

Demos

Basic

GitHubDiscord

Selection

Selected: email — opening a popup never marks a branch active; only selection does.

Link Items

Disabled

Overflow Collapsing

Discord

API

Aria Layer

6

TreeNav

31 Props2 Emits6 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
class of tree-nav root.
size
ThemeSize
—
Visual size of the component.
ui
Partial<TreeNavUi>
—
Per-slot class overrides for the component.
collapsible
boolean
false
Whether top-level overflow items collapse into a trailing "more" branch popup so the bar always fits inside its container.
modelValue
string
—
The value of the currently selected item. Can be used as `v-model`.
defaultValue
string
—
The value of the item that should be selected when initially rendered.
dir
Direction
—
The reading direction of the component when applicable.
trigger
DropdownMenuTriggerType
'hover'
How branch popups are opened. - `click`: The popup will be opened when the trigger is clicked. - `hover`: The popup will be opened when the trigger is hovered.
delayDuration
number
150
The duration from when the pointer enters a branch trigger until the popup gets opened in hover mode.
skipDelayDuration
number
300
How much time a user has to enter another branch trigger without incurring a delay again.
placement
Placement
'bottom-start'
The preferred placement of branch popups relative to their trigger.
showArrow
boolean
false
Whether branch popups show an arrow.
disabled
boolean
—
Whether the whole navigation bar is disabled.
linkProps
LinkExtraProps
—
Properties forwarded to the link element of link items.
itemProps
MenuItemProps
—
Properties forwarded to the item element of popup items.
groupLabelProps
MenuGroupLabelProps
—
Properties forwarded to the group label element of popup group labels.
shortcutProps
MenuShortcutProps
—
Properties forwarded to the shortcut element of popup items.
separatorProps
MenuSeparatorProps
—
Properties forwarded to the separator element of popup separators.
subTriggerProps
MenuSubTriggerProps
—
Properties forwarded to the sub trigger element of popup branches.
subContentProps
MenuSubContentProps
—
Properties forwarded to the sub content element of popup branches.
portalProps
MenuPortalProps
—
Properties forwarded to the portal element of popups.
popupProps
MenuPopupProps
—
Properties forwarded to the popup element of popups.
triggerProps
DropdownMenuTriggerProps
—
Properties forwarded to the trigger element of branch popups.
arrowProps
MenuArrowProps
—
Properties forwarded to the arrow element of popups.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
items
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Top-level items rendered as visible entries.
moreItems
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Items collapsed into the trailing "more" popup.
moreLabel
string
'More'
Label of the trailing "more" trigger.
moreIcon
IconValue
'lucide:ellipsis'
Icon of the trailing "more" trigger.
moreProps
ButtonProps
—
Properties forwarded to the trailing "more" trigger button.
Emits
Emit NameParametersDescription
update:modelValue
string
Emitted when the selected value changes.
select
TreeNavOptionData<TreeNavBaseOptionData>, event: Event
Emitted when an item is selected.
Slots
Slot NameParametersDescription
item
{ item: MenuOptionData<DefinedValue>; isTrigger?: boolean; }
Custom content for the item slot.
item-leading
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item leading slot.
item-trailing
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trailing slot.
item-trigger-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trigger icon slot.
item-link-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item link icon slot.
more-trigger
TreeNavMoreEntry
Custom content for the trailing "more" trigger when present.

TreeNavCompact

28 Props2 Emits6 Slots
Props
PropTypeDefaultDescription
collapsible
boolean
false
Whether top-level overflow items collapse into a trailing "more" branch popup so the bar always fits inside its container.
modelValue
string
—
The value of the currently selected item. Can be used as `v-model`.
defaultValue
string
—
The value of the item that should be selected when initially rendered.
dir
Direction
—
The reading direction of the component when applicable.
trigger
DropdownMenuTriggerType
'hover'
How branch popups are opened. - `click`: The popup will be opened when the trigger is clicked. - `hover`: The popup will be opened when the trigger is hovered.
delayDuration
number
150
The duration from when the pointer enters a branch trigger until the popup gets opened in hover mode.
skipDelayDuration
number
300
How much time a user has to enter another branch trigger without incurring a delay again.
placement
Placement
'bottom-start'
The preferred placement of branch popups relative to their trigger.
showArrow
boolean
false
Whether branch popups show an arrow.
disabled
boolean
—
Whether the whole navigation bar is disabled.
linkProps
LinkExtraProps
—
Properties forwarded to the link element of link items.
itemProps
MenuItemProps
—
Properties forwarded to the item element of popup items.
groupLabelProps
MenuGroupLabelProps
—
Properties forwarded to the group label element of popup group labels.
shortcutProps
MenuShortcutProps
—
Properties forwarded to the shortcut element of popup items.
separatorProps
MenuSeparatorProps
—
Properties forwarded to the separator element of popup separators.
subTriggerProps
MenuSubTriggerProps
—
Properties forwarded to the sub trigger element of popup branches.
subContentProps
MenuSubContentProps
—
Properties forwarded to the sub content element of popup branches.
portalProps
MenuPortalProps
—
Properties forwarded to the portal element of popups.
popupProps
MenuPopupProps
—
Properties forwarded to the popup element of popups.
triggerProps
DropdownMenuTriggerProps
—
Properties forwarded to the trigger element of branch popups.
arrowProps
MenuArrowProps
—
Properties forwarded to the arrow element of popups.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
items
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Top-level items rendered as visible entries.
moreItems
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Items collapsed into the trailing "more" popup.
moreLabel
string
'More'
Label of the trailing "more" trigger.
moreIcon
IconValue
'lucide:ellipsis'
Icon of the trailing "more" trigger.
moreProps
ButtonProps
—
Properties forwarded to the trailing "more" trigger button.
Emits
Emit NameParametersDescription
update:modelValue
string
Emitted when the selected value changes.
select
TreeNavOptionData<TreeNavBaseOptionData>, event: Event
Emitted when an item is selected.
Slots
Slot NameParametersDescription
item
{ item: MenuOptionData<DefinedValue>; isTrigger?: boolean; }
Custom content for the item slot.
item-leading
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item leading slot.
item-trailing
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trailing slot.
item-trigger-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trigger icon slot.
item-link-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item link icon slot.
more-trigger
TreeNavMoreEntry
Custom content for the trailing "more" trigger when present.

TreeNavOptionCompact

2 Props
Props
PropTypeDefaultDescription
item
TreeNavOptionData<T extends TreeNavBaseOptionData = TreeNavBaseOptionData>
—
Current item data.
childSelected
boolean
—
Whether the selected leaf lives inside this branch subtree.

TreeNavOptionsCompact

5 Props6 Slots
Props
PropTypeDefaultDescription
items
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Top-level items rendered as visible entries.
moreItems
TreeNavOptionData<TreeNavBaseOptionData>[]
—
Items collapsed into the trailing "more" popup.
moreLabel
string
'More'
Label of the trailing "more" trigger.
moreIcon
IconValue
'lucide:ellipsis'
Icon of the trailing "more" trigger.
moreProps
ButtonProps
—
Properties forwarded to the trailing "more" trigger button.
Slots
Slot NameParametersDescription
item
{ item: MenuOptionData<DefinedValue>; isTrigger?: boolean; }
Custom content for the item slot.
item-leading
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item leading slot.
item-trailing
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trailing slot.
item-trigger-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item trigger icon slot.
item-link-icon
{ item: MenuOptionData<DefinedValue>; }
Custom content for the item link icon slot.
more-trigger
TreeNavMoreEntry
Custom content for the trailing "more" trigger when present.

TreeNavOverflow

TreeNavRoot

22 Props2 Emits1 Slots
Props
PropTypeDefaultDescription
modelValue
string
—
The value of the currently selected item. Can be used as `v-model`.
defaultValue
string
—
The value of the item that should be selected when initially rendered.
dir
Direction
—
The reading direction of the component when applicable.
trigger
DropdownMenuTriggerType
'hover'
How branch popups are opened. - `click`: The popup will be opened when the trigger is clicked. - `hover`: The popup will be opened when the trigger is hovered.
delayDuration
number
150
The duration from when the pointer enters a branch trigger until the popup gets opened in hover mode.
skipDelayDuration
number
300
How much time a user has to enter another branch trigger without incurring a delay again.
placement
Placement
'bottom-start'
The preferred placement of branch popups relative to their trigger.
showArrow
boolean
false
Whether branch popups show an arrow.
disabled
boolean
—
Whether the whole navigation bar is disabled.
linkProps
LinkExtraProps
—
Properties forwarded to the link element of link items.
itemProps
MenuItemProps
—
Properties forwarded to the item element of popup items.
groupLabelProps
MenuGroupLabelProps
—
Properties forwarded to the group label element of popup group labels.
shortcutProps
MenuShortcutProps
—
Properties forwarded to the shortcut element of popup items.
separatorProps
MenuSeparatorProps
—
Properties forwarded to the separator element of popup separators.
subTriggerProps
MenuSubTriggerProps
—
Properties forwarded to the sub trigger element of popup branches.
subContentProps
MenuSubContentProps
—
Properties forwarded to the sub content element of popup branches.
portalProps
MenuPortalProps
—
Properties forwarded to the portal element of popups.
popupProps
MenuPopupProps
—
Properties forwarded to the popup element of popups.
triggerProps
DropdownMenuTriggerProps
—
Properties forwarded to the trigger element of branch popups.
arrowProps
MenuArrowProps
—
Properties forwarded to the arrow element of popups.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
string
Emitted when the selected value changes.
select
TreeNavOptionData<TreeNavBaseOptionData>, event: Event
Emitted when an item is selected.
Slots
Slot NameParametersDescription
default
—
Default content rendered inside the nav root.

Notes

When to use which navigation component

ComponentState modelLayoutUse for
SMenubaropen menu (modelValue = which menu is open)horizontalapplication command menus (File/Edit)
SNavMenuhighlighted item (modelValue)horizontalsite-level nav with flyout panels
STreeMenupersistent selectionverticalsidebar navigation
STreeNavpersistent selectionhorizontaltop navigation bars

Runtime considerations

  1. Open ≠ active — popup open state is transient UI state managed internally by the DropdownMenu layer; only leaf selection updates data-selected. Do not use SMenubar’s modelValue semantics here.
  2. Collapsed highlight consistency — when a selected item collapses into the “more” popup, its visible ancestor still shows data-child-selected because derivation runs on the full items list.
  3. Collapsible measurement — like Menubar’s overflow collapsing, measurement runs against real layout after mount; give the parent a constrained width (e.g. max-w-* / fixed width) for best results. The first frame may briefly render all items before collapsing.
  4. Controlled mode — with modelValue, internal writes only emit update:modelValue; uncontrolled usage seeds the initial state with defaultValue.
  5. Keyboard model — while the bar is closed, ←/→ (and Home/End) roam the top level through a roving tabindex; branch triggers are roam targets like any other entry, so arrows never open popups. Opening stays on Enter/Space or ArrowDown (focus then moves to the first menu item); once a popup is open, all keys belong to the Menu (↑/↓ inside, Escape to close and return focus to the trigger), and a hover popup closes itself when focus leaves the trigger.

FAQ

Which keyboard shortcuts does the nav bar support?

←/→ roam the top-level entries (Home/End jump to the ends) — branch triggers included, so the arrows only move focus and never open popups. Popups open via Enter/Space or ArrowDown on a branch trigger (focus lands on the first menu item). Direction keys never change the selection — selection only happens on explicit activation (click or Enter/Space on a leaf).

How do I make a top-level entry navigate instead of opening a dropdown?

Set href or to on the item — link entries render as <a> elements and update the selection on click.

How do I control which entry stays highlighted?

Bind v-model. The selected value is compared against the whole items tree; matched leaves get data-selected and their ancestors get data-child-selected.

Why doesn’t hovering a branch mark it active?

Opening a popup is transient state, not selection — select a leaf inside instead. This mirrors STreeMenu, where container nodes never carry the active state.

What happens when my nav bar overflows?

Pass collapsible. Trailing items collapse into a “more” popup (default label More) whenever they exceed the container width, recomputed automatically on resize.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Style

drop the stale "more" branch when collapsible is disabled

Scope: tree-navAuthors: soybeanjsView commit98589

Style

drop the stale "more" branch when collapsible is disabled

Scope: tree-navAuthors: soybeanjsView commit98589

v0.40.0

2026-09-14

Compare release

Fix

menubar-style arrow switching for open branch popups

Scope: tree-navAuthors: soybeanfeView commitf136e

Refactor

extract TreeNavOverflow and refine selected-state styling

Scope: tree-navAuthors: soybeanfeView commita0ea9

Fix

menubar-style arrow switching for open branch popups

Scope: tree-navAuthors: soybeanfeView commitf136e

Refactor

extract TreeNavOverflow and refine selected-state styling

Scope: tree-navAuthors: soybeanfeView commita0ea9