Overview of your workspace activity and key metrics.
Total users
1,284
Active now
42
Revenue
useVyre is under active development - things may change. Share feedback or ideas →
A composable navigation sidebar with sections, active states, badges, and optional
collapse to icon-only mode. Built from small pieces —
SidebarHeader, SidebarContent, SidebarSection,
SidebarItem, and SidebarFooter — so you compose exactly what you need.
Wrap everything in AppLayout (manages collapsed state via context) and put
your page content inside AppShell. Use AppBar for the top bar
and PageContent for the scrollable content area.
import {
AppLayout, AppShell, AppBar, PageContent, SidebarTrigger,
Sidebar, SidebarHeader, SidebarContent,
SidebarSection, SidebarItem, SidebarFooter,
} from "@usevyre/react";
<AppLayout>
<Sidebar>
<SidebarHeader title="Workspace" logo={<AppLogo />} />
<SidebarContent>
<SidebarSection label="Main">
<SidebarItem icon={<HomeIcon />} active href="/dashboard">Dashboard</SidebarItem>
<SidebarItem icon={<UsersIcon />} href="/users">Users</SidebarItem>
<SidebarItem icon={<BellIcon />} badge={3} href="/notifications">Notifications</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarItem icon={<SettingsIcon />} href="/settings">Settings</SidebarItem>
</SidebarFooter>
</Sidebar>
<AppShell>
<AppBar>
<SidebarTrigger />
<Breadcrumb>...</Breadcrumb>
<div style={{ marginLeft: "auto" }}>page actions</div>
</AppBar>
<PageContent>
<h1>Dashboard</h1>
<p>Your page content here.</p>
</PageContent>
</AppShell>
</AppLayout> <script setup>
import {
AppLayout, AppShell, AppBar, PageContent, SidebarTrigger,
Sidebar, SidebarHeader, SidebarContent,
SidebarSection, SidebarItem, SidebarFooter,
} from "@usevyre/vue";
</script>
<template>
<AppLayout>
<Sidebar>
<SidebarHeader title="Workspace">
<template #logo><AppLogo /></template>
</SidebarHeader>
<SidebarContent>
<SidebarSection label="Main">
<SidebarItem href="/dashboard" :active="true">
<template #icon><HomeIcon /></template>
Dashboard
</SidebarItem>
<SidebarItem href="/users">
<template #icon><UsersIcon /></template>
Users
</SidebarItem>
<SidebarItem href="/notifications" :badge="3">
<template #icon><BellIcon /></template>
Notifications
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarItem href="/settings">
<template #icon><SettingsIcon /></template>
Settings
</SidebarItem>
</SidebarFooter>
</Sidebar>
<AppShell>
<AppBar>
<SidebarTrigger />
<Breadcrumb>...</Breadcrumb>
</AppBar>
<PageContent>
<h1>Dashboard</h1>
<p>Your page content here.</p>
</PageContent>
</AppShell>
</AppLayout>
</template>
Use Sidebar standalone when you manage the outer layout yourself.
SidebarItem renders as an <a> when href is set,
otherwise as a <button>. Use badge for notification counts.
import {
Sidebar, SidebarHeader, SidebarContent,
SidebarSection, SidebarItem, SidebarFooter,
} from "@usevyre/react";
const [active, setActive] = useState("dashboard");
<Sidebar>
<SidebarHeader title="My App" logo={<AppLogo />} />
<SidebarContent>
<SidebarSection label="Main">
<SidebarItem icon={<HomeIcon />} active={active === "dashboard"} onClick={() => setActive("dashboard")}>
Dashboard
</SidebarItem>
<SidebarItem icon={<UsersIcon />} active={active === "users"} onClick={() => setActive("users")}>
Users
</SidebarItem>
<SidebarItem icon={<BellIcon />} badge={3} active={active === "notif"} onClick={() => setActive("notif")}>
Notifications
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarItem icon={<SettingsIcon />} href="/settings">Settings</SidebarItem>
</SidebarFooter>
</Sidebar> <script setup>
import {
Sidebar, SidebarHeader, SidebarContent,
SidebarSection, SidebarItem, SidebarFooter,
} from "@usevyre/vue";
const active = ref("dashboard");
</script>
<template>
<Sidebar>
<SidebarHeader title="My App">
<template #logo><AppLogo /></template>
</SidebarHeader>
<SidebarContent>
<SidebarSection label="Main">
<SidebarItem :active="active === 'dashboard'" @click="active = 'dashboard'">
<template #icon><HomeIcon /></template>
Dashboard
</SidebarItem>
<SidebarItem :active="active === 'users'" @click="active = 'users'">
<template #icon><UsersIcon /></template>
Users
</SidebarItem>
<SidebarItem :badge="3" :active="active === 'notif'" @click="active = 'notif'">
<template #icon><BellIcon /></template>
Notifications
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarItem href="/settings">
<template #icon><SettingsIcon /></template>
Settings
</SidebarItem>
</SidebarFooter>
</Sidebar>
</template>
Pass collapsed and onCollapsedChange (React) or v-model:collapsed (Vue)
to enable a collapse toggle. In collapsed mode, labels and section headings are hidden —
only icons remain. Hover title is added automatically for accessibility.
import { AppLayout, AppShell, AppBar, PageContent, SidebarTrigger, Sidebar, ... } from "@usevyre/react";
// AppLayout handles state — no useState needed
<AppLayout defaultCollapsed={false}>
<Sidebar>
<SidebarHeader title="App" logo={<AppLogo />} />
<SidebarContent>
<SidebarSection>
<SidebarItem icon={<HomeIcon />} active>Dashboard</SidebarItem>
<SidebarItem icon={<UsersIcon />}>Users</SidebarItem>
</SidebarSection>
</SidebarContent>
</Sidebar>
<AppShell>
<AppBar>
<SidebarTrigger /> {/* reads collapsed state from AppLayout context */}
</AppBar>
<PageContent>...</PageContent>
</AppShell>
</AppLayout> <script setup>
import { AppLayout, AppShell, AppBar, PageContent, SidebarTrigger, Sidebar, ... } from "@usevyre/vue";
// AppLayout handles state — no ref needed
</script>
<template>
<AppLayout :default-collapsed="false">
<Sidebar>
<SidebarHeader title="App">
<template #logo><AppLogo /></template>
</SidebarHeader>
<SidebarContent>
<SidebarSection>
<SidebarItem :active="true">
<template #icon><HomeIcon /></template>
Dashboard
</SidebarItem>
</SidebarSection>
</SidebarContent>
</Sidebar>
<AppShell>
<AppBar>
<SidebarTrigger /> <!-- reads collapsed state from AppLayout context -->
</AppBar>
<PageContent>...</PageContent>
</AppShell>
</AppLayout>
</template> AppLayout — root, manages collapsed state via context
├── Sidebar — left column (240px / 56px collapsed)
│ ├── SidebarHeader — logo + app name
│ ├── SidebarContent — scrollable nav area, flex: 1
│ │ └── SidebarSection — grouped items with optional label
│ │ └── SidebarItem — <a> or <button>
│ └── SidebarFooter — pinned bottom area
└── AppShell — right column, flex: 1
├── AppBar — optional top bar (52px, border-bottom)
│ └── SidebarTrigger — collapse toggle, reads context
└── PageContent — scrollable page content, padding: 24px | Prop | Type | Default | Description |
|---|---|---|---|
defaultCollapsed | boolean | false | Initial collapsed state for uncontrolled usage. |
collapsed | boolean | — | Controlled collapsed state. |
onCollapsedChange | (v: boolean) => void | — | (React) Called when collapsed state changes. |
v-model:collapsed | boolean | — | (Vue) Two-way binding for collapsed state. |
class / className | string | — | Additional CSS class. |
| Prop | Type | Default | Description |
|---|---|---|---|
class / className | string | — | Additional CSS class on the right column wrapper (flex: 1). |
| Prop | Type | Default | Description |
|---|---|---|---|
class / className | string | — | Additional CSS class on the <header> element (height: 52px). |
| Prop | Type | Default | Description |
|---|---|---|---|
class / className | string | — | Additional CSS class on the scrollable content area (padding: 24px, overflow: auto). |
| Prop | Type | Default | Description |
|---|---|---|---|
collapsed | boolean | false | Collapses the sidebar to icon-only mode (56px wide). |
onCollapsedChange | (v: boolean) => void | — | (React) Called when the collapse toggle is clicked. Shows the toggle button when provided. |
v-model:collapsed | boolean | — | (Vue) Two-way binding for collapsed state. |
variant | "default" | "floating" | "default" | floating adds a border, rounded corners, and shadow — for overlay/inset sidebars. |
class / className | string | — | Additional CSS class. |
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Application or workspace name displayed next to the logo. Hidden when sidebar is collapsed. |
logo | ReactNode | — | (React) Logo element. In Vue use the #logo slot. |
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Highlights the item as the current active page. |
icon | ReactNode / slot | — | Leading icon. In Vue use the #icon slot. |
badge | string | number | — | Notification badge shown on the right. Hidden when collapsed. |
href | string | — | Renders as an <a> tag when provided. Use onClick for button behavior. |
onClick | () => void | — | (React) Click handler. Ignored when href is set. |
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Section heading text. Hidden when sidebar is collapsed. |
Valid props
| Prop | Values | Default |
|---|---|---|
variant | "default"|"floating" | default |
Quick examples
<AppLayout>
<Sidebar>
<SidebarHeader>Logo</SidebarHeader>
<SidebarContent>
<SidebarSection heading="Main">
<SidebarItem href="/" active>Dashboard</SidebarItem>
<SidebarItem href="/settings">Settings</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter><Avatar fallback="JD" size="sm" /></SidebarFooter>
</Sidebar>
<main>Page content</main>
</AppLayout>