Sidebar Component
August 16, 2025 ยท View on GitHub
The Sidebar component is a powerful, flexible navigation component built with Angular signals for optimal performance. It provides responsive behavior, keyboard navigation, multiple display modes, sticky header/footer, and extensive customization options.
Table of Contents
- Features
- Basic Usage
- Installation
- Component Architecture
- API Reference
- Advanced Examples
- Keyboard Navigation
- Responsive Behavior
- Customization
- Accessibility
- Best Practices
- Troubleshooting
Features
- ๐ Signal-based: Built with Angular signals for optimal performance
- โจ๏ธ Full keyboard navigation: Arrow keys, Enter, Space, Home, End support
- ๐ฑ Responsive design: Automatically adapts to different screen sizes with mobile overlay mode
- ๐ฏ Target-based triggers: Control sidebars by ID without ViewChild references
- ๐ Multiple modes: Push (content shifts) and overlay (content covered) display modes
- ๐ Flexible sizing: 5 different width sizes (sm, md, lg, xl, icon)
- ๐จ Icon mode: Compact icon-only mode with tooltips and dropdowns
- ๐ณ Nested navigation: Multi-level navigation with expandable groups
- ๐ Sticky layout: Header and footer stick to top/bottom with scrollable content
- ๐ญ Flexible positioning: Left or right sidebar positioning with flexbox layout
- โฟ Accessibility: Full ARIA support and screen reader friendly
- ๐ง Service integration: SidebarService for programmatic control across components
Basic Usage
Simple Sidebar Structure
The sidebar follows a specific hierarchy where users provide their own main content element:
import { Component } from '@angular/core';
import {
Sidebar,
SidebarContainer,
SidebarContent,
SidebarHeader,
SidebarFooter,
SidebarNavGroup,
SidebarNavItem,
SidebarTrigger
} from '@lib/sidebar';
@Component({
selector: 'app-example',
standalone: true,
imports: [
Sidebar,
SidebarContainer,
SidebarContent,
SidebarHeader,
SidebarFooter,
SidebarNavGroup,
SidebarNavItem,
SidebarTrigger
],
template: `
<!-- Trigger button (optional - can be anywhere) -->
<SidebarTrigger target="my-sidebar" [showLabel]="true" label="Toggle Sidebar" />
<!-- Main sidebar container -->
<SidebarContainer>
<!-- Sidebar component -->
<Sidebar
id="my-sidebar"
side="left"
mode="push"
size="md"
[defaultExpanded]="true"
ariaLabel="Main navigation"
>
<!-- Sticky header -->
<SidebarHeader slot="sidebar-header">
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-blue-600 rounded-lg"></div>
<h2 class="text-lg font-semibold">My App</h2>
</div>
</SidebarHeader>
<!-- Scrollable content -->
<SidebarContent slot="sidebar-content">
<SidebarNavGroup title="Main Navigation">
<SidebarNavItem
routerLink="/dashboard"
label="Dashboard"
icon="<svg>...</svg>"
/>
<SidebarNavItem
routerLink="/users"
label="Users"
icon="<svg>...</svg>"
badge="12"
/>
<SidebarNavItem
[hasChildren]="true"
label="Analytics"
icon="<svg>...</svg>"
>
<SidebarNavItem
[isSubmenuItem]="true"
routerLink="/analytics/reports"
label="Reports"
/>
<SidebarNavItem
[isSubmenuItem]="true"
routerLink="/analytics/insights"
label="Insights"
/>
</SidebarNavItem>
</SidebarNavGroup>
</SidebarContent>
<!-- Sticky footer -->
<SidebarFooter slot="sidebar-footer">
<div class="text-sm text-muted-foreground">
v2.0.3 โข ยฉ 2025 SuperUI
</div>
</SidebarFooter>
</Sidebar>
<!-- User's main content - use any HTML element -->
<div class="flex-1 overflow-auto">
<main class="p-6">
<h1>Main Content Area</h1>
<p>Your application content goes here...</p>
</main>
</div>
</SidebarContainer>
`
})
export class ExampleComponent {}
Installation
- Install the package (if using npm package):
npx ngsui-cli add sidebar
- Import the components in your module or standalone component:
import {
Sidebar,
SidebarContainer,
SidebarContent,
SidebarHeader,
SidebarFooter,
SidebarNavGroup,
SidebarNavItem,
SidebarTrigger,
SidebarService // For programmatic control
} from '@lib/sidebar';
- Add required styles (usually automatically included with the component).
Component Architecture
The sidebar follows a hierarchical structure:
SidebarContainer (flexbox container)
โโโ Sidebar (main sidebar component)
โ โโโ SidebarHeader (sticky header)
โ โโโ SidebarContent (scrollable content)
โ โ โโโ SidebarNavGroup
โ โ โโโ SidebarNavItem (can be nested)
โ โโโ SidebarFooter (sticky footer)
โโโ div/main/section (user's main content with flex-1 class)
Key Points:
- SidebarContainer: Manages flexbox layout and positioning
- Sidebar: Contains all navigation with sticky header/footer
- User Content: Any HTML element with
flex-1class takes remaining space - No SidebarMainContent: Users write their own main content structure
API Reference
SidebarContainer
The root container component that manages flexbox layout and provides context to child components.
SidebarContainer Properties
| Property | Type | Default | Description |
|---|---|---|---|
customClass | string | '' | Additional CSS classes for the container |
height | string | 'h-screen' | Height class for the container |
SidebarContainer Usage
<SidebarContainer>
<Sidebar>...</Sidebar>
<div class="flex-1 overflow-auto">...</div>
</SidebarContainer>
Sidebar
The main sidebar component that contains navigation and controls display behavior.
Sidebar Properties
| Property | Type | Default | Description |
|---|---|---|---|
id | string | '' | Unique identifier for the sidebar (used by triggers) |
side | 'left' | 'right' | 'left' | Which side of the screen to display the sidebar |
mode | 'push' | 'overlay' | 'push' | How the sidebar affects the main content |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Width of the sidebar |
defaultExpanded | boolean | true | Default expanded state on initialization |
isExpanded | boolean | undefined | undefined | External control of expanded state |
allowCollapse | boolean | true | Whether the sidebar can be collapsed |
allowIconOnly | boolean | true | Whether the sidebar can use icon-only mode |
showBackdropInOverlay | boolean | true | Whether to show backdrop in overlay mode |
closeOnBackdropClick | boolean | true | Whether to close sidebar when backdrop is clicked |
closeOnEscape | boolean | true | Whether to close sidebar when Escape is pressed |
preventBodyScroll | boolean | true | Whether to prevent body scroll in overlay mode |
mobileBreakpoint | number | 768 | Pixel width for mobile breakpoint |
mediumBreakpoint | number | 1024 | Pixel width for medium screen breakpoint |
ariaLabel | string | 'Navigation sidebar' | Accessibility label for the sidebar |
customClass | string | '' | Additional CSS classes for the sidebar |
headerCustomClass | string | '' | Additional CSS classes for the header area |
contentCustomClass | string | '' | Additional CSS classes for the content area |
footerCustomClass | string | '' | Additional CSS classes for the footer area |
Sidebar Events
| Event | Type | Description |
|---|---|---|
onExpandedChange | EventEmitter<boolean> | Emitted when expanded state changes |
onStateChange | EventEmitter<SidebarState> | Emitted when sidebar state changes |
Sidebar Methods
| Method | Description |
|---|---|
expand() | Expand the sidebar and exit icon mode |
collapse() | Collapse the sidebar |
toggleExpanded() | Toggle between expanded and collapsed states |
setIconOnly() | Set the sidebar to icon-only mode |
toggleIconOnly() | Toggle between icon-only and expanded modes |
Sidebar Computed Properties
| Property | Type | Description |
|---|---|---|
isExpandedComputed() | boolean | Current expanded state (respects external control) |
isIconOnly() | boolean | Whether sidebar is in icon-only mode |
isMobile() | boolean | Whether current screen is mobile size |
isMediumScreen() | boolean | Whether current screen is medium size |
effectiveMode() | 'push' | 'overlay' | Actual mode (forces overlay on mobile) |
currentState() | 'collapsed' | 'expanded' | 'iconOnly' | Current visual state |
currentSize() | 'sm' | 'md' | 'lg' | 'xl' | 'icon' | Current size (icon when in icon mode) |
Sidebar Slots
The sidebar uses Angular's content projection with slots:
sidebar-header: Content for the sticky header areasidebar-content: Main scrollable content areasidebar-footer: Content for the sticky footer area
Sidebar Size Options
| Size | Width | Description |
|---|---|---|
sm | 256px (16rem) | Compact sidebar for minimal interfaces |
md | 320px (20rem) | Standard width for most applications (default) |
lg | 384px (24rem) | Larger sidebar for content-heavy navigation |
xl | 448px (28rem) | Maximum width for complex navigation structures |
icon | 64px (4rem) | Icon-only mode for minimal space usage |
SidebarHeader
Container for sidebar header content with sticky positioning.
SidebarHeader Properties
| Property | Type | Default | Description |
|---|---|---|---|
customClass | string | '' | Additional CSS classes |
SidebarContent
Scrollable content area of the sidebar.
SidebarContent Properties
| Property | Type | Default | Description |
|---|---|---|---|
customClass | string | '' | Additional CSS classes |
isIconOnly | boolean | false | Whether in icon-only mode (affects styling) |
SidebarFooter
Container for sidebar footer content with sticky positioning.
SidebarFooter Properties
| Property | Type | Default | Description |
|---|---|---|---|
customClass | string | '' | Additional CSS classes |
SidebarNavGroup
Groups related navigation items with an optional title.
SidebarNavGroup Properties
| Property | Type | Default | Description |
|---|---|---|---|
title | string | '' | Optional group title |
isIconOnly | boolean | false | Whether in icon-only mode (hides title) |
customClass | string | '' | Additional CSS classes |
titleCustomClass | string | '' | Additional CSS classes for the title |
SidebarNavItem
Individual navigation item with support for icons, badges, and nesting.
SidebarNavItem Properties
| Property | Type | Default | Description |
|---|---|---|---|
routerLink | string | any[] | null | null | Angular router link |
label | string | '' | Display text for the item |
icon | string | Type<any> | TemplateRef<any> | LucideIconData | '' | Universal icon support: SVG markup, Angular component, template, or Lucide icon data |
badge | string | '' | Badge text or number |
isActive | boolean | false | Whether the item is currently active |
hasChildren | boolean | false | Whether this item has submenu items |
isIconOnly | boolean | false | Whether in icon-only mode |
isSubmenuItem | boolean | false | Whether this is a submenu item |
customClass | string | '' | Additional CSS classes |
badgeCustomClass | string | '' | Additional CSS classes for the badge |
SidebarNavItem Events
| Event | Type | Description |
|---|---|---|
onClick | EventEmitter<Event> | Emitted when item is clicked |
SidebarNavItem Computed Properties
| Property | Type | Description |
|---|---|---|
isExpanded() | boolean | Whether submenu is expanded |
isHovered() | boolean | Whether item is being hovered (for tooltips) |
showLabel() | boolean | Whether to show the label text |
showTooltip() | boolean | Whether to show tooltip in icon mode |
SidebarNavItem Methods
| Method | Description |
|---|---|
onItemClick(event: Event) | Handle item click (toggles submenu if has children) |
onKeyDown(event: KeyboardEvent) | Handle keyboard navigation |
onMouseEnter() | Handle mouse enter for tooltip |
onMouseLeave() | Handle mouse leave for tooltip |
getAriaLabel() | Get accessible label for screen readers |
SidebarTrigger
Button component to toggle sidebar visibility.
SidebarTrigger Properties
| Property | Type | Default | Description |
|---|---|---|---|
target | string | '' | ID of the sidebar to control |
label | string | '' | Button label text |
showIcon | boolean | true | Whether to show the hamburger icon |
showLabel | boolean | false | Whether to show text label |
isExpanded | boolean | false | Fallback expanded state if no target |
variant | 'default' | 'outline' | 'ghost' | 'outline' | Button style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
customClass | string | '' | Additional CSS classes |
SidebarTrigger Events
| Event | Type | Description |
|---|---|---|
onTrigger | EventEmitter<void> | Emitted when trigger is activated |
SidebarTrigger Methods
| Method | Description |
|---|---|
onTriggerClick() | Handle trigger button click |
getTargetExpandedState() | Get expanded state from target sidebar |
getAriaLabel() | Get accessible label for the button |
SidebarService
Injectable service for programmatic sidebar control.
SidebarService Methods
| Method | Parameters | Return Type | Description |
|---|---|---|---|
registerSidebar(id, sidebar) | id: string, sidebar: Sidebar | void | Register a sidebar instance |
unregisterSidebar(id) | id: string | void | Unregister a sidebar instance |
getSidebar(id) | id: string | Sidebar | undefined | Get sidebar instance by ID |
toggleSidebar(id) | id: string | boolean | Toggle sidebar by ID |
getAllSidebars() | - | Sidebar[] | Get all registered sidebar instances |
SidebarService Usage
import { Component, inject } from '@angular/core';
import { SidebarService } from '@lib/sidebar';
@Component({
template: `
<button (click)="toggleSidebar()">Toggle Sidebar</button>
`
})
export class MyComponent {
private sidebarService = inject(SidebarService);
toggleSidebar() {
this.sidebarService.toggle('my-sidebar');
}
}
Migration Note
SidebarMainContent has been removed in the current implementation for greater flexibility. Users should provide their own main content element with the flex-1 overflow-auto CSS classes.
Before (old implementation)
<SidebarContainer>
<Sidebar>...</Sidebar>
<SidebarMainContent>
<!-- Your content here -->
</SidebarMainContent>
</SidebarContainer>
After (current implementation)
<SidebarContainer>
<Sidebar>...</Sidebar>
<div class="flex-1 overflow-auto">
<!-- Your content here -->
</div>
</SidebarContainer>
Advanced Examples
Nested Navigation
<SidebarNavGroup title="Analytics">
<SidebarNavItem
label="Reports"
icon="<svg>...</svg>"
[hasChildren]="true"
>
<!-- Level 2 -->
<SidebarNavItem
routerLink="/reports/sales"
label="Sales Reports"
[isSubmenuItem]="true"
[customClass]="isIconOnly ? '' : 'ml-4'"
/>
<SidebarNavItem
label="User Reports"
[hasChildren]="true"
[isSubmenuItem]="true"
[customClass]="isIconOnly ? '' : 'ml-4'"
>
<!-- Level 3 -->
<SidebarNavItem
routerLink="/reports/users/active"
label="Active Users"
[isSubmenuItem]="true"
[customClass]="isIconOnly ? '' : 'ml-8'"
/>
</SidebarNavItem>
</SidebarNavItem>
</SidebarNavGroup>
Responsive Sidebar
@Component({
template: `
<SidebarContainer>
<Sidebar
id="responsive-sidebar"
[side]="sidebarSide()"
[mode]="sidebarMode()"
[size]="sidebarSize()"
[defaultExpanded]="!isMobile()"
>
<!-- Sidebar content -->
</Sidebar>
<div class="flex-1">
<!-- Main content -->
</div>
</SidebarContainer>
`
})
export class ResponsiveExample {
// Responsive behavior
readonly isMobile = computed(() => window.innerWidth <= 768);
readonly sidebarMode = computed(() => this.isMobile() ? 'overlay' : 'push');
readonly sidebarSide = computed(() => 'left');
readonly sidebarSize = computed(() => this.isMobile() ? 'sm' : 'md');
}
Custom Styling
<Sidebar
id="custom-sidebar"
[customClass]="'bg-gradient-to-b from-blue-900 to-purple-900 text-white'"
[headerCustomClass]="'bg-blue-800 border-b border-blue-700'"
>
<SidebarHeader slot="sidebar-header">
<div class="text-white font-bold">Custom Sidebar</div>
</SidebarHeader>
<SidebarContent slot="sidebar-content">
<SidebarNavGroup
title="Navigation"
[titleCustomClass]="'text-blue-200'"
>
<SidebarNavItem
label="Dashboard"
[customClass]="'text-white hover:bg-blue-800'"
[badgeCustomClass]="'bg-yellow-500 text-yellow-900'"
badge="3"
/>
</SidebarNavGroup>
</SidebarContent>
</Sidebar>
Icon Mode with Tooltips
@Component({
template: `
<Sidebar
id="icon-sidebar"
#sidebar
[defaultExpanded]="false"
>
<SidebarContent slot="sidebar-content" [isIconOnly]="sidebar.isIconOnly()">
<SidebarNavGroup [isIconOnly]="sidebar.isIconOnly()">
<SidebarNavItem
routerLink="/dashboard"
label="Dashboard"
icon="<svg>...</svg>"
[isIconOnly]="sidebar.isIconOnly()"
/>
<!-- In icon mode, tooltips automatically appear on hover -->
</SidebarNavGroup>
</SidebarContent>
</Sidebar>
`
})
export class IconModeExample {}
Multiple Sidebars
<SidebarContainer>
<!-- Left sidebar -->
<Sidebar
id="left-sidebar"
side="left"
mode="push"
ariaLabel="Main navigation"
>
<!-- Navigation content -->
</Sidebar>
<!-- Main content -->
<div class="flex-1">
<main>Content</main>
</div>
<!-- Right sidebar -->
<Sidebar
id="right-sidebar"
side="right"
mode="overlay"
ariaLabel="Tools and settings"
>
<!-- Tools content -->
</Sidebar>
</SidebarContainer>
<!-- Triggers -->
<SidebarTrigger target="left-sidebar" label="Menu" />
<SidebarTrigger target="right-sidebar" label="Tools" />
Keyboard Navigation
The sidebar provides comprehensive keyboard navigation support:
Navigation Keys
| Key | Action |
|---|---|
โ / โ | Navigate between menu items |
โ / โ | Collapse/expand submenus |
Enter / Space | Activate item or toggle submenu |
Home | Jump to first item |
End | Jump to last item |
Tab | Navigate between sidebar groups |
Escape | Close sidebar (when in overlay mode) |
Focus Management
- Focus is automatically managed when navigating with arrow keys
- When a submenu is expanded, focus moves to the first submenu item
- Focus is trapped within the sidebar when using overlay mode
- Proper focus indicators are provided for keyboard users
Example: Programmatic Focus
@Component({
template: `
<Sidebar #sidebar id="my-sidebar">
<SidebarContent slot="sidebar-content">
<SidebarNavItem
#firstItem
routerLink="/dashboard"
label="Dashboard"
/>
</SidebarContent>
</Sidebar>
`
})
export class FocusExample {
@ViewChild('firstItem') firstItem!: SidebarNavItem;
focusFirstItem() {
// Focus first item programmatically
this.firstItem.focus();
}
}
Responsive Behavior
Automatic Responsive Mode
The sidebar automatically adapts to different screen sizes:
- Desktop (>1024px): Push mode by default, full size
- Tablet (768-1024px): Push mode, potentially smaller size
- Mobile (<768px): Overlay mode, compact size
Manual Responsive Control
@Component({
template: `
<Sidebar
[mode]="responsiveMode()"
[size]="responsiveSize()"
[defaultExpanded]="!isMobileDevice()"
>
<!-- Content -->
</Sidebar>
`
})
export class ResponsiveControl {
private readonly breakpoint = inject(BreakpointObserver);
readonly isMobileDevice = computed(() =>
this.breakpoint.isMatched('(max-width: 768px)')
);
readonly responsiveMode = computed(() =>
this.isMobileDevice() ? 'overlay' : 'push'
);
readonly responsiveSize = computed(() =>
this.isMobileDevice() ? 'sm' : 'md'
);
}
Responsive Navigation Items
<!-- Show different content based on screen size -->
<SidebarNavItem
[label]="isMobile() ? 'Dash' : 'Dashboard'"
[icon]="dashboardIcon"
routerLink="/dashboard"
/>
<!-- Hide items on mobile -->
<SidebarNavItem
*ngIf="!isMobile()"
label="Advanced Settings"
routerLink="/settings/advanced"
/>
Accessibility
The sidebar component is built with accessibility in mind:
ARIA Support
- Proper ARIA roles (
navigation,menu,menuitem) - ARIA labels and descriptions
- ARIA expanded state for submenus
- ARIA current for active items
Screen Reader Support
- Descriptive labels for all interactive elements
- Status announcements for state changes
- Proper heading hierarchy
- Alternative text for icons
Example: Enhanced Accessibility
<Sidebar
id="accessible-sidebar"
ariaLabel="Main navigation menu"
role="navigation"
>
<SidebarContent slot="sidebar-content">
<SidebarNavGroup
title="Primary Navigation"
role="group"
[attr.aria-labelledby]="groupId"
>
<SidebarNavItem
routerLink="/dashboard"
label="Dashboard"
[attr.aria-current]="isCurrentPage('/dashboard') ? 'page' : null"
[attr.aria-describedby]="'dashboard-desc'"
/>
<div id="dashboard-desc" class="sr-only">
Main dashboard with overview of all metrics
</div>
</SidebarNavGroup>
</SidebarContent>
</Sidebar>
Best Practices
Performance
- Use OnPush Change Detection:
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
// ...
})
- Lazy Load Navigation Data:
readonly navigationItems = computed(() => {
return this.authService.user()?.role === 'admin'
? this.adminNavItems()
: this.userNavItems();
});
- Optimize Icon Rendering:
// Pre-sanitize icons for better performance
readonly sanitizedIcon = computed(() =>
this.sanitizer.bypassSecurityTrustHtml(this.icon())
);
UX Guidelines
- Consistent Navigation: Keep navigation structure consistent across your application
- Clear Labels: Use descriptive labels that clearly indicate the destination
- Visual Hierarchy: Use grouping and indentation to show relationships
- State Indicators: Show active states and loading indicators appropriately
Code Organization
- Separate Navigation Logic:
@Injectable()
export class NavigationService {
getNavigationItems(userRole: string) {
// Return navigation items based on user role
}
}
- Use TypeScript Interfaces:
interface NavigationItem {
label: string;
route: string;
icon: string;
badge?: string;
children?: NavigationItem[];
}
- Component Composition:
@Component({
template: `
<SidebarNavGroup title="Analytics">
<app-analytics-nav-items />
</SidebarNavGroup>
`
})
export class AnalyticsNavComponent {}
Troubleshooting
Common Issues
Sidebar Not Responding to Trigger
Problem: Sidebar trigger button doesn't open/close the sidebar.
Solution: Ensure the trigger target matches the sidebar id:
<SidebarTrigger target="my-sidebar" />
<Sidebar id="my-sidebar"> <!-- Must match -->
SidebarMainContent Not Found Error
Problem: Error about SidebarMainContent component not being found.
Solution: SidebarMainContent has been removed. Replace it with your own element:
<!-- OLD - Will cause errors -->
<SidebarContainer>
<Sidebar>...</Sidebar>
<SidebarMainContent>Content</SidebarMainContent>
</SidebarContainer>
<!-- NEW - Use regular HTML elements -->
<SidebarContainer>
<Sidebar>...</Sidebar>
<div class="flex-1 overflow-auto">
<main class="p-6">Content</main>
</div>
</SidebarContainer>
Main Content Not Taking Full Width
Problem: Content area doesn't expand to fill remaining space.
Solution: Ensure your main content element has flex-1 class:
<SidebarContainer>
<Sidebar>...</Sidebar>
<div class="flex-1 overflow-auto"> <!-- Required classes -->
<!-- Your content -->
</div>
</SidebarContainer>
Sidebar Positioning Issues
Problem: Sidebar appears in wrong position or overlaps content.
Solution: Verify proper component structure and CSS classes:
<!-- Correct structure -->
<SidebarContainer> <!-- Manages flexbox layout -->
<Sidebar side="left">...</Sidebar> <!-- Positioned first for left -->
<div class="flex-1 overflow-auto">...</div> <!-- Takes remaining space -->
</SidebarContainer>
<!-- For right sidebar -->
<SidebarContainer>
<div class="flex-1 overflow-auto">...</div> <!-- Content first -->
<Sidebar side="right">...</Sidebar> <!-- Sidebar second for right -->
</SidebarContainer>
Icons Not Displaying
Problem: SVG icons don't appear in navigation items.
Solution: Ensure SVG strings are properly formatted:
readonly dashboardIcon = `
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/>
</svg>
`;
Header/Footer Not Sticky
Problem: Header and footer scroll with content instead of staying fixed.
Solution: Ensure proper slot usage and CSS structure:
<Sidebar>
<SidebarHeader slot="sidebar-header">...</SidebarHeader>
<SidebarContent slot="sidebar-content">...</SidebarContent>
<SidebarFooter slot="sidebar-footer">...</SidebarFooter>
</Sidebar>
Keyboard Navigation Not Working
Problem: Arrow keys don't navigate between items.
Solution: Ensure items have proper tabindex and role attributes:
<SidebarNavItem
role="menuitem"
tabindex="0"
label="Dashboard"
/>
Submenu Not Expanding
Problem: Nested items don't show when parent is clicked.
Solution: Set hasChildren to true and use proper nesting:
<SidebarNavItem
[hasChildren]="true"
label="Analytics"
>
<SidebarNavItem
[isSubmenuItem]="true"
label="Reports"
/>
</SidebarNavItem>
Responsive Issues
Problem: Sidebar doesn't adapt to mobile screens.
Solution: Use responsive mode and size:
<Sidebar
[mode]="isMobile() ? 'overlay' : 'push'"
[size]="isMobile() ? 'sm' : 'md'"
[breakpoint]="'md'"
/>
Migration from Previous Versions
If upgrading from an older version:
- Remove SidebarMainContent imports:
// Remove this import
import { SidebarMainContent } from '@lib/sidebar';
// Keep these imports
import {
Sidebar,
SidebarContainer,
SidebarContent,
// ... other components
} from '@lib/sidebar';
- Update template structure:
<!-- Replace SidebarMainContent with regular elements -->
<div class="flex-1 overflow-auto">
<!-- Your content here -->
</div>
- Update CSS classes:
- Replace
customClasswithclassName - Ensure flexbox layout with
flex-1on main content
Debugging Tips
- Check Console Errors: Look for any JavaScript errors that might prevent functionality
- Inspect Element: Use browser dev tools to verify proper HTML structure and CSS classes
- Test Keyboard Navigation: Use Tab and arrow keys to test navigation flow
- Verify ARIA Attributes: Check that accessibility attributes are properly set
- Check Component Structure: Ensure proper nesting of sidebar components
- Validate CSS Classes: Confirm flexbox classes are applied correctly
Performance Issues
If you experience performance issues:
- Minimize Re-renders: Use
OnPushchange detection - Optimize Icons: Pre-process SVG icons instead of generating them dynamically
- Lazy Load: Load navigation items only when needed
- Use TrackBy: For dynamic navigation lists, use trackBy functions
- Signal Optimization: Use computed signals for derived state
Development Environment Issues
- Hot Reload: Changes might require a full page refresh
- Build Errors: Ensure all imports are correctly updated after migration
- TypeScript Errors: Check component property names match current API
Contributing
If you find any issues or have suggestions for improvements, please:
- Check existing issues on GitHub
- Create a new issue with detailed description
- Consider submitting a pull request
License
This component is part of the Angular SuperUI library and follows the same license terms.