Side Navigation Block
The SideNavigation Component is a fully customizable and accessible side navigation menu built with React and TypeScript. It provides a complete navigation interface with modern design patterns, mobile-responsive behavior, floating and fixed modes, and flexible customization options.
π Installationβ
npm install @nodeblocks/frontend-side-navigation-block@0.3.0
π Usageβ
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
- Basic Usage
- Advanced Usage
function SimpleSideNavigation() { const links = [ {icon: DashboardIcon, text: 'Dashboard', href: '/dashboard'}, {icon: InventoryIcon, text: 'Products', href: '/products'}, {icon: ShoppingCartIcon, text: 'Orders', href: '/orders'}, {icon: PeopleIcon, text: 'Customers', href: '/customers'}, {icon: AnalyticsIcon, text: 'Analytics', href: '/analytics'}, {icon: SettingsIcon, text: 'Settings', href: '/settings'}, ]; const header = { icon: HomeIcon, text: 'My App', href: '/', }; return ( <SideNavigation header={header} links={links} /> ); }
function AdvancedSideNavigation() { const [isMenuOpen, setIsMenuOpen] = useState(false); const links = [ {icon: DashboardIcon, text: 'Dashboard', href: '/dashboard'}, {icon: InventoryIcon, text: 'Products', href: '/products'}, {icon: ShoppingCartIcon, text: 'Orders', href: '/orders'}, {icon: PeopleIcon, text: 'Customers', href: '/customers'}, {icon: AnalyticsIcon, text: 'Analytics', href: '/analytics'}, {icon: SettingsIcon, text: 'Settings', href: '/settings'}, ]; const header = { icon: HomeIcon, text: 'Acme Inc', href: '/', }; return ( <SideNavigation header={header} links={links} isFloating={true} isMenuOpen={isMenuOpen} setIsMenuOpen={setIsMenuOpen} sx={{ position: 'relative', minHeight: 400, }} > {({defaultBlocks, defaultBlockOrder}) => { const customMenuButton = ( <div style={{ position: 'fixed', top: '16px', left: '16px', zIndex: 1200, }} > <button onClick={() => setIsMenuOpen(!isMenuOpen)} style={{ width: '48px', height: '48px', borderRadius: '12px', background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#ffffff', fontSize: '24px', boxShadow: '0 4px 14px rgba(99, 102, 241, 0.4)', }} > {isMenuOpen ? 'β' : 'β°'} </button> </div> ); const customOverlay = isMenuOpen ? ( <div onClick={() => setIsMenuOpen(false)} style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0, 0, 0, 0.5)', zIndex: 1100, }} /> ) : null; const customLinks = ( <nav style={{ position: 'fixed', top: 0, left: isMenuOpen ? 0 : '-300px', width: '280px', height: '100vh', background: 'linear-gradient(180deg, #1e1b4b 0%, #312e81 100%)', zIndex: 1150, transition: 'left 0.3s ease', display: 'flex', flexDirection: 'column', }} > <div style={{ padding: '24px 20px', borderBottom: '1px solid rgba(255,255,255,0.1)', display: 'flex', alignItems: 'center', gap: '12px', }} > <div> <div style={{color: '#ffffff', fontSize: '16px', fontWeight: '700'}}>Acme Inc</div> <div style={{color: '#a5b4fc', fontSize: '12px'}}>Enterprise</div> </div> </div> <div style={{padding: '16px 12px', flex: 1}}> {links.map((link, index) => { const IconComponent = link.icon; return ( <a key={index} href={link.href} style={{ display: 'flex', alignItems: 'center', gap: '12px', padding: '12px 16px', borderRadius: '12px', textDecoration: 'none', marginBottom: '4px', color: '#a5b4fc', transition: 'all 0.2s ease', }} > {IconComponent && <IconComponent style={{fontSize: '20px'}} />} <span style={{fontSize: '14px', fontWeight: '500'}}>{link.text}</span> </a> ); })} </div> <div style={{ padding: '16px 20px', borderTop: '1px solid rgba(255,255,255,0.1)', }} > <div style={{display: 'flex', alignItems: 'center', gap: '12px'}}> <div style={{ width: '36px', height: '36px', borderRadius: '50%', background: '#6366f1', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '14px', fontWeight: '600', }} > JD </div> <div style={{flex: 1}}> <div style={{color: '#ffffff', fontSize: '14px', fontWeight: '500'}}>John Doe</div> <div style={{color: '#a5b4fc', fontSize: '12px'}}>Admin</div> </div> </div> </div> </nav> ); return { blocks: { ...defaultBlocks, menuButton: customMenuButton, overlay: customOverlay, links: customLinks, }, blockOrder: defaultBlockOrder, }; }} </SideNavigation> ); }
π§ Props Referenceβ
Main Component Propsβ
The main SideNavigation component inherits all props from MUI Stack component with component="aside".
| Prop | Type | Default | Description |
|---|---|---|---|
isFloating | boolean | undefined | Whether the navigation should float over content (mobile-style) or be fixed in place |
isMenuOpen | boolean | false | Controls whether the navigation menu is open or closed. If not provided, uses internal state |
setIsMenuOpen | (isMenuOpen: boolean) => void | Internal setter | Function to control the menu open/close state. If not provided, uses internal state setter |
header | { icon?: SvgIconComponent; text?: ReactNode; href: string } | undefined | Header link object with optional MUI icon component, text content, and href |
links | { icon?: SvgIconComponent; text?: ReactNode; href: string }[] | Required | Array of navigation link objects with optional MUI icon components |
children | BlocksOverride | undefined | Function to override default blocks or add custom navigation components |
className | string | undefined | Additional CSS class name(s) |
sx | SxProps<Theme> | See below | MUI system props for styling |
Default sx styling:
{
display: 'inline-flex',
maxWidth: 300,
alignItems: 'stretch',
backgroundColor: 'background.paper',
width: 'fit-content',
height: '100%',
// When open: minWidth: 240
// When floating: position: 'absolute', top: 0, right: 0, zIndex: theme.zIndex.drawer
// When floating and closed: display: 'none'
}
Sub-Componentsβ
The SideNavigation component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
SideNavigation.Overlayβ
A full-screen overlay that appears when the floating menu is open. Inherits all MUI Box props.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | undefined | Custom content for the overlay |
setIsMenuOpen | (isMenuOpen: boolean) => void | From context | Function to control menu state when overlay is clicked |
onClick | (event) => void | Closes menu | Click handler (defaults to calling setIsMenuOpen(false)) |
className | string | undefined | Additional CSS class name(s) |
sx | SxProps<Theme> | See below | MUI system props for styling |
Default sx styling:
{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: '#1d1e20b2',
zIndex: 'inherit',
}
Note: This component inherits all MUI Box component props.
SideNavigation.MenuButtonβ
The hamburger menu button for toggling the navigation. Inherits all MUI IconButton props.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | <SvgIcon component={Menu} /> | Custom content for the button (defaults to Menu/MenuOpen icon) |
isFloating | boolean | From context | Whether in floating mode |
isMenuOpen | boolean | From context | Current menu open state |
setIsMenuOpen | (isMenuOpen: boolean) => void | From context | Function to toggle menu state |
onClick | (event) => void | Toggles menu | Click handler (defaults to toggling isMenuOpen) |
className | string | undefined | Additional CSS class name(s) |
sx | SxProps<Theme> | See below | MUI system props for styling |
Default sx styling:
{
display: 'inline-flex',
border: 'none',
background: 'none',
alignSelf: 'flex-start',
// Floating: p: 1.25
// Non-floating: p: 1.5, mx: 1.5
}
Note: This component inherits all MUI IconButton component props. The default icon changes between Menu and MenuOpen based on state (non-floating mode).
SideNavigation.Linksβ
The navigation links container. Inherits all MUI Stack props with component="nav".
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default links rendering | Custom content to override default links rendering |
isFloating | boolean | From context | Whether in floating mode (affects link styling) |
isMenuOpen | boolean | From context | Whether menu is open (controls text visibility) |
header | { icon?: SvgIconComponent; text?: ReactNode; href: string } | From context | Header link object to display |
links | { icon?: SvgIconComponent; text?: ReactNode; href: string }[] | From context | Array of navigation links to display |
className | string | undefined | Additional CSS class name(s) |
sx | SxProps<Theme> | See below | MUI system props for styling |
Default sx styling:
{
position: 'relative',
zIndex: 'inherit',
}
Note: This component inherits all MUI Stack component props. Each link is rendered as an MUI Link with consistent styling.
π¨ Configuration examplesβ
Custom Stylingβ
import HomeIcon from '@mui/icons-material/Home';
import FolderIcon from '@mui/icons-material/Folder';
import GroupIcon from '@mui/icons-material/Group';
import SettingsIcon from '@mui/icons-material/Settings';
function CustomStyledSideNavigation() {
const links = [
{icon: HomeIcon, text: 'Home', href: '/'},
{icon: FolderIcon, text: 'Files', href: '/files'},
{icon: GroupIcon, text: 'Profile', href: '/profile'},
{icon: SettingsIcon, text: 'Settings', href: '/settings'},
];
const header = {
text: 'Menu',
href: '/',
};
return (
<SideNavigation
header={header}
links={links}
sx={{
width: 260,
bgcolor: 'grey.900',
borderRight: '1px solid',
borderColor: 'grey.800',
minHeight: 400,
}}
>
<SideNavigation.Links
sx={{
p: 2,
'& .MuiListItem-root': {
borderRadius: 1,
mb: 0.5,
color: 'grey.300',
'&:hover': {
bgcolor: 'grey.800',
},
},
'& .MuiSvgIcon-root': {
color: 'primary.light',
},
}}
/>
</SideNavigation>
);
}
Floating Navigationβ
import {useState} from 'react';
import DashboardIcon from '@mui/icons-material/Dashboard';
import InventoryIcon from '@mui/icons-material/Inventory';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import SettingsIcon from '@mui/icons-material/Settings';
import HomeIcon from '@mui/icons-material/Home';
function FloatingSideNavigation() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const links = [
{icon: DashboardIcon, text: 'Dashboard', href: '/dashboard'},
{icon: InventoryIcon, text: 'Products', href: '/products'},
{icon: ShoppingCartIcon, text: 'Orders', href: '/orders'},
{icon: SettingsIcon, text: 'Settings', href: '/settings'},
];
const header = {
icon: HomeIcon,
text: 'App',
href: '/',
};
return (
<SideNavigation
header={header}
links={links}
isFloating={true}
isMenuOpen={isMenuOpen}
setIsMenuOpen={setIsMenuOpen}
>
<SideNavigation.Overlay />
<SideNavigation.MenuButton />
<SideNavigation.Links />
</SideNavigation>
);
}
Custom Links Container Stylingβ
<SideNavigation.Links
sx={{
bgcolor: 'grey.100',
borderRadius: 2,
p: 1
}}
/>
Custom Menu Button Stylingβ
<SideNavigation.MenuButton
sx={{
color: 'primary.main',
'&:hover': { bgcolor: 'primary.light' }
}}
/>
Custom Overlay Stylingβ
<SideNavigation.Overlay
sx={{
bgcolor: 'rgba(0, 0, 0, 0.7)'
}}
/>
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
import {SvgIconComponent} from '@mui/icons-material';
import DashboardIcon from '@mui/icons-material/Dashboard';
import AnalyticsIcon from '@mui/icons-material/Analytics';
import InventoryIcon from '@mui/icons-material/Inventory';
import SettingsIcon from '@mui/icons-material/Settings';
import HomeIcon from '@mui/icons-material/Home';
import {useState} from 'react';
interface NavLink {
icon?: SvgIconComponent;
text?: React.ReactNode;
href: string;
}
interface NavHeader {
icon?: SvgIconComponent;
text?: React.ReactNode;
href: string;
}
function TypedSideNavigation() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navigationLinks: NavLink[] = [
{
icon: DashboardIcon,
text: 'Dashboard',
href: '/dashboard',
},
{
icon: AnalyticsIcon,
text: 'Analytics',
href: '/analytics',
},
{
icon: InventoryIcon,
text: 'Products',
href: '/products',
},
{
icon: SettingsIcon,
text: 'Settings',
href: '/settings',
},
];
const navigationHeader: NavHeader = {
icon: HomeIcon,
text: 'App Name',
href: '/',
};
return (
<SideNavigation
header={navigationHeader}
links={navigationLinks}
isFloating={false}
isMenuOpen={isMenuOpen}
setIsMenuOpen={setIsMenuOpen}
sx={{
width: 280,
minHeight: '100vh',
borderRight: '1px solid #e5e7eb',
}}
>
<SideNavigation.Links />
</SideNavigation>
);
}
π Notesβ
-
MUI Integration: The component uses MUI
Stack,Box,IconButton,Link, andSvgIconcomponents under the hood. -
Icon Type: The
iconproperty expects anSvgIconComponentfrom@mui/icons-material, not a string. Import icons likeHome,Dashboard, etc. -
Internal State Management: If
isMenuOpenandsetIsMenuOpenare not provided, the component manages its own state internally. -
Floating vs Fixed Mode:
- Floating mode: Navigation appears on top of content with an overlay, positioned absolutely on the right side. Menu button appears outside the navigation.
- Fixed mode: Navigation is inline with content. Menu button appears inside the navigation with a close button that appears outside when open.
-
Responsive Behavior: In floating mode, the navigation is hidden when closed (
display: 'none'). The overlay blocks interaction with the page content. -
Block Override Pattern: Use the
childrenfunction to customize sub-components while preserving the default block structure. -
Z-Index: The component uses
theme.zIndex.drawerfor floating mode to ensure proper layering.
Built with β€οΈ using React, TypeScript, MUI, and modern web standards.