
Syncfusion React Sidebar
- 339 installs
- 3 repo stars
- Updated July 28, 2026
- syncfusion/react-ui-components-skills
Use syncfusion-react-sidebar for development tasks
About
syncfusion-react-sidebar: A skill for development. This provides functionality for development workflows.
- syncfusion-react-sidebar
Syncfusion React Sidebar by the numbers
- 339 all-time installs (skills.sh)
- +23 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,186 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/react-ui-components-skills --skill syncfusion-react-sidebarAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 339 |
|---|---|
| repo stars | ★ 3 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/react-ui-components-skills ↗ |
What it does
Use syncfusion-react-sidebar for development tasks
Files
Implementing Syncfusion React Sidebar
The Syncfusion React Sidebar is a responsive navigation component that enables flexible layout patterns for modern web applications. It supports multiple display modes (Over, Push, Slide, Auto), responsive breakpoints, touch gestures, keyboard navigation, and seamless integration with ListView and TreeView components.
When to Use This Skill
Choose Sidebar when you need:
- Responsive navigation - Drawer menus that adapt to desktop/mobile viewports
- Multi-mode layouts - Over (float), Push (shift content), Slide (translate), or Auto (responsive) behaviors
- Content organization - Nested menus, ListView/TreeView integration, or multi-panel layouts
- User interaction patterns - Toggle buttons, backdrop overlays, auto-close on item click, or keyboard shortcuts
- Accessibility - ARIA labels, keyboard navigation (Tab, Enter, Escape), and screen reader support
- Customization - Themed styling, animation variations, RTL support, or custom context containers
Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and package setup
- Basic sidebar rendering
- CSS imports and theme configuration
- Initial state management
- First working example
API Reference: Properties
📄 Read: references/properties-reference.md
- All 18 properties with types, defaults, and examples
- Display properties (type, position, width, animate, showBackdrop, zIndex)
- Behavior properties (closeOnDocumentClick, enableGestures, enableRtl, mediaQuery)
- State properties (isOpen, enableDock, dockSize, enablePersistence)
- Container property (target)
API Reference: Methods
📄 Read: references/methods-reference.md
show(e?: Event)- Display sidebar with optional event parameterhide(e?: Event)- Hide sidebar with optional event parametertoggle()- Toggle open/closed statedestroy()- Remove sidebar from DOM- Complete examples for each method
API Reference: Events
📄 Read: references/events-reference.md
change- State change notification (user or programmatic)open- Before sidebar opens (preventable)close- Before sidebar closes (preventable)created- After sidebar is initializeddestroyed- When sidebar is removed- Event handling examples and patterns
API Reference: Event Arguments
📄 Read: references/event-arguments-reference.md
ChangeEventArgsinterface - element, name, cancel, isInteractedEventArgsinterface - cancel, element, event, isInteracted, modelSidebarModelobject - Complete configuration snapshot- Type definitions and usage examples
Sidebar Positioning & Behavior
📄 Read: references/sidebar-positioning.md
- Sidebar types: Over, Push, Slide, Auto
- Position: Left or Right
- Width and dock size configuration
- Multiple sidebars side-by-side
- Media query responsive behavior
Opening & Closing Sidebar
📄 Read: references/opening-closing.md
- Toggle functionality
- Programmatic show/hide methods
- Auto-close on document click
- Auto-close on escape key
- Animation transitions
- Event handling for state changes
Content Integration
📄 Read: references/content-integration.md
- ListView integration with sidebar
- TreeView integration for hierarchical navigation
- Custom HTML content and structures
- Dynamic data binding patterns
- Menu-like navigation structures
Styling & Customization
📄 Read: references/styling-customization.md
- CSS class customization
- Theme styles (default, material, bootstrap)
- Animation variations and timing
- Responsive breakpoint patterns
- RTL (Right-to-Left) support
- Custom animations
Accessibility & Best Practices
📄 Read: references/accessibility.md
- WCAG compliance guidelines
- Keyboard navigation (Tab, Enter, Escape)
- ARIA attributes for screen readers
- Focus management
- Backdrop overlay interaction patterns
Quick Start
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [isOpen, setIsOpen] = useState(false);
const handleToggle = () => {
setIsOpen(!isOpen);
};
return (
<div className="container">
{/* Toggle Button */}
<ButtonComponent
cssClass="e-primary"
onClick={handleToggle}
>
Toggle Sidebar
</ButtonComponent>
{/* Sidebar Component */}
<SidebarComponent
id="sidebar"
width="250px"
type="Over"
isOpen={isOpen}
change={() => setIsOpen(!isOpen)}
showBackdrop={true}
closeOnDocumentClick={true}
>
<div className="sidebar-content">
<h3>Navigation Menu</h3>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div>
</SidebarComponent>
{/* Main Content */}
<div className="main-content">
<h1>Main Content Area</h1>
<p>Content shifts when type is "Push"</p>
</div>
</div>
);
}
export default App;Common Patterns
Pattern 1: Responsive Auto Sidebar
Automatically switches between Over (mobile) and Push (desktop) modes based on viewport.
<SidebarComponent
type="Auto"
width="250px"
isOpen={true}
showBackdrop={true}
/>Pattern 2: Mobile Drawer Menu
Floating sidebar that closes on backdrop click or escape key.
<SidebarComponent
type="Over"
width="280px"
showBackdrop={true}
closeOnDocumentClick={true}
position="Left"
/>Pattern 3: Docked Navigation Panel
Persistent sidebar with fixed width that shows as icon bar when docked.
<SidebarComponent
enableDock={true}
dockSize="50px"
width="250px"
type="Push"
/>Pattern 4: RTL Navigation (Arabic/Hebrew)
Right-aligned sidebar for right-to-left languages.
<SidebarComponent
position="Right"
enableRtl={true}
type="Over"
/>Key Properties Overview
| Property | Type | Default | Purpose |
|---|---|---|---|
| type | SidebarType | 'Auto' | Display mode: Over, Push, Slide, Auto |
| isOpen | boolean | false | Controls sidebar open/closed state |
| position | SidebarPosition | 'Left' | Sidebar placement: Left or Right |
| width | `string \ | number` | 'auto' |
| target | `HTMLElement \ | string` | null |
| showBackdrop | boolean | false | Show overlay when open |
| closeOnDocumentClick | boolean | false | Close on content area click |
| animate | boolean | true | Enable open/close animations |
| enableDock | boolean | false | Enable dock/minimize mode |
| dockSize | `string \ | number` | 'auto' |
| enableGestures | boolean | true | Touch swipe gestures |
| enableRtl | boolean | false | Right-to-left layout |
Common Use Cases
- Admin Dashboard Navigation - Top header with collapsible sidebar menu
- Mobile App Navigation - Hamburger menu with drawer sidebar
- E-commerce Product Filter - Left sidebar with expandable categories
- Documentation Sites - Persistent table of contents sidebar
- Settings Panels - Floating right sidebar for preferences
- Multi-panel Layouts - Multiple sidebars on different sides
---
Accessibility & Best Practices
Table of Contents
- WCAG Compliance
- Keyboard Navigation
- ARIA Attributes
- Screen Reader Support
- Focus Management
- Color Contrast
- Best Practices
---
WCAG Compliance
WCAG 2.1 Accessibility Levels
The Syncfusion Sidebar component supports WCAG 2.1 Level AA compliance:
- Level A: Basic accessibility support
- Level AA: Enhanced accessibility (recommended)
- Level AAA: Advanced accessibility features
Accessibility Guidelines
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function AccessibleSidebar() {
const sidebarRef = useRef(null);
// WCAG 2.1 compliant implementation
return (
<div>
{/* 1. Semantic HTML */}
<button
aria-label="Open navigation menu"
aria-controls="sidebar"
onClick={() => sidebarRef.current?.toggle()}
>
☰ Menu
</button>
{/* 2. Proper ARIA attributes */}
<SidebarComponent
ref={sidebarRef}
id="sidebar"
type="Over"
width="280px"
role="navigation"
aria-label="Main Navigation"
>
<nav aria-label="Navigation links">
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</SidebarComponent>
</div>
);
}
export default AccessibleSidebar;---
Keyboard Navigation
Standard Keyboard Shortcuts
| Key | Action |
|---|---|
| Tab | Move focus to next focusable element |
| Shift + Tab | Move focus to previous focusable element |
| Enter | Activate button/link |
| Space | Toggle sidebar open/close |
| Escape | Close sidebar |
| Arrow Down | Move focus to next item in list |
| Arrow Up | Move focus to previous item in list |
Implementation
import React, { useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function KeyboardAccessibleSidebar() {
const sidebarRef = useRef(null);
const toggleBtnRef = useRef(null);
useEffect(() => {
const handleKeyDown = (event) => {
if (!sidebarRef.current) return;
// Spacebar or Enter to toggle
if (event.key === ' ' || event.key === 'Enter') {
if (document.activeElement === toggleBtnRef.current) {
event.preventDefault();
sidebarRef.current.toggle();
}
}
// Escape to close
if (event.key === 'Escape') {
if (sidebarRef.current.element.classList.contains('e-open')) {
sidebarRef.current.hide();
toggleBtnRef.current?.focus();
}
}
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
return (
<div>
<button
ref={toggleBtnRef}
aria-label="Toggle navigation menu"
aria-controls="sidebar"
aria-expanded={sidebarRef.current?.element?.classList.contains('e-open') || false}
>
☰ Menu
</button>
<SidebarComponent
ref={sidebarRef}
id="sidebar"
type="Over"
width="280px"
role="navigation"
>
<nav>
<a href="#home" tabIndex="0">Home</a>
<a href="#products" tabIndex="0">Products</a>
<a href="#services" tabIndex="0">Services</a>
</nav>
</SidebarComponent>
</div>
);
}
export default KeyboardAccessibleSidebar;Keyboard Focus Trap (Modal Pattern)
When sidebar is open as a modal, keep focus within sidebar:
import React, { useRef, useEffect } from 'react';
function FocusTrapSidebar() {
const sidebarRef = useRef(null);
useEffect(() => {
const sidebar = sidebarRef.current?.element;
if (!sidebar) return;
const focusableElements = sidebar.querySelectorAll(
'a, button, input, select, textarea, [tabindex]'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
const handleKeyDown = (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
// Shift + Tab on first element -> go to last
if (document.activeElement === firstElement) {
e.preventDefault();
lastElement?.focus();
}
} else {
// Tab on last element -> go to first
if (document.activeElement === lastElement) {
e.preventDefault();
firstElement?.focus();
}
}
};
sidebar.addEventListener('keydown', handleKeyDown);
return () => sidebar.removeEventListener('keydown', handleKeyDown);
}, []);
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
role="dialog"
aria-modal="true"
>
{/* Content */}
</SidebarComponent>
);
}
export default FocusTrapSidebar;---
ARIA Attributes
Essential ARIA Attributes
<SidebarComponent
// Identifies role
role="navigation"
// Descriptive label
aria-label="Main Navigation"
// Related button
aria-controls="toggle-button"
// Current expanded state
aria-expanded={isOpen}
// Modal state
aria-modal="true"
// Hidden from screen readers
aria-hidden={!isOpen}
/>Complete ARIA Example
import React, { useState, useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function ARIACompliantSidebar() {
const [isOpen, setIsOpen] = useState(false);
const sidebarRef = useRef(null);
const toggleRef = useRef(null);
const handleChange = (args) => {
const nowOpen = args.element.classList.contains('e-open');
setIsOpen(nowOpen);
// Update toggle button aria-expanded
if (toggleRef.current) {
toggleRef.current.setAttribute('aria-expanded', nowOpen);
}
};
return (
<div>
<button
ref={toggleRef}
id="sidebar-toggle"
aria-label="Open navigation menu"
aria-controls="main-sidebar"
aria-expanded={isOpen}
onClick={() => sidebarRef.current?.toggle()}
>
☰ Menu
</button>
<SidebarComponent
ref={sidebarRef}
id="main-sidebar"
role="navigation"
aria-label="Primary Navigation"
aria-expanded={isOpen}
type="Over"
width="280px"
change={handleChange}
>
<nav aria-label="Menu Items">
<ul role="menubar">
<li role="none">
<a href="#home" role="menuitem">
Home
</a>
</li>
<li role="none">
<a href="#products" role="menuitem">
Products
</a>
</li>
<li role="none">
<a href="#services" role="menuitem">
Services
</a>
</li>
</ul>
</nav>
</SidebarComponent>
</div>
);
}
export default ARIACompliantSidebar;---
Screen Reader Support
Screen Reader Friendly Content
function ScreenReaderOptimizedSidebar() {
return (
<SidebarComponent
type="Over"
role="navigation"
aria-label="Application Navigation"
>
{/* Skip link for screen reader users */}
<a href="#main-content" className="skip-link">
Skip to main content
</a>
<nav>
<h2 className="sr-only">Navigation Menu</h2>
<ul>
<li>
<a href="#home" aria-current="page">
Home <span className="sr-only">(current page)</span>
</a>
</li>
<li>
<a href="#about">About Us</a>
</li>
<li>
<a href="#contact">Contact</a>
</li>
</ul>
</nav>
</SidebarComponent>
);
}CSS for Screen Reader Content
/* Hide visually but keep for screen readers */
.sr-only,
.skip-link {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
/* Make skip link visible on focus */
.skip-link:focus {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
padding: 1rem;
background-color: #000;
color: #fff;
width: auto;
height: auto;
overflow: visible;
clip: auto;
}---
Focus Management
Initial Focus
Automatically focus first interactive element when sidebar opens:
import React, { useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function FocusManagementSidebar() {
const sidebarRef = useRef(null);
const firstLinkRef = useRef(null);
useEffect(() => {
const sidebar = sidebarRef.current?.element;
if (!sidebar) return;
const handleOpened = () => {
// Focus first interactive element
setTimeout(() => {
firstLinkRef.current?.focus();
}, 100);
};
sidebar.addEventListener('opened', handleOpened);
return () => sidebar.removeEventListener('opened', handleOpened);
}, []);
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
role="dialog"
aria-modal="true"
>
<nav>
<a ref={firstLinkRef} href="#home">Home</a>
<a href="#about">About</a>
</nav>
</SidebarComponent>
);
}
export default FocusManagementSidebar;Restore Focus on Close
Return focus to trigger button when sidebar closes:
function RestoreFocusSidebar() {
const sidebarRef = useRef(null);
const toggleRef = useRef(null);
useEffect(() => {
const sidebar = sidebarRef.current?.element;
if (!sidebar) return;
const handleClosed = () => {
// Return focus to toggle button
setTimeout(() => {
toggleRef.current?.focus();
}, 100);
};
sidebar.addEventListener('closed', handleClosed);
return () => sidebar.removeEventListener('closed', handleClosed);
}, []);
return (
<>
<button
ref={toggleRef}
onClick={() => sidebarRef.current?.toggle()}
>
Menu
</button>
<SidebarComponent ref={sidebarRef} type="Over">
{/* Content */}
</SidebarComponent>
</>
);
}---
Color Contrast
WCAG Contrast Ratios
- Normal text: Minimum 4.5:1
- Large text (18pt+): Minimum 3:1
- UI components: Minimum 3:1
Compliant Color Scheme
/* Light theme with good contrast */
.accessible-sidebar-light {
background-color: #ffffff; /* White */
color: #333333; /* Dark gray (contrast ratio 12.63:1) */
}
.accessible-sidebar-light a {
color: #0056b3; /* Blue (contrast ratio 8.59:1) */
}
.accessible-sidebar-light a:visited {
color: #7030a0; /* Purple (contrast ratio 8.41:1) */
}
/* Dark theme with good contrast */
.accessible-sidebar-dark {
background-color: #1a1a1a; /* Very dark gray */
color: #e0e0e0; /* Light gray (contrast ratio 12.04:1) */
}
.accessible-sidebar-dark a {
color: #4a90e2; /* Light blue (contrast ratio 8.32:1) */
}
.accessible-sidebar-dark a:visited {
color: #b89ed6; /* Light purple (contrast ratio 7.99:1) */
}Check Contrast Tools
- WebAIM Contrast Checker
- Accessible Colors Tool
---
Best Practices
1. Semantic HTML
<SidebarComponent role="navigation">
<nav>
<ul>
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</SidebarComponent>2. Meaningful Labels
// Good
<button aria-label="Open navigation menu">☰</button>
// Bad
<button>Menu</button>3. Visible Focus Indicators
/* Always provide visible focus state */
a:focus,
button:focus {
outline: 2px solid #0056b3;
outline-offset: 2px;
}4. Alternative Text
<SidebarComponent type="Over">
<img src="logo.svg" alt="Company Logo" />
<img src="icon.svg" alt="" aria-hidden="true" /> {/* Decorative */}
</SidebarComponent>5. Test with Assistive Technology
# Screen readers to test with:
# - NVDA (free, Windows)
# - JAWS (commercial, Windows)
# - VoiceOver (built-in, macOS/iOS)
# - TalkBack (built-in, Android)
# Keyboard navigation test:
# - Tab through all elements
# - Use arrow keys in lists
# - Test Escape key
# - Test Enter/Space6. Accessibility Checklist
function AccessibilityChecklist() {
const checks = [
'✓ Semantic HTML (nav, button, etc)',
'✓ ARIA labels and roles',
'✓ Keyboard navigation (Tab, Arrow, Escape)',
'✓ Focus management (visible focus, initial focus)',
'✓ Screen reader support (alt text, labels)',
'✓ Color contrast (4.5:1 minimum)',
'✓ Sufficient touch target size (44x44px)',
'✓ No keyboard traps',
'✓ No auto-playing content',
'✓ Tested with screen readers'
];
return (
<div>
<h3>Accessibility Checklist</h3>
<ul>
{checks.map((check, i) => <li key={i}>{check}</li>)}
</ul>
</div>
);
}7. Complete Accessible Example
import React, { useState, useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function FullyAccessibleSidebar() {
const [isOpen, setIsOpen] = useState(false);
const sidebarRef = useRef(null);
const toggleRef = useRef(null);
useEffect(() => {
const handleEscape = (e) => {
if (e.key === 'Escape' && isOpen) {
sidebarRef.current?.hide();
setIsOpen(false);
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isOpen]);
const handleToggle = () => {
sidebarRef.current?.toggle();
setIsOpen(!isOpen);
};
return (
<div>
<header>
<ButtonComponent
ref={toggleRef}
id="sidebar-toggle"
cssClass="menu-button"
onClick={handleToggle}
aria-label="Toggle navigation menu"
aria-controls="main-sidebar"
aria-expanded={isOpen}
>
☰ <span>Menu</span>
</ButtonComponent>
<h1>Application</h1>
</header>
<SidebarComponent
ref={sidebarRef}
id="main-sidebar"
type="Over"
width="280px"
role="navigation"
aria-label="Main Navigation"
aria-expanded={isOpen}
change={(args) => {
const nowOpen = args.element.classList.contains('e-open');
setIsOpen(nowOpen);
if (toggleRef.current) {
toggleRef.current.setAttribute('aria-expanded', nowOpen);
}
}}
showBackdrop={true}
closeOnDocumentClick={true}
>
<nav aria-label="Navigation links">
<ul role="menubar">
<li role="none">
<a href="#home" role="menuitem" tabIndex="0">
🏠 Home
</a>
</li>
<li role="none">
<a href="#products" role="menuitem" tabIndex="0">
📦 Products
</a>
</li>
<li role="none">
<a href="#contact" role="menuitem" tabIndex="0">
📧 Contact
</a>
</li>
</ul>
</nav>
</SidebarComponent>
<main id="main-content">
<h2>Welcome</h2>
<p>Press ESC to close the sidebar or click outside.</p>
</main>
</div>
);
}
export default FullyAccessibleSidebar;---
Resources:
- WCAG 2.1 Guidelines
- ARIA Authoring Practices
- WebAIM
- Accessible Components
Content Integration
Table of Contents
---
ListView Integration
Basic ListView in Sidebar
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const sidebarRef = useRef(null);
const listItems = [
{ text: 'Home', id: '1' },
{ text: 'Profile', id: '2' },
{ text: 'Settings', id: '3' },
{ text: 'Logout', id: '4' }
];
const handleListClick = (args) => {
console.log('Selected:', args.text);
sidebarRef.current?.hide();
};
return (
<div>
<ButtonComponent onClick={() => sidebarRef.current?.toggle()}>
☰ Menu
</ButtonComponent>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="280px"
>
<h3>Navigation</h3>
<ListViewComponent
dataSource={listItems}
click={handleListClick}
/>
</SidebarComponent>
<div className="content">
<h1>Main Content</h1>
</div>
</div>
);
}
export default App;ListView with Icons and Actions
function SidebarWithListView() {
const [selectedItem, setSelectedItem] = React.useState(null);
const sidebarRef = React.useRef(null);
const listItems = [
{
text: 'Home',
icon: '🏠',
id: 'home'
},
{
text: 'Products',
icon: '📦',
id: 'products'
},
{
text: 'Orders',
icon: '📋',
id: 'orders'
},
{
text: 'Settings',
icon: '⚙️',
id: 'settings'
},
{
text: 'Logout',
icon: '🚪',
id: 'logout'
}
];
const handleItemSelect = (args) => {
setSelectedItem(args.text);
sidebarRef.current?.hide();
};
const itemTemplate = (props) => {
return (
<div className="list-item-template">
<span className="item-icon">{props.icon}</span>
<span className="item-text">{props.text}</span>
</div>
);
};
return (
<div>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="300px"
showBackdrop={true}
>
<h3>Menu</h3>
<ListViewComponent
dataSource={listItems}
template={itemTemplate}
click={handleItemSelect}
cssClass="sidebar-list"
/>
</SidebarComponent>
<div className="content">
<h1>Selected: {selectedItem || 'None'}</h1>
</div>
</div>
);
}CSS for List Styling
.sidebar-list .e-list-item {
padding: 12px 20px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: all 0.3s ease;
}
.sidebar-list .e-list-item:hover {
background-color: #f5f5f5;
border-left: 4px solid #1976d2;
padding-left: 16px;
}
.sidebar-list .e-list-item.e-active {
background-color: #e3f2fd;
color: #1976d2;
}
.list-item-template {
display: flex;
align-items: center;
gap: 12px;
}
.item-icon {
font-size: 20px;
}
.item-text {
flex: 1;
}---
TreeView Integration
Basic TreeView in Sidebar
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const sidebarRef = useRef(null);
const treeData = [
{
id: '1',
text: 'Products',
expanded: true,
children: [
{ id: '1-1', text: 'Electronics' },
{ id: '1-2', text: 'Clothing' },
{ id: '1-3', text: 'Books' }
]
},
{
id: '2',
text: 'Services',
expanded: false,
children: [
{ id: '2-1', text: 'Consulting' },
{ id: '2-2', text: 'Support' }
]
},
{
id: '3',
text: 'Settings'
}
];
const handleNodeClick = (args) => {
console.log('Clicked:', args.node.textContent);
};
return (
<div>
<ButtonComponent onClick={() => sidebarRef.current?.toggle()}>
☰ Menu
</ButtonComponent>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="300px"
>
<h3>Navigation</h3>
<TreeViewComponent
fields={{ dataSource: treeData, id: 'id', text: 'text', child: 'children' }}
nodeClicked={handleNodeClick}
/>
</SidebarComponent>
<div className="content">
<h1>Hierarchical Navigation</h1>
</div>
</div>
);
}
export default App;TreeView with Multi-level Categories
function SidebarWithHierarchy() {
const sidebarRef = React.useRef(null);
const [expandedNodes, setExpandedNodes] = React.useState(['1']);
const categoryData = [
{
id: '1',
text: '🏢 Business',
expanded: true,
children: [
{
id: '1-1',
text: '👥 Teams',
children: [
{ id: '1-1-1', text: '📌 Management' },
{ id: '1-1-2', text: '👨💼 Sales' },
{ id: '1-1-3', text: '🛠️ Engineering' }
]
},
{
id: '1-2',
text: '📊 Reports',
children: [
{ id: '1-2-1', text: '📈 Analytics' },
{ id: '1-2-2', text: '💰 Finance' }
]
}
]
},
{
id: '2',
text: '⚙️ Administration',
children: [
{ id: '2-1', text: '🔐 Security' },
{ id: '2-2', text: '👤 Users' },
{ id: '2-3', text: '🎨 Settings' }
]
}
];
const handleNodeClick = (args) => {
// Navigate or perform action
console.log('Navigate to:', args.node.textContent);
};
return (
<SidebarComponent
ref={sidebarRef}
type="Push"
width="320px"
>
<TreeViewComponent
fields={{ dataSource: categoryData, id: 'id', text: 'text', child: 'children' }}
nodeClicked={handleNodeClick}
cssClass="sidebar-tree"
/>
</SidebarComponent>
);
}CSS for TreeView Styling
.sidebar-tree .e-treeview {
border: none;
background: transparent;
}
.sidebar-tree .e-treeview .e-list-item {
padding: 8px 16px;
color: #555;
}
.sidebar-tree .e-treeview .e-list-item:hover {
background-color: #f5f5f5;
}
.sidebar-tree .e-treeview .e-list-item.e-active {
background-color: #e3f2fd;
border-left: 4px solid #1976d2;
color: #1976d2;
}
.sidebar-tree .e-treeview .e-icon {
margin-right: 10px;
font-size: 18px;
}---
Custom HTML Content
Complex Content Structure
function SidebarWithCustomContent() {
const sidebarRef = React.useRef(null);
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
width="300px"
>
{/* Header Section */}
<div className="sidebar-header">
<img src="logo.png" alt="Logo" className="logo" />
<h3>Dashboard</h3>
</div>
{/* User Section */}
<div className="user-section">
<img src="avatar.jpg" alt="User" className="avatar" />
<div className="user-info">
<p className="user-name">John Doe</p>
<p className="user-role">Administrator</p>
</div>
</div>
{/* Navigation Sections */}
<div className="nav-section">
<h4 className="section-title">Main</h4>
<nav className="nav">
<a href="#dashboard" className="nav-link active">
<span className="icon">📊</span>
<span>Dashboard</span>
</a>
<a href="#analytics" className="nav-link">
<span className="icon">📈</span>
<span>Analytics</span>
</a>
</nav>
</div>
<div className="nav-section">
<h4 className="section-title">Management</h4>
<nav className="nav">
<a href="#users" className="nav-link">
<span className="icon">👥</span>
<span>Users</span>
</a>
<a href="#settings" className="nav-link">
<span className="icon">⚙️</span>
<span>Settings</span>
</a>
</nav>
</div>
{/* Footer Section */}
<div className="sidebar-footer">
<a href="#logout" className="logout-btn">
🚪 Logout
</a>
</div>
</SidebarComponent>
);
}CSS for Custom Content
.sidebar-header {
padding: 20px;
border-bottom: 1px solid #e0e0e0;
text-align: center;
}
.sidebar-header .logo {
width: 50px;
height: 50px;
margin-bottom: 10px;
}
.user-section {
display: flex;
align-items: center;
gap: 15px;
padding: 15px 20px;
border-bottom: 1px solid #f0f0f0;
}
.user-section .avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
.user-info {
flex: 1;
}
.user-name {
font-weight: 600;
color: #333;
margin: 0;
}
.user-role {
color: #999;
font-size: 12px;
margin: 0;
}
.nav-section {
padding: 20px 0;
}
.section-title {
font-size: 12px;
text-transform: uppercase;
color: #999;
margin: 0 20px 10px;
letter-spacing: 1px;
}
.nav {
display: flex;
flex-direction: column;
}
.nav-link {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 20px;
color: #555;
text-decoration: none;
transition: all 0.3s ease;
border-left: 3px solid transparent;
}
.nav-link:hover {
background-color: #f5f5f5;
border-left-color: #1976d2;
}
.nav-link.active {
background-color: #e3f2fd;
color: #1976d2;
border-left-color: #1976d2;
}
.nav-link .icon {
font-size: 18px;
}
.sidebar-footer {
padding: 15px 20px;
border-top: 1px solid #e0e0e0;
margin-top: 20px;
}
.logout-btn {
display: block;
padding: 10px 15px;
background-color: #f5f5f5;
color: #d32f2f;
text-decoration: none;
border-radius: 4px;
text-align: center;
transition: all 0.3s ease;
}
.logout-btn:hover {
background-color: #ffebee;
color: #c62828;
}---
Dynamic Data Binding
Load Data from API
import React, { useRef, useEffect, useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
function SidebarWithDynamicData() {
const sidebarRef = useRef(null);
const [navItems, setNavItems] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Fetch navigation items from API
fetch('/api/navigation')
.then(res => res.json())
.then(data => {
setNavItems(data);
setLoading(false);
})
.catch(err => {
console.error('Failed to load navigation:', err);
setLoading(false);
});
}, []);
if (loading) {
return <div>Loading...</div>;
}
return (
<SidebarComponent type="Over" width="280px">
<h3>Navigation</h3>
<ListViewComponent dataSource={navItems} />
</SidebarComponent>
);
}
export default SidebarWithDynamicData;Real-time Updates
function SidebarWithRealtimeData() {
const [menuItems, setMenuItems] = useState([
{ id: '1', text: 'Inbox', badge: 5 },
{ id: '2', text: 'Sent', badge: 0 }
]);
// Update in real-time (e.g., WebSocket)
useEffect(() => {
const ws = new WebSocket('wss://api.example.com/notifications');
ws.onmessage = (event) => {
const notification = JSON.parse(event.data);
setMenuItems(prev => prev.map(item =>
item.id === notification.itemId
? { ...item, badge: item.badge + 1 }
: item
));
};
return () => ws.close();
}, []);
const itemTemplate = (props) => (
<div className="nav-item-with-badge">
<span>{props.text}</span>
{props.badge > 0 && (
<span className="badge">{props.badge}</span>
)}
</div>
);
return (
<ListViewComponent
dataSource={menuItems}
template={itemTemplate}
/>
);
}---
Menu Structures
Dropdown Menu Pattern
function SidebarWithDropdowns() {
const [expandedMenus, setExpandedMenus] = React.useState({});
const toggleMenu = (menuId) => {
setExpandedMenus(prev => ({
...prev,
[menuId]: !prev[menuId]
}));
};
return (
<div className="sidebar-menu">
{/* Collapsible Menu Item */}
<div className="menu-section">
<button
className="menu-header"
onClick={() => toggleMenu('products')}
>
📦 Products
<span className={`arrow ${expandedMenus.products ? 'open' : ''}`}>▼</span>
</button>
{expandedMenus.products && (
<div className="submenu">
<a href="#electronics">Electronics</a>
<a href="#clothing">Clothing</a>
<a href="#books">Books</a>
</div>
)}
</div>
<div className="menu-section">
<button
className="menu-header"
onClick={() => toggleMenu('services')}
>
🔧 Services
<span className={`arrow ${expandedMenus.services ? 'open' : ''}`}>▼</span>
</button>
{expandedMenus.services && (
<div className="submenu">
<a href="#consulting">Consulting</a>
<a href="#support">Support</a>
</div>
)}
</div>
</div>
);
}CSS for Menu Structures
.menu-section {
border-bottom: 1px solid #f0f0f0;
}
.menu-header {
width: 100%;
background: none;
border: none;
padding: 12px 20px;
text-align: left;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
color: #555;
transition: all 0.3s ease;
}
.menu-header:hover {
background-color: #f5f5f5;
}
.arrow {
transition: transform 0.3s ease;
font-size: 12px;
}
.arrow.open {
transform: rotate(180deg);
}
.submenu {
background-color: #fafafa;
display: flex;
flex-direction: column;
animation: slideDown 0.3s ease;
}
.submenu a {
padding: 10px 40px;
color: #777;
text-decoration: none;
display: block;
border-left: 3px solid transparent;
transition: all 0.3s ease;
}
.submenu a:hover {
background-color: #f0f0f0;
color: #1976d2;
border-left-color: #1976d2;
}
@keyframes slideDown {
from {
opacity: 0;
max-height: 0;
}
to {
opacity: 1;
max-height: 500px;
}
}---
Event Arguments Reference
Table of Contents
---
Overview
This reference documents the argument objects passed to Sidebar event handlers. Understanding these objects is essential for implementing proper event handling.
---
ChangeEventArgs
Passed to the change event handler. Represents state change notification with user interaction tracking.
Type Definition:
interface ChangeEventArgs {
element: HTMLElement // The Sidebar DOM element
name: string // Event name string ('change')
cancel?: boolean // Set to true to prevent the state change
isInteracted: boolean // True if state changed by user interaction
// False if changed programmatically
}Properties:
| Property | Type | Description |
|---|---|---|
element | HTMLElement | Reference to the Sidebar DOM element |
name | string | The name of the event ('change') |
cancel | boolean (optional) | Set to true to prevent the state change |
isInteracted | boolean | Indicates whether the state change was caused by user interaction (click, gesture, key) vs programmatic methods (show/hide/toggle) |
Usage Examples:
Example 1: Check interaction type
import { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [changeLog, setChangeLog] = useState([]);
const handleChange = (args) => {
if (args.isInteracted) {
console.log('User manually changed sidebar state');
setChangeLog(prev => [...prev, 'User action']);
} else {
console.log('State changed by program (show/hide/toggle methods)');
setChangeLog(prev => [...prev, 'Programmatic change']);
}
};
return (
<div>
<ul>
{changeLog.map((log, i) => <li key={i}>{log}</li>)}
</ul>
<SidebarComponent change={handleChange} />
</div>
);
}
export default App;Example 2: Access element properties
const handleChange = (args) => {
const isOpen = args.element.classList.contains('e-open');
const isAnimating = args.element.classList.contains('e-animate');
console.log('Open:', isOpen, 'Animating:', isAnimating);
};
return <SidebarComponent change={handleChange} />;Example 3: Cancel state change (edge case)
const handleChange = (args) => {
// Rarely used, but example for reference
if (restrictedMode && !args.isInteracted) {
args.cancel = true;
}
};
return <SidebarComponent change={handleChange} />;---
EventArgs
Passed to open, close, created, and destroyed event handlers. Provides detailed event information including the triggering event and sidebar model.
Type Definition:
interface EventArgs {
cancel?: boolean // Set to true to prevent the action (open/close)
element: HTMLElement // The Sidebar DOM element
event?: MouseEvent | Event // Original DOM event that triggered the action
isInteracted?: boolean // True if triggered by user interaction
model: SidebarModel // Current Sidebar configuration model
}Properties:
| Property | Type | Description |
|---|---|---|
cancel | boolean (optional) | For open/close events, set to true to prevent the action |
element | HTMLElement | Reference to the Sidebar DOM element |
event | `MouseEvent \ | Event` (optional) |
isInteracted | boolean (optional) | Indicates whether the event was triggered by user interaction |
model | SidebarModel | The complete Sidebar configuration model at time of event |
Usage Examples:
Example 1: Prevent opening based on conditions
import React from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [userAuthorized, setUserAuthorized] = React.useState(false);
const handleOpen = (args) => {
if (!userAuthorized) {
args.cancel = true;
console.log('Opening cancelled - authorization required');
}
};
return (
<SidebarComponent open={handleOpen} type="Over">
Sidebar Content
</SidebarComponent>
);
}
export default App;Example 2: Access event source
const handleClose = (args) => {
if (args.event) {
console.log('Close triggered by:', args.event.type);
console.log('Target element:', args.event.target);
}
};
return <SidebarComponent close={handleClose} />;Example 3: Access sidebar model configuration
const handleOpen = (args) => {
// Check current configuration
console.log('Current sidebar type:', args.model.type);
console.log('Current position:', args.model.position);
console.log('Current width:', args.model.width);
console.log('Animations enabled:', args.model.animate);
};
return <SidebarComponent open={handleOpen} />;Example 4: Distinguish event types
const handleOpen = (args) => {
if (args.isInteracted) {
console.log('User triggered opening (click, gesture, key)');
} else {
console.log('Program triggered opening (show/toggle methods)');
}
};
return <SidebarComponent open={handleOpen} />;Example 5: Conditional actions on close
const handleClose = (args) => {
// Different logic for user vs programmatic close
if (args.isInteracted) {
// User-triggered close - save preference
localStorage.setItem('userClosedSidebar', 'true');
} else {
// Programmatic close
console.log('Sidebar closed by app logic');
}
};
return <SidebarComponent close={handleClose} />;---
SidebarModel
Reference object containing the complete Sidebar configuration at time of event.
Type Definition:
interface SidebarModel {
type: 'Over' | 'Push' | 'Slide' | 'Auto'
position: 'Left' | 'Right'
width: string | number
target?: HTMLElement | string
isOpen: boolean
animate: boolean
showBackdrop: boolean
closeOnDocumentClick: boolean
enableDock: boolean
dockSize: string | number
enableGestures: boolean
enableRtl: boolean
enablePersistence: boolean
mediaQuery?: string | MediaQueryList
zIndex: string | number
}Properties:
| Property | Type | Description |
|---|---|---|
type | `'Over' \ | 'Push' \ |
position | `'Left' \ | 'Right'` |
width | `string \ | number` |
target | `HTMLElement \ | string` (optional) |
isOpen | boolean | Current open state |
animate | boolean | Animation enabled |
showBackdrop | boolean | Overlay visible |
closeOnDocumentClick | boolean | Auto-close enabled |
enableDock | boolean | Dock mode enabled |
dockSize | `string \ | number` |
enableGestures | boolean | Touch gestures enabled |
enableRtl | boolean | RTL mode enabled |
enablePersistence | boolean | Persistence enabled |
mediaQuery | `string \ | MediaQueryList` (optional) |
zIndex | `string \ | number` |
Usage Examples:
Example 1: Log all configuration on open
const handleOpen = (args) => {
console.log('Sidebar Configuration:', {
type: args.model.type,
position: args.model.position,
width: args.model.width,
openState: args.model.isOpen,
animations: args.model.animate,
backdrop: args.model.showBackdrop,
});
};
return <SidebarComponent open={handleOpen} />;Example 2: Verify responsive behavior
const handleOpen = (args) => {
if (args.model.type === 'Auto') {
console.log('Sidebar is in responsive Auto mode');
}
if (args.model.mediaQuery) {
console.log('Media query set:', args.model.mediaQuery);
}
};
return <SidebarComponent open={handleOpen} type="Auto" />;Example 3: Check persistence settings
const handleOpen = (args) => {
if (args.model.enablePersistence) {
console.log('Sidebar state will be saved to storage');
}
};
return (
<SidebarComponent
open={handleOpen}
enablePersistence={true}
/>
);---
Events Reference
Table of Contents
---
Overview
The Sidebar component provides 5 events for lifecycle and state tracking. Events can be preventable (open, close) or notification-only (change, created, destroyed).
---
change Event
Triggers when the sidebar state changes (expand/collapse). This is the primary event for tracking state transitions. Note: For Auto type sidebars, state changes on viewport resize will not include user interaction flag.
Event Type: EmitType<ChangeEventArgs>
Callback Signature:
(args: ChangeEventArgs) => voidExample 1: Track sidebar state changes
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [sidebarState, setSidebarState] = useState('closed');
const handleChange = (args) => {
if (args.element.classList.contains('e-open')) {
setSidebarState('open');
console.log('Sidebar opened');
} else {
setSidebarState('closed');
console.log('Sidebar closed');
}
};
return (
<>
<div>Sidebar is: {sidebarState}</div>
<SidebarComponent
change={handleChange}
type="Over"
width="250px"
>
Content
</SidebarComponent>
</>
);
}
export default App;Example 2: Differentiate user interaction from programmatic changes
const handleChange = (args) => {
if (args.isInteracted) {
console.log('User manually toggled sidebar');
} else {
console.log('Sidebar state changed programmatically');
}
};
return <SidebarComponent change={handleChange} />;Example 3: Log event name with change event
const handleChange = (args) => {
console.log(`Event: ${args.name}`);
console.log(`Is User Interaction: ${args.isInteracted}`);
console.log(`Element:`, args.element);
};
return <SidebarComponent change={handleChange} />;---
open Event
Triggers when the sidebar is about to open. You can prevent the opening by setting args.cancel = true.
Event Type: EmitType<EventArgs>
Callback Signature:
(args: EventArgs) => voidExample 1: Allow conditional opening
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [isAuthorized, setIsAuthorized] = useState(true);
const handleOpen = (args) => {
if (!isAuthorized) {
args.cancel = true; // Prevent opening
alert('Not authorized to open sidebar');
} else {
console.log('Opening sidebar...');
}
};
return (
<SidebarComponent
open={handleOpen}
type="Over"
>
Sidebar Content
</SidebarComponent>
);
}
export default App;Example 2: Access event details
const handleOpen = (args) => {
console.log('Open triggered by:', args.event);
console.log('User interaction:', args.isInteracted);
console.log('Element:', args.element);
};
return <SidebarComponent open={handleOpen} />;Example 3: Cancel based on external state
const handleOpen = (args) => {
if (userPreferences.sidebarDisabled) {
args.cancel = true;
showNotification('Sidebar is disabled');
}
};
return <SidebarComponent open={handleOpen} />;---
close Event
Triggers when the sidebar is about to close. You can prevent the closing by setting args.cancel = true.
Event Type: EmitType<EventArgs>
Callback Signature:
(args: EventArgs) => voidExample 1: Confirm before closing
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const handleClose = (args) => {
if (hasUnsavedChanges) {
const proceed = window.confirm(
'You have unsaved changes. Close anyway?'
);
if (!proceed) {
args.cancel = true; // Prevent closing
}
}
};
return (
<SidebarComponent
close={handleClose}
type="Over"
>
Sidebar Content
</SidebarComponent>
);
}
export default App;Example 2: Track close events
const handleClose = (args) => {
console.log('Closing sidebar...');
console.log('User triggered:', args.isInteracted);
if (args.isInteracted) {
console.log('User clicked to close');
} else {
console.log('Close triggered programmatically');
}
};
return <SidebarComponent close={handleClose} />;Example 3: Save state before closing
const handleClose = (args) => {
// Save current sidebar state to localStorage
localStorage.setItem('sidebarOpen', 'false');
console.log('Sidebar state saved');
};
return <SidebarComponent close={handleClose} />;---
created Event
Triggers after the sidebar component is initialized, rendered into the DOM, and ready to use. This is the ideal place to set up additional event listeners, initialize child components, or perform setup tasks.
Event Type: EmitType<Object>
Callback Signature:
() => voidExample 1: Initialize on component creation
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleCreated = () => {
console.log('Sidebar created and initialized');
console.log('Sidebar element:', sidebarRef.current?.element);
};
return (
<SidebarComponent
ref={sidebarRef}
created={handleCreated}
type="Over"
>
Sidebar Content
</SidebarComponent>
);
}
export default App;Example 2: Setup custom event listeners
const handleCreated = () => {
const sidebarElement = sidebarRef.current?.element;
// Add custom keyboard shortcuts
sidebarElement?.addEventListener('keydown', (e) => {
if (e.key === 's') {
// Custom action
}
});
console.log('Custom event listeners attached');
};
return (
<SidebarComponent
ref={sidebarRef}
created={handleCreated}
/>
);Example 3: Initialize related components
const handleCreated = () => {
console.log('Sidebar is ready');
// Initialize ListView or other components
initializeNavigationItems();
loadUserPreferences();
};
return (
<SidebarComponent created={handleCreated} />
);---
destroyed Event
Triggers when the sidebar component is destroyed/removed. Use this to clean up resources, remove event listeners, or perform tear-down tasks.
Event Type: EmitType<Object>
Callback Signature:
() => voidExample 1: Cleanup on destroy
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleDestroyed = () => {
console.log('Sidebar destroyed');
console.log('Cleaning up resources...');
};
return (
<SidebarComponent
ref={sidebarRef}
destroyed={handleDestroyed}
type="Over"
>
Sidebar Content
</SidebarComponent>
);
}
export default App;Example 2: Remove custom listeners on destroy
const handleDestroyed = () => {
// Remove custom event listeners
const sidebarElement = sidebarRef.current?.element;
sidebarElement?.removeEventListener('keydown', customKeyHandler);
// Clear cached data
sessionStorage.removeItem('sidebarState');
console.log('Resources cleaned up');
};
return (
<SidebarComponent destroyed={handleDestroyed} />
);Example 3: Notify parent component
const handleDestroyed = () => {
if (onSidebarDestroyed) {
onSidebarDestroyed();
}
};
return (
<SidebarComponent destroyed={handleDestroyed} />
);---
Event Patterns
State Tracking Pattern
const [isOpen, setIsOpen] = useState(false);
<SidebarComponent
change={(args) => {
setIsOpen(args.element.classList.contains('e-open'));
}}
/>Prevention Pattern
const handleOpen = (args) => {
if (!canOpen) {
args.cancel = true;
}
};
<SidebarComponent open={handleOpen} />Lifecycle Pattern
<SidebarComponent
created={() => setupListeners()}
destroyed={() => cleanupListeners()}
/>Interaction Detection Pattern
const handleChange = (args) => {
if (args.isInteracted) {
console.log('User action');
} else {
console.log('Programmatic change');
}
};
<SidebarComponent change={handleChange} />---
Getting Started with React Sidebar
Table of Contents
- Installation
- 1. Install Syncfusion Packages
- 2. Import CSS Styles
- 3. Import Components
- Basic Sidebar Implementation
- Minimal Example
- With State Management
- With Toggle Button
- Theme Configuration
- RTL (Right-to-Left) Support
- Responsive Sidebar
- Complete Setup Example
---
Installation
1. Install Syncfusion Packages
Install the required packages using npm:
npm install @syncfusion/ej2-react-navigations
npm install @syncfusion/ej2-react-buttonsFor Material or Bootstrap themes:
npm install @syncfusion/ej2-base
npm install @syncfusion/ej2-theme-bootstrap5
npm install @syncfusion/ej2-theme-material2. Import CSS Styles
Add theme CSS imports to your application entry point (index.js or main.jsx):
// Default theme
import '@syncfusion/ej2-navigations/styles/material.css';
// Or choose another theme:
// import '@syncfusion/ej2-navigations/styles/bootstrap5.css';
// import '@syncfusion/ej2-navigations/styles/fluent.css';
// import '@syncfusion/ej2-navigations/styles/tailwind.css';
// Import base styles
import '@syncfusion/ej2-base/styles/material.css';3. Import Components
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';---
Basic Sidebar Implementation
Minimal Example
import React from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import '@syncfusion/ej2-navigations/styles/material.css';
function App() {
return (
<SidebarComponent width="250px">
<h3>Sidebar Content</h3>
<p>This is a basic sidebar.</p>
</SidebarComponent>
);
}
export default App;With State Management
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [isOpen, setIsOpen] = useState(false);
const handleToggle = () => {
setIsOpen(!isOpen);
};
return (
<div className="container">
<ButtonComponent onClick={handleToggle}>
Toggle Sidebar
</ButtonComponent>
<SidebarComponent
width="250px"
isOpen={isOpen}
change={() => setIsOpen(!isOpen)}
type="Over"
>
<h3>Navigation</h3>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#services">Services</a></li>
</ul>
</SidebarComponent>
<div className="main-content">
<h1>Main Content Area</h1>
</div>
</div>
);
}
export default App;---
CSS Theme Configuration
Theme Options
Syncfusion provides multiple built-in themes:
| Theme | CSS File | Best For |
|---|---|---|
| Material | material.css | Modern Material Design |
| Bootstrap | bootstrap5.css | Bootstrap-styled apps |
| Fluent | fluent.css | Microsoft Fluent Design |
| Tailwind | tailwind.css | Tailwind CSS projects |
Applying Themes
// In index.js or main.jsx
// Material Theme (Default)
import '@syncfusion/ej2-navigations/styles/material.css';
import '@syncfusion/ej2-base/styles/material.css';
// Bootstrap Theme
// import '@syncfusion/ej2-navigations/styles/bootstrap5.css';
// import '@syncfusion/ej2-base/styles/bootstrap5.css';Custom Theme with CSS
/* Custom styles in your CSS file */
/* Sidebar background */
.e-sidebar {
background-color: #f5f5f5;
border-right: 1px solid #ddd;
}
/* Sidebar header */
.e-sidebar h3 {
color: #333;
padding: 20px;
border-bottom: 1px solid #ddd;
}
/* Navigation links */
.e-sidebar ul li a {
color: #555;
padding: 12px 20px;
display: block;
text-decoration: none;
transition: background-color 0.3s;
}
.e-sidebar ul li a:hover {
background-color: #e3f2fd;
color: #1976d2;
}---
Initial State Management
Control Sidebar Open State
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
// Start with sidebar open
const [isOpen, setIsOpen] = useState(true);
const handleChange = (args) => {
const sidebarElement = args.element;
const nowOpen = sidebarElement.classList.contains('e-open');
setIsOpen(nowOpen);
};
return (
<SidebarComponent
isOpen={isOpen}
change={handleChange}
type="Push"
width="250px"
>
{/* Content */}
</SidebarComponent>
);
}
export default App;Using useRef for Direct Control
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleShowClick = () => {
if (sidebarRef.current) {
sidebarRef.current.show();
}
};
const handleHideClick = () => {
if (sidebarRef.current) {
sidebarRef.current.hide();
}
};
const handleToggleClick = () => {
if (sidebarRef.current) {
sidebarRef.current.toggle();
}
};
return (
<div>
<div>
<button onClick={handleShowClick}>Show</button>
<button onClick={handleHideClick}>Hide</button>
<button onClick={handleToggleClick}>Toggle</button>
</div>
<SidebarComponent
ref={sidebarRef}
width="250px"
type="Over"
>
Sidebar Content
</SidebarComponent>
</div>
);
}
export default App;---
RTL (Right-to-Left) Support
Enable RTL for Arabic/Hebrew Languages
<SidebarComponent
enableRtl={true}
position="Right"
type="Over"
width="250px"
>
محتوى الشريط الجانبي {/* Arabic content */}
</SidebarComponent>RTL CSS Adjustments
/* RTL specific styles */
body[dir="rtl"] .e-sidebar {
border-right: none;
border-left: 1px solid #ddd;
}
body[dir="rtl"] .e-sidebar ul {
text-align: right;
}---
Responsive Sidebar Implementation
Responsive Layout with Bootstrap
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="container-fluid">
{/* Header */}
<header className="navbar navbar-light bg-light">
<div className="container-fluid">
<ButtonComponent
cssClass="btn-primary"
onClick={() => setIsOpen(!isOpen)}
>
☰ Menu
</ButtonComponent>
<span className="navbar-brand">My App</span>
</div>
</header>
<div className="row">
{/* Sidebar - Responsive */}
<div className="col-md-3">
<SidebarComponent
width="100%"
isOpen={isOpen}
type="Over"
showBackdrop={true}
closeOnDocumentClick={true}
>
<ul className="list-unstyled">
<li><a href="#home">Home</a></li>
<li><a href="#products">Products</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</SidebarComponent>
</div>
{/* Main Content - Responsive */}
<div className="col-md-9">
<h1>Main Content</h1>
<p>Content area that adapts to screen size.</p>
</div>
</div>
</div>
);
}
export default App;---
Complete Setup Example
import React, { useState, useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import '@syncfusion/ej2-navigations/styles/material.css';
import '@syncfusion/ej2-base/styles/material.css';
import './App.css';
function App() {
const [isOpen, setIsOpen] = useState(false);
const sidebarRef = useRef(null);
const handleToggle = () => {
if (sidebarRef.current) {
sidebarRef.current.toggle();
}
};
const handleChange = (args) => {
const isOpen = args.element.classList.contains('e-open');
setIsOpen(isOpen);
};
const handleNavItemClick = (e) => {
if (e.target.tagName === 'A') {
// Close sidebar on navigation
if (sidebarRef.current) {
sidebarRef.current.hide();
}
}
};
return (
<div className="app-container">
{/* Header */}
<header className="app-header">
<ButtonComponent
cssClass="e-btn e-icon-btn e-primary"
onClick={handleToggle}
title="Toggle Navigation"
>
<span className="e-btn-icon e-icons e-menu"></span>
</ButtonComponent>
<h1 className="app-title">My Application</h1>
</header>
{/* Main Layout */}
<div className="app-layout">
{/* Sidebar */}
<SidebarComponent
ref={sidebarRef}
id="sidebar"
width="280px"
type="Over"
isOpen={isOpen}
position="Left"
change={handleChange}
showBackdrop={true}
closeOnDocumentClick={true}
animate={true}
>
<div className="sidebar-content" onClick={handleNavItemClick}>
<h3>Navigation Menu</h3>
<nav className="nav-menu">
<a href="#home" className="nav-item">🏠 Home</a>
<a href="#products" className="nav-item">📦 Products</a>
<a href="#services" className="nav-item">🔧 Services</a>
<a href="#about" className="nav-item">ℹ️ About Us</a>
<a href="#contact" className="nav-item">📧 Contact</a>
</nav>
</div>
</SidebarComponent>
{/* Main Content */}
<main className="main-content">
<h2>Welcome to the Application</h2>
<p>This is the main content area. Click the menu button to toggle the sidebar.</p>
</main>
</div>
{/* Footer */}
<footer className="app-footer">
<p>© 2024 My Application. All rights reserved.</p>
</footer>
</div>
);
}
export default App;Corresponding CSS (App.css)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
}
.app-container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.app-header {
background-color: #1976d2;
color: white;
padding: 15px 20px;
display: flex;
align-items: center;
gap: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.app-title {
margin: 0;
font-size: 24px;
}
.app-layout {
display: flex;
flex: 1;
}
.sidebar-content {
padding: 20px;
}
.sidebar-content h3 {
color: #1976d2;
margin-bottom: 15px;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 10px;
}
.nav-menu {
display: flex;
flex-direction: column;
gap: 10px;
}
.nav-item {
display: block;
padding: 12px 15px;
color: #555;
text-decoration: none;
border-radius: 4px;
transition: all 0.3s ease;
}
.nav-item:hover {
background-color: #e3f2fd;
color: #1976d2;
padding-left: 20px;
}
.main-content {
flex: 1;
padding: 30px;
background-color: white;
margin: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.main-content h2 {
color: #1976d2;
margin-bottom: 15px;
}
.app-footer {
background-color: #f0f0f0;
padding: 20px;
text-align: center;
color: #666;
border-top: 1px solid #ddd;
}
/* Responsive Design */
@media (max-width: 768px) {
.app-header {
flex-direction: row;
}
.main-content {
margin: 10px;
padding: 15px;
}
}---
Methods Reference
Table of Contents
---
Overview
The Sidebar component provides 4 public methods for programmatic control. All methods return void.
---
show()
Displays the sidebar if currently closed. Triggers the open event. Optionally accepts an Event parameter that triggered the show action.
Signature:
show(e?: Event): voidParameters:
| Parameter | Type | Optional | Description |
|---|---|---|---|
e | Event | Yes | The DOM event that triggered the show action (e.g., click, keydown) |
Returns: void
Example 1: Basic show() without event
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleShow = () => {
sidebarRef.current?.show();
};
return (
<>
<button onClick={handleShow}>Open Sidebar</button>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
>
<div>Sidebar Content</div>
</SidebarComponent>
</>
);
}
export default App;Example 2: show() with event parameter from click handler
const handleShowWithEvent = (e) => {
sidebarRef.current?.show(e);
};
return (
<button onClick={handleShowWithEvent}>
Open Sidebar
</button>
);Example 3: show() with keyboard event
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
sidebarRef.current?.show(e);
}
};
return (
<input
type="button"
value="Show on Enter"
onKeyPress={handleKeyPress}
/>
);---
hide()
Hides the sidebar if currently open. Triggers the close event. Optionally accepts an Event parameter that triggered the hide action.
Signature:
hide(e?: Event): voidParameters:
| Parameter | Type | Optional | Description |
|---|---|---|---|
e | Event | Yes | The DOM event that triggered the hide action |
Returns: void
Example 1: Basic hide() without event
function App() {
const sidebarRef = useRef(null);
const handleHide = () => {
sidebarRef.current?.hide();
};
return (
<>
<button onClick={handleHide}>Close Sidebar</button>
<SidebarComponent ref={sidebarRef} type="Over" width="250px" />
</>
);
}Example 2: hide() with event from button click
const handleHideWithEvent = (e) => {
sidebarRef.current?.hide(e);
};
return (
<button onClick={handleHideWithEvent}>
Close Sidebar
</button>
);Example 3: hide() on escape key press
import { useEffect } from 'react';
useEffect(() => {
const handleEscapeKey = (e) => {
if (e.key === 'Escape') {
sidebarRef.current?.hide(e);
}
};
document.addEventListener('keydown', handleEscapeKey);
return () => document.removeEventListener('keydown', handleEscapeKey);
}, []);---
toggle()
Toggles the sidebar between open and closed states. Automatically triggers appropriate open or close events.
Signature:
toggle(): voidReturns: void
Example 1: Basic toggle
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleToggle = () => {
sidebarRef.current?.toggle();
};
return (
<>
<button className="e-btn e-primary" onClick={handleToggle}>
☰ Menu
</button>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
>
<div>Navigation Items</div>
</SidebarComponent>
</>
);
}
export default App;Example 2: Toggle with state synchronization
import { useState } from 'react';
function App() {
const sidebarRef = useRef(null);
const [isOpen, setIsOpen] = useState(false);
const handleToggle = () => {
sidebarRef.current?.toggle();
setIsOpen(!isOpen);
};
return (
<>
<button onClick={handleToggle}>
{isOpen ? 'Close' : 'Open'} Sidebar
</button>
<SidebarComponent ref={sidebarRef} type="Over" />
</>
);
}---
destroy()
Removes the sidebar component from the DOM and detaches all event handlers, attributes, and classes. After calling destroy(), the component must be re-initialized to use again.
Signature:
destroy(): voidReturns: void
Example 1: Basic destroy
function App() {
const sidebarRef = useRef(null);
const handleDestroy = () => {
sidebarRef.current?.destroy();
};
return (
<>
<button onClick={handleDestroy}>
Destroy Sidebar
</button>
<SidebarComponent ref={sidebarRef} />
</>
);
}Example 2: Cleanup on component unmount
import { useEffect } from 'react';
function App() {
const sidebarRef = useRef(null);
useEffect(() => {
return () => {
// Cleanup: destroy sidebar when component unmounts
sidebarRef.current?.destroy();
};
}, []);
return (
<SidebarComponent ref={sidebarRef} type="Over" />
);
}Example 3: Destroy and recreate pattern
function App() {
const containerRef = useRef(null);
const [destroyed, setDestroyed] = useState(false);
const handleDestroyAndRecreate = () => {
if (!destroyed) {
containerRef.current?.destroy();
setDestroyed(true);
} else {
setDestroyed(false);
}
};
return (
<>
<button onClick={handleDestroyAndRecreate}>
{destroyed ? 'Recreate' : 'Destroy'}
</button>
{!destroyed && (
<SidebarComponent ref={containerRef} type="Over" />
)}
</>
);
}---
Method Patterns
Control Pattern: show/hide
// Explicit show/hide control
const handleShowSidebar = () => sidebarRef.current?.show();
const handleHideSidebar = () => sidebarRef.current?.hide();
return (
<>
<button onClick={handleShowSidebar}>Open</button>
<button onClick={handleHideSidebar}>Close</button>
<SidebarComponent ref={sidebarRef} />
</>
);Toggle Pattern
// Simple toggle for hamburger menus
<button onClick={() => sidebarRef.current?.toggle()}>
☰ Menu
</button>Event Parameter Pattern
// Pass event context to methods
const handleMenuClick = (e) => {
sidebarRef.current?.show(e);
};Lifecycle Pattern
useEffect(() => {
return () => {
sidebarRef.current?.destroy();
};
}, []);---
Opening & Closing Sidebar
Table of Contents
- Toggle Functionality
- Programmatic Show/Hide
- Auto-Close Behavior
- Event Handling
- Animation & Transitions
- Complete Examples
---
Toggle Functionality
Basic Toggle with Button
import React, { useState, useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const sidebarRef = useRef(null);
const handleToggle = () => {
if (sidebarRef.current) {
sidebarRef.current.toggle();
}
};
return (
<div>
<ButtonComponent onClick={handleToggle}>
☰ Toggle Menu
</ButtonComponent>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
>
{/* Sidebar content */}
</SidebarComponent>
</div>
);
}
export default App;Toggle with State Management
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [isOpen, setIsOpen] = useState(false);
const handleChange = (args) => {
const nowOpen = args.element.classList.contains('e-open');
setIsOpen(nowOpen);
};
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>
Toggle: {isOpen ? 'Close' : 'Open'}
</button>
<SidebarComponent
isOpen={isOpen}
change={handleChange}
type="Over"
>
Content
</SidebarComponent>
</div>
);
}
export default App;---
Programmatic Show/Hide
Show Method
Opens the sidebar programmatically.
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const openSidebar = () => {
if (sidebarRef.current) {
sidebarRef.current.show();
}
};
return (
<div>
<button onClick={openSidebar}>Open Sidebar</button>
<SidebarComponent ref={sidebarRef} type="Over" width="250px">
Sidebar Content
</SidebarComponent>
</div>
);
}
export default App;Hide Method
Closes the sidebar programmatically.
const closeSidebar = () => {
if (sidebarRef.current) {
sidebarRef.current.hide();
}
};
return <button onClick={closeSidebar}>Close Sidebar</button>;Show/Hide Based on Conditions
function App() {
const sidebarRef = useRef(null);
const [userRole, setUserRole] = useState('guest');
const handleLogin = (role) => {
setUserRole(role);
// Show sidebar only for authenticated users
if (role !== 'guest' && sidebarRef.current) {
sidebarRef.current.show();
}
};
const handleLogout = () => {
setUserRole('guest');
// Hide sidebar on logout
if (sidebarRef.current) {
sidebarRef.current.hide();
}
};
return (
<div>
{userRole === 'guest' ? (
<>
<button onClick={() => handleLogin('user')}>Login</button>
</>
) : (
<button onClick={handleLogout}>Logout</button>
)}
<SidebarComponent
ref={sidebarRef}
type="Push"
width="250px"
>
<h3>Welcome, {userRole}!</h3>
</SidebarComponent>
</div>
);
}---
Auto-Close Behavior
Close on Document Click
Automatically closes sidebar when user clicks on main content area.
<SidebarComponent
type="Over"
width="250px"
closeOnDocumentClick={true}
showBackdrop={true}
>
{/* Closes when backdrop/content clicked */}
</SidebarComponent>Caveat: Works best with showBackdrop={true} for better UX.
Close on Escape Key
import React, { useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
useEffect(() => {
const handleEscape = (event) => {
if (event.key === 'Escape' && sidebarRef.current) {
sidebarRef.current.hide();
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, []);
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
>
Press ESC to close
</SidebarComponent>
);
}
export default App;Close on Navigation Item Click
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const sidebarRef = useRef(null);
const handleNavigation = (e) => {
if (e.target.tagName === 'A') {
// Close sidebar when any link is clicked
if (sidebarRef.current) {
sidebarRef.current.hide();
}
}
};
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
>
<nav onClick={handleNavigation}>
<a href="#home">Home</a>
<a href="#about">About</a>
<a href="#contact">Contact</a>
</nav>
</SidebarComponent>
);
}
export default App;Close After Delay
function App() {
const sidebarRef = useRef(null);
const openAndAutoClose = () => {
if (sidebarRef.current) {
sidebarRef.current.show();
// Auto-close after 5 seconds
setTimeout(() => {
if (sidebarRef.current) {
sidebarRef.current.hide();
}
}, 5000);
}
};
return (
<div>
<button onClick={openAndAutoClose}>Open (Auto-closes in 5s)</button>
<SidebarComponent ref={sidebarRef} type="Over" width="250px">
This sidebar will auto-close
</SidebarComponent>
</div>
);
}---
Event Handling
Change Event (State Change)
Triggers when sidebar opens or closes.
<SidebarComponent
change={(args) => {
const isNowOpen = args.element.classList.contains('e-open');
console.log(isNowOpen ? 'Opened' : 'Closed');
console.log('User interaction:', args.isInteracted);
}}
/>Open Event (Before Opening)
Triggers before sidebar opens. Can prevent opening.
<SidebarComponent
open={(args) => {
console.log('Sidebar opening...');
// Prevent opening under certain conditions
if (userHasNoPermission) {
args.cancel = true;
}
}}
/>Close Event (Before Closing)
Triggers before sidebar closes. Can prevent closing.
<SidebarComponent
close={(args) => {
console.log('Sidebar closing...');
// Ask for confirmation before closing
if (!confirm('Are you sure?')) {
args.cancel = true;
}
}}
/>Created & Destroyed Events
<SidebarComponent
created={() => console.log('Sidebar initialized')}
destroyed={() => console.log('Sidebar removed from DOM')}
/>Complete Event Example
import React, { useState, useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [status, setStatus] = useState('');
const sidebarRef = useRef(null);
const handleChange = (args) => {
const isOpen = args.element.classList.contains('e-open');
setStatus(`State changed: ${isOpen ? 'Opened' : 'Closed'}`);
};
const handleOpen = (args) => {
setStatus('Opening...');
};
const handleClose = (args) => {
setStatus('Closing...');
};
return (
<div>
<p>Status: {status}</p>
<button onClick={() => sidebarRef.current?.toggle()}>Toggle</button>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
change={handleChange}
open={handleOpen}
close={handleClose}
>
Sidebar with Events
</SidebarComponent>
</div>
);
}
export default App;---
Animation & Transitions
Enable/Disable Animations
// With animation (default)
<SidebarComponent animate={true} />
// Without animation (instant)
<SidebarComponent animate={false} />Custom Animation Duration
/* Slower animation */
.e-sidebar.e-open {
transition: transform 0.5s ease-in-out;
}
/* Faster animation */
.e-sidebar.e-open {
transition: transform 0.2s ease-out;
}Animation Effects
/* Slide in from left */
.e-sidebar.e-slide {
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
/* Fade and slide */
.e-sidebar.e-open {
animation: fadeSlide 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@keyframes fadeSlide {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}---
Complete Examples
Example 1: Mobile Menu with All Features
import React, { useState, useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function MobileMenu() {
const [isOpen, setIsOpen] = useState(false);
const [lastAction, setLastAction] = useState('');
const sidebarRef = useRef(null);
useEffect(() => {
const handleEscape = (e) => {
if (e.key === 'Escape' && isOpen) {
sidebarRef.current?.hide();
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isOpen]);
const handleNavClick = (e) => {
if (e.target.tagName === 'A') {
setLastAction(`Navigated to: ${e.target.textContent}`);
sidebarRef.current?.hide();
}
};
return (
<div className="mobile-menu-app">
<header className="header">
<ButtonComponent
cssClass="e-icon-btn e-outline"
onClick={() => setIsOpen(!isOpen)}
>
☰
</ButtonComponent>
<h1>Mobile App</h1>
</header>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="280px"
isOpen={isOpen}
change={() => setIsOpen(!isOpen)}
open={() => setLastAction('Menu opened')}
close={() => setLastAction('Menu closed')}
showBackdrop={true}
closeOnDocumentClick={true}
animate={true}
>
<nav className="nav" onClick={handleNavClick}>
<a href="#home" className="nav-item">🏠 Home</a>
<a href="#products" className="nav-item">📦 Products</a>
<a href="#about" className="nav-item">ℹ️ About</a>
<a href="#contact" className="nav-item">📧 Contact</a>
<a href="#settings" className="nav-item">⚙️ Settings</a>
</nav>
</SidebarComponent>
<main className="main-content">
<h2>Welcome</h2>
<p>Last action: {lastAction || 'None'}</p>
</main>
</div>
);
}
export default MobileMenu;Example 2: Desktop Sidebar with Persistent State
function DesktopSidebar() {
const [isOpen, setIsOpen] = useState(() => {
// Load from localStorage
return localStorage.getItem('sidebarOpen') === 'true';
});
const sidebarRef = useRef(null);
useEffect(() => {
// Save to localStorage
localStorage.setItem('sidebarOpen', isOpen);
}, [isOpen]);
return (
<SidebarComponent
ref={sidebarRef}
type="Push"
width="250px"
isOpen={isOpen}
change={() => setIsOpen(!isOpen)}
>
{/* Persistent sidebar */}
</SidebarComponent>
);
}Example 3: Conditional Sidebar Opening
function ConditionalSidebar() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const sidebarRef = useRef(null);
const login = async (credentials) => {
try {
const response = await authenticate(credentials);
if (response.success) {
setIsAuthenticated(true);
// Open sidebar on successful login
sidebarRef.current?.show();
}
} catch (error) {
console.error('Login failed');
}
};
if (!isAuthenticated) {
return <LoginForm onLogin={login} />;
}
return (
<SidebarComponent
ref={sidebarRef}
type="Push"
isOpen={true}
>
{/* Dashboard with sidebar */}
</SidebarComponent>
);
}---
Properties Reference
Table of Contents
- Overview
- Core Properties
- target
- width
- position
- type
- isOpen
- Display Properties
- showBackdrop
- animate
- zIndex
- Behavior Properties
- closeOnDocumentClick
- enableGestures
- enableRtl
- mediaQuery
- enableDock
- dockSize
- enablePersistence
- Quick Reference Table
---
Overview
The Sidebar component provides 18 properties to control appearance, behavior, and state. This reference covers all properties with types, defaults, and practical examples.
---
Core Properties
target
Type: HTMLElement | string Default: null
Specifies the container element where the sidebar should be rendered. This allows placing the sidebar inside a specific DOM element instead of the document body.
Use Cases:
- Rendering sidebar within a specific container
- Multiple sidebars in different containers
- Custom layout patterns
Example:
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const containerRef = useRef(null);
return (
<div>
{/* Target container for sidebar */}
<div ref={containerRef} className="sidebar-container" style={{ position: 'relative', height: '500px' }}>
<SidebarComponent
target={containerRef.current}
width="250px"
type="Push"
>
<div>Sidebar content inside target container</div>
</SidebarComponent>
</div>
</div>
);
}
export default App;---
width
Type: string | number Default: 'auto'
Sets the width of the sidebar. Can be specified in pixels (e.g., '250px') or percentage (e.g., '25%').
Example:
<SidebarComponent width="280px" />
<SidebarComponent width="25%" />
<SidebarComponent width={250} />---
position
Type: 'Left' | 'Right' Default: 'Left'
Determines sidebar placement relative to main content.
Example:
// Left-aligned sidebar (default)
<SidebarComponent position="Left" />
// Right-aligned sidebar (for RTL or alternative layouts)
<SidebarComponent position="Right" />---
type
Type: 'Over' | 'Push' | 'Slide' | 'Auto' Default: 'Auto'
Specifies how the sidebar interacts with main content:
- Over - Floats above content, no content movement
- Push - Pushes content aside when open
- Slide - Translates content without resizing
- Auto - Over on mobile, Push on desktop
Example:
// Floating drawer menu (mobile pattern)
<SidebarComponent type="Over" />
// Sidebar with content shift (desktop pattern)
<SidebarComponent type="Push" />
// Responsive behavior
<SidebarComponent type="Auto" />---
isOpen
Type: boolean Default: false
Controls the open/closed state of the sidebar. For Auto type, this property is ignored on mobile (type becomes Over regardless).
Example:
import { useState } from 'react';
function App() {
const [isOpen, setIsOpen] = useState(true);
return (
<SidebarComponent
isOpen={isOpen}
change={(args) => setIsOpen(args.element.classList.contains('e-open'))}
>
Content
</SidebarComponent>
);
}---
Display Properties
showBackdrop
Type: boolean Default: false
Displays a semi-transparent overlay behind the sidebar when open. Commonly used with Over type sidebars.
Example:
<SidebarComponent
type="Over"
showBackdrop={true}
closeOnDocumentClick={true}
/>CSS Styling:
.e-sidebar-overlay {
background-color: rgba(0, 0, 0, 0.5);
opacity: 0.5;
}---
animate
Type: boolean Default: true
Enables smooth CSS transitions when opening/closing the sidebar.
Example:
// With animation
<SidebarComponent animate={true} />
// Without animation (instant)
<SidebarComponent animate={false} />---
zIndex
Type: string | number Default: 1000
Sets the CSS z-index for the sidebar (applicable to Over type). Controls layering above other elements.
Example:
<SidebarComponent
type="Over"
zIndex={9999}
showBackdrop={true}
/>---
Behavior Properties
closeOnDocumentClick
Type: boolean Default: false
Automatically closes the sidebar when clicking on the main content area. Useful for drawer/modal-like behavior.
Example:
<SidebarComponent
type="Over"
closeOnDocumentClick={true}
/>---
enableGestures
Type: boolean Default: true
Enables touch swipe gestures on mobile devices to open/close the sidebar.
Example:
<SidebarComponent
enableGestures={true} // Swipe to open/close
type="Over"
/>---
enableRtl
Type: boolean Default: false
Renders the sidebar in right-to-left (RTL) mode for Arabic, Hebrew, and other RTL languages.
Example:
<SidebarComponent
enableRtl={true}
position="Right"
/>---
mediaQuery
Type: string | MediaQueryList Default: null
CSS media query string that triggers sidebar state. Sidebar auto-opens when media query matches.
Example:
// Open sidebar on screens wider than 768px
<SidebarComponent
mediaQuery="(min-width: 768px)"
isOpen={false}
type="Over"
/>
// Custom breakpoint
<SidebarComponent
mediaQuery="(max-width: 600px)"
/>---
enableDock
Type: boolean Default: false
Enables dock/minimize mode - sidebar collapses to a narrow panel showing only icons.
Example:
<SidebarComponent
enableDock={true}
dockSize="50px"
width="250px"
/>---
dockSize
Type: string | number Default: 'auto'
Width of the sidebar when docked (only applicable when enableDock={true}).
Example:
<SidebarComponent
enableDock={true}
dockSize="50px" // Icon-only bar
width="250px" // Expanded width
type="Push"
/>---
enablePersistence
Type: boolean Default: false
Saves sidebar state (position and type) to browser storage and restores it on page reload.
Example:
<SidebarComponent
enablePersistence={true}
position="Left"
type="Auto"
/>---
Quick Reference Table
| Property | Type | Default | Purpose |
|---|---|---|---|
| target | `HTMLElement \ | string` | null |
| width | `string \ | number` | 'auto' |
| position | `'Left' \ | 'Right'` | 'Left' |
| type | `'Over' \ | 'Push' \ | 'Slide' \ |
| isOpen | boolean | false | Open state |
| showBackdrop | boolean | false | Overlay |
| animate | boolean | true | Animations |
| zIndex | `string \ | number` | 1000 |
| closeOnDocumentClick | boolean | false | Auto-close |
| enableGestures | boolean | true | Touch swipe |
| enableRtl | boolean | false | RTL mode |
| mediaQuery | `string \ | MediaQueryList` | null |
| enableDock | boolean | false | Dock mode |
| dockSize | `string \ | number` | 'auto' |
| enablePersistence | boolean | false | Save state |
---
Sidebar Positioning & Behavior
Table of Contents
---
Sidebar Types
The type property controls how the sidebar interacts with main content.
Type: Over (Floating)
Behavior: Sidebar floats above the main content without pushing or shifting it.
Best For:
- Mobile drawer menus
- Modal-like sidebars
- Floating panels
Example:
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="app">
<ButtonComponent onClick={() => setIsOpen(!isOpen)}>
☰ Menu
</ButtonComponent>
<SidebarComponent
type="Over"
width="280px"
isOpen={isOpen}
change={() => setIsOpen(!isOpen)}
showBackdrop={true}
closeOnDocumentClick={true}
>
<h3>Over Type Sidebar</h3>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</SidebarComponent>
<div className="content">
<h1>Main Content Area</h1>
<p>Content remains in same position when sidebar opens.</p>
</div>
</div>
);
}
export default App;Type: Push (Content Shift)
Behavior: Sidebar pushes main content aside when open. Content width reduces to accommodate sidebar.
Best For:
- Desktop navigation layouts
- Persistent sidebars
- Dashboard layouts
Example:
<SidebarComponent
type="Push"
width="250px"
position="Left"
isOpen={true}
animate={true}
>
<h3>Push Type Sidebar</h3>
<ul>
<li><a href="#profile">Profile</a></li>
<li><a href="#settings">Settings</a></li>
<li><a href="#logout">Logout</a></li>
</ul>
</SidebarComponent>Type: Slide (Translate)
Behavior: Sidebar slides in without pushing content. Main content stays full-width but may be covered by sidebar.
Best For:
- Side panels
- Secondary navigation
- Complementary content areas
Example:
<SidebarComponent
type="Slide"
width="300px"
position="Right"
>
<h3>Slide Type Sidebar</h3>
<p>Sidebar slides without affecting main content layout.</p>
</SidebarComponent>Type: Auto (Responsive)
Behavior: Automatically switches type based on screen size.
- Mobile (< 768px): Over type
- Desktop (≥ 768px): Push type
Best For:
- Responsive applications
- Mobile-first designs
Example:
<SidebarComponent
type="Auto"
width="250px"
isOpen={false}
mediaQuery="(min-width: 768px)"
>
<h3>Auto Type Sidebar</h3>
<p>Over on mobile, Push on desktop.</p>
</SidebarComponent>Type Comparison Table:
| Type | Interaction | Content Movement | Use Case |
|---|---|---|---|
| Over | Float above | None | Mobile menus |
| Push | Side-by-side | Shifts right | Desktop nav |
| Slide | Slide in | None/Covered | Panels |
| Auto | Responsive | Depends on screen | Responsive apps |
---
Position (Left/Right)
The position property determines sidebar placement relative to content.
Position: Left (Default)
Standard for LTR languages (English, French, etc.)
<SidebarComponent
position="Left"
width="250px"
type="Push"
>
{/* Left-aligned sidebar */}
</SidebarComponent>Position: Right
Standard for RTL languages (Arabic, Hebrew) or alternative layouts
<SidebarComponent
position="Right"
width="250px"
type="Push"
enableRtl={true}
>
{/* Right-aligned sidebar */}
</SidebarComponent>CSS Layout with Left/Right Positioning
/* Left positioned sidebar */
.sidebar-left {
display: flex;
flex-direction: row;
}
.sidebar-left .e-sidebar {
order: 1;
}
.sidebar-left .main-content {
order: 2;
flex: 1;
}
/* Right positioned sidebar */
.sidebar-right {
display: flex;
flex-direction: row-reverse;
}
.sidebar-right .e-sidebar {
order: 2;
}
.sidebar-right .main-content {
order: 1;
flex: 1;
}---
Width Configuration
Fixed Width in Pixels
<SidebarComponent width="250px" />
<SidebarComponent width="300px" />Responsive Width
<SidebarComponent width="25%" />
<SidebarComponent width="100%" />Dynamic Width Based on Content
<SidebarComponent width="auto">
{/* Width auto-adjusts to content */}
</SidebarComponent>Width Adjustment Example
function App() {
const [sidebarWidth, setSidebarWidth] = useState('250px');
const handleResize = () => {
if (window.innerWidth < 768) {
setSidebarWidth('80vw'); // 80% of viewport on mobile
} else {
setSidebarWidth('250px'); // Fixed on desktop
}
};
React.useEffect(() => {
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<SidebarComponent width={sidebarWidth}>
Responsive Sidebar
</SidebarComponent>
);
}---
Dock Mode
Dock Mode allows sidebars to collapse to a narrow "icon bar" while keeping functionality.
Basic Dock Setup
<SidebarComponent
enableDock={true}
dockSize="50px" // Width when docked
width="250px" // Width when expanded
type="Push"
>
{/* Sidebar content */}
</SidebarComponent>Icon-Based Dock Navigation
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [isDocked, setIsDocked] = useState(false);
return (
<SidebarComponent
enableDock={true}
dockSize="50px"
width="250px"
type="Push"
>
{/* Icon bar when docked */}
<div className="dock-icons">
<a href="#home" className="nav-icon" title="Home">
🏠
</a>
<a href="#search" className="nav-icon" title="Search">
🔍
</a>
<a href="#profile" className="nav-icon" title="Profile">
👤
</a>
<a href="#settings" className="nav-icon" title="Settings">
⚙️
</a>
</div>
{/* Full labels when expanded */}
<div className="expanded-menu" style={{ display: isDocked ? 'none' : 'block' }}>
<nav>
<a href="#home">🏠 Home</a>
<a href="#search">🔍 Search</a>
<a href="#profile">👤 Profile</a>
<a href="#settings">⚙️ Settings</a>
</nav>
</div>
</SidebarComponent>
);
}
export default App;Dock CSS Styling
/* Icon bar styling */
.e-sidebar.e-dock .dock-icons {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 10px;
}
.e-sidebar.e-dock .dock-icons .nav-icon {
font-size: 24px;
cursor: pointer;
padding: 10px;
border-radius: 50%;
transition: background-color 0.3s;
}
.e-sidebar.e-dock .dock-icons .nav-icon:hover {
background-color: #e3f2fd;
}
.e-sidebar.e-dock .expanded-menu {
display: none;
}
/* When expanded */
.e-sidebar:not(.e-dock) .expanded-menu {
display: block;
padding: 20px;
}
.e-sidebar:not(.e-dock) .dock-icons {
display: none;
}---
Multiple Sidebars
Left and Right Sidebars
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [leftOpen, setLeftOpen] = useState(false);
const [rightOpen, setRightOpen] = useState(false);
return (
<div className="multi-sidebar-layout">
{/* Left Sidebar */}
<SidebarComponent
type="Push"
position="Left"
width="250px"
isOpen={leftOpen}
change={() => setLeftOpen(!leftOpen)}
>
<h3>Navigation</h3>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#products">Products</a></li>
<li><a href="#services">Services</a></li>
</ul>
</SidebarComponent>
{/* Main Content */}
<main className="main-content">
<h1>Main Content Area</h1>
<p>Content between two sidebars</p>
</main>
{/* Right Sidebar */}
<SidebarComponent
type="Over"
position="Right"
width="280px"
isOpen={rightOpen}
change={() => setRightOpen(!rightOpen)}
showBackdrop={true}
>
<h3>Properties</h3>
<div className="properties-panel">
<p>Right sidebar content here</p>
</div>
</SidebarComponent>
</div>
);
}
export default App;CSS for Multiple Sidebars
.multi-sidebar-layout {
display: flex;
min-height: 100vh;
}
.multi-sidebar-layout .e-sidebar:first-child {
order: 1;
}
.multi-sidebar-layout .main-content {
order: 2;
flex: 1;
padding: 20px;
overflow-y: auto;
}
.multi-sidebar-layout .e-sidebar:last-child {
order: 3;
}---
Responsive Auto Mode
MediaQuery Configuration
// Open on screens wider than 768px
<SidebarComponent
type="Auto"
mediaQuery="(min-width: 768px)"
isOpen={false}
width="250px"
/>Responsive Sidebar with Breakpoints
import React, { useState, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [sidebarConfig, setSidebarConfig] = useState({
type: 'Over',
isOpen: false,
width: '280px'
});
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 1200) {
// Large screens: Push mode, always open
setSidebarConfig({
type: 'Push',
isOpen: true,
width: '280px'
});
} else if (window.innerWidth >= 768) {
// Medium screens: Push mode, manual toggle
setSidebarConfig({
type: 'Push',
isOpen: false,
width: '250px'
});
} else {
// Small screens: Over mode, modal-like
setSidebarConfig({
type: 'Over',
isOpen: false,
width: '80vw'
});
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<SidebarComponent
type={sidebarConfig.type}
isOpen={sidebarConfig.isOpen}
width={sidebarConfig.width}
showBackdrop={sidebarConfig.type === 'Over'}
closeOnDocumentClick={sidebarConfig.type === 'Over'}
>
Responsive Sidebar
</SidebarComponent>
);
}
export default App;CSS Media Queries for Responsive Layout
/* Mobile */
@media (max-width: 767px) {
.e-sidebar {
width: 80vw !important;
type: 'Over';
}
}
/* Tablet */
@media (min-width: 768px) and (max-width: 1199px) {
.e-sidebar {
width: 250px !important;
}
}
/* Desktop */
@media (min-width: 1200px) {
.e-sidebar {
width: 280px !important;
display: flex; /* Always visible */
}
}---
Complete Responsive Example
import React, { useState, useRef, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [config, setConfig] = useState({
type: 'Over',
isOpen: false,
width: '280px'
});
const sidebarRef = useRef(null);
useEffect(() => {
const updateSidebar = () => {
const width = window.innerWidth;
if (width >= 1024) {
setConfig({ type: 'Push', isOpen: true, width: '280px' });
} else if (width >= 768) {
setConfig({ type: 'Push', isOpen: false, width: '250px' });
} else {
setConfig({ type: 'Over', isOpen: false, width: '75vw' });
}
};
updateSidebar();
window.addEventListener('resize', updateSidebar);
return () => window.removeEventListener('resize', updateSidebar);
}, []);
return (
<div className="responsive-layout">
<header>
<ButtonComponent onClick={() => setConfig(c => ({ ...c, isOpen: !c.isOpen }))}>
☰ Menu
</ButtonComponent>
<h1>Responsive Sidebar App</h1>
</header>
<SidebarComponent
ref={sidebarRef}
type={config.type}
isOpen={config.isOpen}
width={config.width}
showBackdrop={config.type === 'Over'}
closeOnDocumentClick={config.type === 'Over'}
>
<nav className="sidebar-nav">
<a href="#home">Home</a>
<a href="#products">Products</a>
<a href="#services">Services</a>
<a href="#about">About</a>
</nav>
</SidebarComponent>
<main>
<h2>Welcome</h2>
<p>Resize the browser to see responsive behavior.</p>
</main>
</div>
);
}
export default App;---
Styling & Customization
Table of Contents
- Theme Application
- CSS Class Customization
- Animation Variations
- Responsive Breakpoints
- RTL Support
- Custom Animations
---
Theme Application
Available Themes
Syncfusion provides four built-in themes:
// 1. Material Theme (Default, Modern)
import '@syncfusion/ej2-navigations/styles/material.css';
import '@syncfusion/ej2-base/styles/material.css';
// 2. Bootstrap Theme (Bootstrap design)
import '@syncfusion/ej2-navigations/styles/bootstrap5.css';
import '@syncfusion/ej2-base/styles/bootstrap5.css';
// 3. Fluent Theme (Microsoft Fluent)
import '@syncfusion/ej2-navigations/styles/fluent.css';
import '@syncfusion/ej2-base/styles/fluent.css';
// 4. Tailwind Theme (Tailwind CSS)
import '@syncfusion/ej2-navigations/styles/tailwind.css';
import '@syncfusion/ej2-base/styles/tailwind.css';Dynamic Theme Switching
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function App() {
const [theme, setTheme] = useState('material');
const switchTheme = (newTheme) => {
setTheme(newTheme);
// Remove old theme
document.querySelectorAll('link[data-theme]').forEach(link => {
link.remove();
});
// Add new theme
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = `url`;
link.setAttribute('data-theme', newTheme);
document.head.appendChild(link);
};
return (
<div>
<div className="theme-switcher">
<button onClick={() => switchTheme('material')}>Material</button>
<button onClick={() => switchTheme('bootstrap5')}>Bootstrap</button>
<button onClick={() => switchTheme('fluent')}>Fluent</button>
</div>
<SidebarComponent type="Over" width="250px">
Themed Sidebar
</SidebarComponent>
</div>
);
}
export default App;---
CSS Class Customization
Component Classes
Key Syncfusion sidebar CSS classes:
/* Sidebar container */
.e-sidebar { }
/* When sidebar is open */
.e-sidebar.e-open { }
/* When sidebar is closed */
.e-sidebar:not(.e-open) { }
/* Backdrop overlay */
.e-sidebar-overlay { }
/* Content within sidebar */
.e-sidebar-content { }Custom Styling Example
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import './CustomSidebar.css';
function App() {
const sidebarRef = useRef(null);
return (
<SidebarComponent
ref={sidebarRef}
type="Over"
width="280px"
cssClass="custom-sidebar"
>
<h3>Custom Styled Sidebar</h3>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</SidebarComponent>
);
}
export default App;CustomSidebar.css
/* Custom sidebar styling */
.custom-sidebar {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.custom-sidebar h3 {
color: white;
padding: 20px;
margin: 0;
border-bottom: 2px solid rgba(255, 255, 255, 0.2);
}
.custom-sidebar ul {
list-style: none;
padding: 0;
margin: 0;
}
.custom-sidebar ul li {
margin: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.custom-sidebar ul li a {
display: block;
padding: 15px 20px;
color: rgba(255, 255, 255, 0.9);
text-decoration: none;
transition: all 0.3s ease;
}
.custom-sidebar ul li a:hover {
background-color: rgba(255, 255, 255, 0.1);
padding-left: 25px;
}
.custom-sidebar ul li a:active {
background-color: rgba(255, 255, 255, 0.2);
}
/* Overlay styling */
.custom-sidebar + .e-sidebar-overlay {
background-color: rgba(0, 0, 0, 0.7);
}---
Animation Variations
Animation Speed Control
/* Slow animation (700ms) */
.slow-animation.e-sidebar {
transition: transform 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* Fast animation (200ms) */
.fast-animation.e-sidebar {
transition: transform 0.2s ease-out;
}
/* Standard animation (300ms) */
.standard-animation.e-sidebar {
transition: transform 0.3s ease-in-out;
}Easing Functions
/* Ease-in (slow start) */
.ease-in.e-sidebar {
transition: transform 0.4s ease-in;
}
/* Ease-out (slow end) */
.ease-out.e-sidebar {
transition: transform 0.4s ease-out;
}
/* Custom cubic-bezier (bouncy) */
.bouncy.e-sidebar {
transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* Custom cubic-bezier (smooth) */
.smooth.e-sidebar {
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}Animation Presets
import React, { useState, useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function AnimatedSidebar() {
const [animationType, setAnimationType] = useState('standard');
const sidebarRef = useRef(null);
return (
<div>
<select onChange={(e) => setAnimationType(e.target.value)}>
<option value="standard">Standard</option>
<option value="slow">Slow</option>
<option value="fast">Fast</option>
<option value="bouncy">Bouncy</option>
</select>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="250px"
cssClass={`${animationType}-animation`}
animate={true}
>
Animated Sidebar
</SidebarComponent>
</div>
);
}
export default AnimatedSidebar;---
Responsive Breakpoints
Mobile-First Responsive Design
import React, { useState, useEffect } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function ResponsiveSidebar() {
const [config, setConfig] = useState({
type: 'Over',
width: '80vw',
breakpoint: 'mobile'
});
useEffect(() => {
const updateLayout = () => {
const width = window.innerWidth;
if (width < 576) {
// Small mobile
setConfig({
type: 'Over',
width: '85vw',
breakpoint: 'xs'
});
} else if (width < 768) {
// Large mobile
setConfig({
type: 'Over',
width: '75vw',
breakpoint: 'sm'
});
} else if (width < 992) {
// Tablet
setConfig({
type: 'Push',
width: '280px',
breakpoint: 'md'
});
} else if (width < 1200) {
// Small desktop
setConfig({
type: 'Push',
width: '300px',
breakpoint: 'lg'
});
} else {
// Large desktop
setConfig({
type: 'Push',
width: '320px',
breakpoint: 'xl'
});
}
};
updateLayout();
window.addEventListener('resize', updateLayout);
return () => window.removeEventListener('resize', updateLayout);
}, []);
return (
<SidebarComponent
type={config.type}
width={config.width}
>
Responsive: {config.breakpoint}
</SidebarComponent>
);
}
export default ResponsiveSidebar;Responsive CSS Media Queries
/* Extra small (< 576px) */
@media (max-width: 575px) {
.e-sidebar {
width: 85vw !important;
}
.sidebar-header h3 {
font-size: 18px;
}
}
/* Small (576px - 768px) */
@media (min-width: 576px) and (max-width: 767px) {
.e-sidebar {
width: 75vw !important;
}
}
/* Medium (768px - 992px) */
@media (min-width: 768px) and (max-width: 991px) {
.e-sidebar {
width: 280px !important;
}
.sidebar-header h3 {
font-size: 20px;
}
}
/* Large (992px - 1200px) */
@media (min-width: 992px) and (max-width: 1199px) {
.e-sidebar {
width: 300px !important;
}
}
/* Extra large (>= 1200px) */
@media (min-width: 1200px) {
.e-sidebar {
width: 320px !important;
}
.sidebar-content {
padding: 25px;
}
}---
RTL Support
Enable RTL Mode
<SidebarComponent
enableRtl={true}
position="Right"
type="Push"
>
محتوى الشريط الجانبي
</SidebarComponent>RTL CSS Adjustments
/* RTL specific styles */
body[dir="rtl"] .e-sidebar {
border-right: none;
border-left: 1px solid #ddd;
}
body[dir="rtl"] .e-sidebar h3 {
text-align: right;
}
body[dir="rtl"] .e-sidebar ul li a {
text-align: right;
padding-right: 20px;
padding-left: 0;
}
body[dir="rtl"] .e-sidebar ul li a:hover {
padding-right: 25px;
padding-left: 0;
}
body[dir="rtl"] .sidebar-content {
direction: rtl;
}Complete RTL Example
import React, { useState } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
function RTLSidebar() {
const [isRTL, setIsRTL] = useState(false);
React.useEffect(() => {
if (isRTL) {
document.documentElement.dir = 'rtl';
document.documentElement.lang = 'ar';
} else {
document.documentElement.dir = ltr';
document.documentElement.lang = 'en';
}
}, [isRTL]);
return (
<div>
<button onClick={() => setIsRTL(!isRTL)}>
{isRTL ? 'Switch to LTR' : 'Switch to RTL'}
</button>
<SidebarComponent
enableRtl={isRTL}
position={isRTL ? 'Right' : 'Left'}
type="Push"
width="280px"
>
<h3>{isRTL ? 'المحتوى' : 'Content'}</h3>
<ul>
<li><a href="#home">{isRTL ? 'الرئيسية' : 'Home'}</a></li>
<li><a href="#about">{isRTL ? 'حول' : 'About'}</a></li>
<li><a href="#contact">{isRTL ? 'اتصل' : 'Contact'}</a></li>
</ul>
</SidebarComponent>
</div>
);
}
export default RTLSidebar;---
Custom Animations
Slide In from Top
@keyframes slideFromTop {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.slide-top.e-sidebar.e-open {
animation: slideFromTop 0.4s ease-out;
}Fade and Zoom
@keyframes fadeZoom {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
.fade-zoom.e-sidebar.e-open {
animation: fadeZoom 0.3s ease-out;
}Rotate Entrance
@keyframes rotateEnter {
from {
transform: rotateY(90deg);
opacity: 0;
}
to {
transform: rotateY(0);
opacity: 1;
}
}
.rotate-enter.e-sidebar.e-open {
animation: rotateEnter 0.5s ease-out;
perspective: 1000px;
}Custom Animation Implementation
import React, { useRef } from 'react';
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
import './CustomAnimations.css';
function AnimatedSidebarDemo() {
const sidebarRef = useRef(null);
const [animation, setAnimation] = React.useState('slide-left');
const animations = [
'slide-left',
'fade-slide',
'fade-zoom',
'rotate-enter',
'bounce-in'
];
return (
<div>
<div className="animation-selector">
{animations.map(anim => (
<button
key={anim}
onClick={() => setAnimation(anim)}
className={animation === anim ? 'active' : ''}
>
{anim}
</button>
))}
</div>
<SidebarComponent
ref={sidebarRef}
type="Over"
width="280px"
cssClass={animation}
animate={true}
>
Animated Sidebar
</SidebarComponent>
</div>
);
}
export default AnimatedSidebarDemo;CustomAnimations.css
/* Bounce In */
@keyframes bounceIn {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1.05); }
100% { transform: scale(1); opacity: 1; }
}
.bounce-in.e-sidebar.e-open {
animation: bounceIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* Fade and Slide */
@keyframes fadeSlide {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.fade-slide.e-sidebar.e-open {
animation: fadeSlide 0.4s ease-out;
}---