Overview
Side panel is a fixed sidebar component for displaying supplementary information, navigation, or related content. Unlike Drawer, it’s not an overlay but a persistent layout element.
Basic usage
import { SidePanel } from '@raystack/apsara';
<SidePanel>
<SidePanel.Header
title="Panel title"
description="Optional description"
/>
<SidePanel.Section>
Panel content goes here.
</SidePanel.Section>
</SidePanel>
Components
SidePanel (Root)
The root container component that creates a fixed sidebar.
side
'left' | 'right'
default:"'right'"
The side of the screen where the panel is positioned.
Additional CSS classes for the panel container.
A header component for displaying the panel title, icon, and action buttons.
The main title text displayed in the header.
Optional description text displayed below the title.
An icon element displayed before the title.
An array of action buttons or elements displayed on the right side of the header.
SidePanel.Section
A content section container within the panel.
The content to display within the section.
Usage examples
Basic side panel
<SidePanel>
<SidePanel.Header title="Details" />
<SidePanel.Section>
<p>This is the panel content.</p>
</SidePanel.Section>
</SidePanel>
Panel on left side
<SidePanel side="left">
<SidePanel.Header title="Navigation" />
<SidePanel.Section>
<nav>
<a href="/home">Home</a>
<a href="/about">About</a>
</nav>
</SidePanel.Section>
</SidePanel>
With icon and description
import { InfoCircledIcon } from '@radix-ui/react-icons';
<SidePanel>
<SidePanel.Header
title="Information"
description="Additional details about this item"
icon={<InfoCircledIcon />}
/>
<SidePanel.Section>
Content goes here.
</SidePanel.Section>
</SidePanel>
With action buttons
import { Cross2Icon, Pencil1Icon } from '@radix-ui/react-icons';
import { IconButton } from '@raystack/apsara';
<SidePanel>
<SidePanel.Header
title="Edit mode"
actions={[
<IconButton key="edit" aria-label="Edit">
<Pencil1Icon />
</IconButton>,
<IconButton key="close" aria-label="Close">
<Cross2Icon />
</IconButton>
]}
/>
<SidePanel.Section>
Panel content with header actions.
</SidePanel.Section>
</SidePanel>
Multiple sections
<SidePanel>
<SidePanel.Header title="Multi-section panel" />
<SidePanel.Section>
<h3>Section 1</h3>
<p>First section content.</p>
</SidePanel.Section>
<SidePanel.Section>
<h3>Section 2</h3>
<p>Second section content.</p>
</SidePanel.Section>
<SidePanel.Section>
<h3>Section 3</h3>
<p>Third section content.</p>
</SidePanel.Section>
</SidePanel>
Full layout example
function PageWithSidePanel() {
return (
<div style={{ display: 'flex' }}>
<main style={{ flex: 1 }}>
<h1>Main content</h1>
<p>Your main page content goes here.</p>
</main>
<SidePanel side="right">
<SidePanel.Header
title="Related info"
description="Supplementary information"
/>
<SidePanel.Section>
<h3>Quick links</h3>
<ul>
<li><a href="/link1">Link 1</a></li>
<li><a href="/link2">Link 2</a></li>
</ul>
</SidePanel.Section>
<SidePanel.Section>
<h3>Statistics</h3>
<p>Some statistics here.</p>
</SidePanel.Section>
</SidePanel>
</div>
);
}
Custom styling
<SidePanel className="custom-panel-styles">
<SidePanel.Header title="Custom styled panel" />
<SidePanel.Section>
Content with custom styles.
</SidePanel.Section>
</SidePanel>
Layout considerations
Side panel is designed as a persistent layout element:
- Not an overlay: Unlike Drawer, it doesn’t float over content
- Fixed position: Stays in place as a part of the page layout
- Flex layout: Works well in flexbox or grid layouts
- Scrollable: The panel content can scroll independently
Typical layout pattern:
<div style={{ display: 'flex', height: '100vh' }}>
<main style={{ flex: 1, overflow: 'auto' }}>
{/* Main content */}
</main>
<SidePanel side="right">
{/* Panel content */}
</SidePanel>
</div>
Comparison with Drawer
| Feature | SidePanel | Drawer |
|---|
| Type | Fixed layout element | Overlay modal |
| Dismissible | No | Yes |
| Backdrop | No | Yes |
| Swipe gesture | No | Yes |
| Use case | Persistent sidebar | Temporary panel |
Use SidePanel when:
- Content should always be visible
- You need a persistent sidebar layout
- Information supplements the main content
Use Drawer when:
- Content should be temporarily displayed
- User needs to focus on main content
- Space is limited on smaller screens
Accessibility features
- Semantic HTML: Uses
<aside> element for proper semantics
- Keyboard navigation: Works with standard keyboard navigation patterns
- Action buttons: Properly labeled with
aria-label attributes
- Header structure: Clear hierarchy with title and description
Responsive considerations
For responsive layouts, consider conditionally rendering SidePanel on larger screens and Drawer on smaller screens:
function ResponsivePanel() {
const isDesktop = useMediaQuery('(min-width: 1024px)');
const content = (
<>
<Header title="Content" />
<Section>Panel content</Section>
</>
);
if (isDesktop) {
return (
<SidePanel>
{content}
</SidePanel>
);
}
return (
<Drawer>
<Drawer.Trigger>Open panel</Drawer.Trigger>
<Drawer.Content>
{content}
</Drawer.Content>
</Drawer>
);
}