Sidebar
Fixed sidebar navigation component with collapsible states, icon-only mode, and responsive behavior. Provides visual states only - state management is left to the implementing application.
Example
The sidebar component provides three visual states controlled by the data-state attribute:
Main content area
<aside class="omni-sidebar" data-state="extended">
<div class="omni-sidebar-header">
<h2 class="omni-sidebar-title">Navigation</h2>
<button class="omni-close" aria-label="Close sidebar">
<svg>...</svg>
</button>
</div>
<div class="omni-sidebar-content">
<nav class="omni-sidebar-nav">
<a href="#" class="omni-sidebar-item" data-active="true">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Dashboard</span>
</a>
<a href="#" class="omni-sidebar-item">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Projects</span>
<span class="omni-badge" data-variant="primary" data-size="sm">3</span>
</a>
</nav>
</div>
</aside>
States
The sidebar supports three visual states controlled by data-state:
Hidden (default)
The sidebar is completely hidden with width: 0 and translated off-screen. This is the default state when no data-state attribute is present.
<!-- Hidden by default -->
<aside class="omni-sidebar">...</aside>
Icon-Only Mode
Use data-state="icon" for a collapsed sidebar showing only icons. Text labels are hidden.
Main content area
<aside class="omni-sidebar" data-state="icon">
<div class="omni-sidebar-content">
<nav class="omni-sidebar-nav">
<a href="#" class="omni-sidebar-item" aria-label="Dashboard">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Dashboard</span>
</a>
</nav>
</div>
</aside>
Extended Mode
Use data-state="extended" for a full-width sidebar with icons and text labels visible.
<aside class="omni-sidebar" data-state="extended">
<!-- Full navigation with text labels -->
</aside>
Position
Control sidebar position with data-position:
Left (default)
The sidebar is positioned on the left side by default.
<aside class="omni-sidebar" data-state="extended">...</aside>
Right
Use data-position="right" to position the sidebar on the right side.
Main content area
<aside class="omni-sidebar" data-state="extended" data-position="right">
<!-- Right-positioned sidebar -->
</aside>
Structure
Sidebar Header
Optional header with title and close button. Hidden on desktop by default, shown on mobile (≤900px) for close functionality.
<div class="omni-sidebar-header">
<h2 class="omni-sidebar-title">Navigation</h2>
<button class="omni-close" aria-label="Close sidebar">
<svg>...</svg>
</button>
</div>
Sidebar Content
Scrollable content area for navigation items. Uses flex-grow to fill available space.
<div class="omni-sidebar-content">
<nav class="omni-sidebar-nav">
<!-- Navigation items -->
</nav>
</div>
Sidebar Items
Navigation items with optional icons, text, and badges. Use data-active="true" to indicate the current page.
<a href="#" class="omni-sidebar-item" data-active="true">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Dashboard</span>
</a>
<!-- With badge -->
<a href="#" class="omni-sidebar-item">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Messages</span>
<span class="omni-badge" data-variant="danger" data-size="sm">5</span>
</a>
<!-- As button -->
<button class="omni-sidebar-item">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Sign Out</span>
</button>
Responsive Behavior
The sidebar includes basic responsive adjustments:
- Desktop (>900px): Sidebar header is hidden by default. Use state management to toggle between icon and extended modes.
- Mobile (≤900px): Sidebar header is shown to provide a close button. Typically shown as overlay with backdrop.
- State Management: The component provides CSS-only visual states. JavaScript state management, breakpoint decisions, and overlay/backdrop handling are intentionally left to the implementing application.
API Reference
| Attribute | Values | Default | Description |
|---|---|---|---|
data-state |
hidden, icon, extended | hidden | Visual state of the sidebar |
data-position |
left, right | left | Side of the screen for placement |
data-active (item) |
true | — | Marks the current active navigation item |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--omni-sidebar-width |
240px | Width of extended sidebar |
--omni-sidebar-width-collapsed |
64px | Width of icon-only sidebar |
--omni-navbar-height |
64px | Height offset for fixed navbar |
Classes
| Class | Element | Description |
|---|---|---|
.omni-sidebar |
<aside> |
Main sidebar container |
.omni-sidebar-header |
<div> |
Header with title and close button |
.omni-sidebar-title |
<h2> |
Sidebar title text |
.omni-sidebar-content |
<div> |
Scrollable content container |
.omni-sidebar-nav |
<nav> |
Navigation list container |
.omni-sidebar-item |
<a>, <button> |
Individual navigation item |
.omni-sidebar-icon |
<span> |
Icon container |
.omni-sidebar-text |
<span> |
Text label (hidden in icon mode) |
Accessibility
- Use semantic
<nav>element with appropriatearia-label - Mark current page with
data-active="true"on the corresponding item - Icon-only mode requires
aria-labelon each sidebar item for screen readers - Full keyboard navigation support (Tab, Enter, Space for buttons)
- Focus visible indicators with proper contrast ratios
- Close button requires
aria-labelfor accessibility - Supports
prefers-reduced-motionfor transitions - High contrast mode increases border widths and adds visible borders to active items
- Works with both
<a>links and<button>elements
Best Practices
<!-- ✓ Good: Semantic markup with labels -->
<aside class="omni-sidebar" data-state="icon">
<div class="omni-sidebar-content">
<nav class="omni-sidebar-nav" aria-label="Main navigation">
<a href="/dashboard" class="omni-sidebar-item"
data-active="true" aria-label="Dashboard">
<span class="omni-sidebar-icon"><svg>...</svg></span>
<span class="omni-sidebar-text">Dashboard</span>
</a>
</nav>
</div>
</aside>
<!-- ✗ Bad: Missing aria-label in icon mode -->
<aside class="omni-sidebar" data-state="icon">
<a href="/dashboard" class="omni-sidebar-item">
<span class="omni-sidebar-icon"><svg>...</svg></span>
</a>
</aside>
Components Used
Other OmniUI components demonstrated on this page: