Menubar
<r-menubar>APIStyle tokensPlaygroundSource
A thin bar that wires hover open and a shared viewport hop across sibling chrome
selects (r-select, r-theme-switch, r-surface-switch, or any host with open).
On a fine pointer, moving across triggers keeps one floating shell that morphs size and position under the active trigger while content slides by direction (Stripe / Radix NavigationMenu). Native select portals stay for state but are visually suppressed while the viewport is open. Touch keeps each control’s own click. Soft enter from idle fades the shell in.
Use when a row of chrome menus should feel like one surface (docs headers, settings toolbars). For a single select, use
<r-select>alone.
Quick Start
Language + theme + surface
Hover across the three controls (desktop). The shell slides with the pointer and content cross-fades by direction.
<r-menubar>
<r-select dropdownclass="ran-chrome-menu" defaultValue="en" aria-label="Language">
<r-option value="en">English</r-option>
<r-option value="zh">简体中文</r-option>
<r-option value="pt">Português</r-option>
</r-select>
<r-theme-switch></r-theme-switch>
<r-surface-switch></r-surface-switch>
</r-menubar>import 'ranui/menubar';
import 'ranui/select';
import 'ranui/theme-switch';
import 'ranui/surface-switch';Mark portaled panels with dropdownclass="ran-chrome-menu" (theme/surface switches already
do). The handoff harvests that class into the shared viewport.
Imperative host (no custom element)
import { mountMenubarHandoff } from 'ranui/menubar';
const stop = mountMenubarHandoff({ root: document.querySelector('.chrome') });
// later: stop()API Reference
Attributes
| Attribute | Default | Description |
|---|---|---|
panel-selector |
r-dropdown.ran-chrome-menu |
Native panels harvested into the shared viewport. |
leave-delay |
180 |
ms before close after leaving the bar + viewport. |
duration |
280 |
Shell morph + content slide duration in ms. |
sheet |
'' |
CSS injected into the component's shadow DOM. |
CSS Parts
| Part | Description |
|---|---|
root |
Inner shell (display: contents). |
r-menubar {
--ran-menubar-gap: 8px;
}Notes
- Triggers are light-DOM descendants tagged
r-select,r-theme-switch,r-surface-switch, or[data-ran-menubar-item]that exposeopen. - Nested wrappers (e.g. an
.appearancegroup) are fine — the bar finds the hosts. - Peer hops use one viewport (
html[data-ran-menubar-viewport]); reduced motion skips slides and snaps the shell.
Playground