@usevyre/react@usevyre/vue

Sidebar

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.


Full layout

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.

Dashboard

Overview of your workspace activity and key metrics.

Total users

1,284

Active now

42

Revenue

$9.4k

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>

Sidebar only

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.

Dashboard

Content for the dashboard page.

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>

Collapsible

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.

Click trigger to collapse

Active: dashboard

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>

Custom trigger icon

By default SidebarTrigger renders a built-in menu icon. Provide your own — and a different glyph per state — so users can tell at a glance whether the sidebar is open or collapsed (a common dashboard pattern). React uses the icon / collapsedIcon props; Vue uses the #icon / #collapsed-icon slots.collapsedIcon falls back to icon, which falls back to the built-in icon — all optional, fully backward compatible.

Toggle — the icon changes per state

Active: dashboard

import { SidebarTrigger } from "@usevyre/react";

// Any ReactNode works — inline SVG (zero-dep) or your icon library.
const PanelClose = (
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
    <rect x="3" y="4" width="18" height="16" rx="2" stroke="currentColor" strokeWidth="1.7"/>
    <path d="M10 4v16" stroke="currentColor" strokeWidth="1.7"/>
    <path d="M16.5 9.5L14 12l2.5 2.5" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/>
  </svg>
);
const PanelOpen = (
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
    <rect x="3" y="4" width="18" height="16" rx="2" stroke="currentColor" strokeWidth="1.7"/>
    <path d="M10 4v16" stroke="currentColor" strokeWidth="1.7"/>
    <path d="M14 9.5L16.5 12 14 14.5" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/>
  </svg>
);

// Distinct glyphs signal the collapsed state to users.
<SidebarTrigger icon={PanelClose} collapsedIcon={PanelOpen} />

// Omit collapsedIcon to reuse icon for both states.
// Omit both for the built-in menu icon.

Component hierarchy

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

Props

AppLayout

Props

PropTypeDefaultDescription
defaultCollapsedbooleanfalseInitial collapsed state for uncontrolled usage.
collapsedbooleanControlled collapsed state.
onCollapsedChange(v: boolean) => void(React) Called when collapsed state changes.
v-model:collapsedboolean(Vue) Two-way binding for collapsed state.
class / classNamestringAdditional CSS class.

AppShell

Props

PropTypeDefaultDescription
class / classNamestringAdditional CSS class on the right column wrapper (flex: 1).

AppBar

Props

PropTypeDefaultDescription
class / classNamestringAdditional CSS class on the <header> element (height: 52px).

PageContent

Props

PropTypeDefaultDescription
class / classNamestringAdditional CSS class on the scrollable content area (padding: 24px, overflow: auto).

Sidebar

Props

PropTypeDefaultDescription
collapsedbooleanfalseCollapses 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:collapsedboolean(Vue) Two-way binding for collapsed state.
variant"default" | "floating""default"floating adds a border, rounded corners, and shadow — for overlay/inset sidebars.
class / classNamestringAdditional CSS class.

SidebarHeader

Props

PropTypeDefaultDescription
titlestringApplication or workspace name displayed next to the logo. Hidden when sidebar is collapsed.
logoReactNode(React) Logo element. In Vue use the #logo slot.

SidebarItem

Props

PropTypeDefaultDescription
activebooleanfalseHighlights the item as the current active page.
iconReactNode / slotLeading icon. In Vue use the #icon slot.
badgestring | numberNotification badge shown on the right. Hidden when collapsed.
hrefstringRenders as an <a> tag when provided. Use onClick for button behavior.
onClick() => void(React) Click handler. Ignored when href is set.

SidebarSection

Props

PropTypeDefaultDescription
labelstringSection heading text. Hidden when sidebar is collapsed.

SidebarTrigger

Props

PropTypeDefaultDescription
iconReactNode / #icon slotbuilt-in menu iconIcon shown when the sidebar is expanded.
collapsedIconReactNode / #collapsed-icon slotfalls back to iconIcon shown when collapsed. Use a different glyph to signal collapsed state.
className / classstringAdditional CSS class on the trigger button.