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.2.0
π Usageβ
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
- Basic Usage
- Advanced Usage
function BasicSideNavigation() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navigationHeader = {
icon: 'home' as const,
text: 'Home',
href: '#home',
};
const navigationLinks = [
{icon: 'dashboard' as const, text: 'Dashboard', href: '#dashboard'},
{icon: 'shopping_cart' as const, text: 'Products', href: '#products'},
{icon: 'reorder' as const, text: 'Orders', href: '#orders'},
{icon: 'settings' as const, text: 'Settings', href: '#settings'},
{icon: 'help' as const, text: 'Support', href: '#support'},
];
return (
<SideNavigation
isFloating={true}
isMenuOpen={isMenuOpen}
setIsMenuOpen={setIsMenuOpen}
header={navigationHeader}
links={navigationLinks}>
<SideNavigation.Links />
</SideNavigation>
);
}
function AdvancedSideNavigation() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navigationHeader = {
icon: 'home' as const,
text: 'Home',
href: '#home',
};
const navigationLinks = [
{icon: 'π' as const, text: 'Dashboard', href: '#dashboard', color: '#007bff'},
{icon: 'ποΈ' as const, text: 'Products', href: '#products', color: '#007bff'},
{icon: 'π¦' as const, text: 'Orders', href: '#orders', color: '#007bff'},
{icon: 'βοΈ' as const, text: 'Settings', href: '#settings', color: '#007bff'},
{icon: 'π¬' as const, text: 'Support', href: '#support', color: '#007bff'},
];
return (
<SideNavigation
isFloating={true}
isMenuOpen={isMenuOpen}
setIsMenuOpen={setIsMenuOpen}
header={navigationHeader}
links={[]} // will use inside the override function
>
{({defaultBlocks, defaultBlockOrder}) => {
return {
blocks: {
...defaultBlocks,
// π§ Rich Navigation Links with full component override
links: {
...defaultBlocks.links,
props: {
...defaultBlocks.links.props,
className: 'custom-links',
children: (
<nav
style={{
display: 'flex',
flexDirection: 'column',
gap: '8px',
padding: '20px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
minHeight: '100vh',
width: isMenuOpen ? '280px' : '60px',
transition: 'all 0.3s ease',
position: 'relative',
overflow: 'hidden',
}}
>
{/* Header Section */}
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '12px',
padding: '16px 12px',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
borderRadius: '12px',
marginBottom: '20px',
backdropFilter: 'blur(10px)',
border: '1px solid rgba(255, 255, 255, 0.2)',
}}
>
<div
style={{
width: '40px',
height: '40px',
backgroundColor: '#fff',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.2rem',
color: '#667eea',
fontWeight: 'bold',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
}}
>
π
</div>
{isMenuOpen && (
<div style={{color: 'white'}}>
<div style={{fontWeight: 'bold', fontSize: '1.1rem'}}>My App</div>
<div style={{fontSize: '0.8rem', opacity: 0.8}}>Welcome back!</div>
</div>
)}
</div>
{/* Navigation Links */}
<div style={{display: 'flex', flexDirection: 'column', gap: '6px'}}>
{navigationLinks.map((item, index) => (
<a
key={index}
href={item.href}
style={{
display: 'flex',
alignItems: 'center',
gap: '15px',
padding: '14px 16px',
borderRadius: '10px',
textDecoration: 'none',
color: 'white',
transition: 'all 0.3s ease',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
border: '1px solid rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
}}
onMouseEnter={e => {
e.currentTarget.style.backgroundColor = item.color;
e.currentTarget.style.transform = 'translateX(8px)';
//@ts-expect-error - color is not a valid property
e.currentTarget.style.boxShadow = `0 4px 15px ${item.color}40`;
}}
onMouseLeave={e => {
e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
e.currentTarget.style.transform = 'translateX(0)';
e.currentTarget.style.boxShadow = 'none';
}}
>
<div
style={{
fontSize: '1.4rem',
minWidth: '24px',
textAlign: 'center',
}}
>
{item.icon}
</div>
{isMenuOpen && (
<div
style={{
fontSize: '0.95rem',
fontWeight: '500',
whiteSpace: 'nowrap',
}}
>
{item.text}
</div>
)}
</a>
))}
</div>
</nav>
),
},
},
},
blockOrder: defaultBlockOrder,
};
}}
</SideNavigation>
);
}
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
isFloating | boolean | undefined | Whether the navigation should float over content (mobile-style) or be fixed in place |
isMenuOpen | boolean | undefined | Controls whether the navigation menu is open or closed |
setIsMenuOpen | (isMenuOpen: boolean) => void | Required | Function to control the menu open/close state |
header | { icon?: IconType; text?: ReactNode; href: string } | Required | Header link object with optional icon, text content, and href |
links | { icon?: IconType; text?: ReactNode; href: string }[] | Required | Array of navigation link objects with optional icons |
children | BlocksOverride | undefined | Function to override default blocks or add custom navigation components |
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β
| 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 |
Note: This component inherits all HTML div element props.
SideNavigation.MenuButtonβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | <Icon icon="menu" /> | Custom content for the menu button (defaults to hamburger icon) |
isMenuOpen | boolean | From context | Current menu open state |
setIsMenuOpen | (isMenuOpen: boolean) => void | From context | Function to toggle menu state |
Note: This component inherits all HTML button element props.
SideNavigation.Linksβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default links rendering | Custom content to override default links rendering |
header | { icon?: IconType; text?: ReactNode; href: string } | From context | Header link object to display |
links | { icon?: IconType; text?: ReactNode; href: string }[] | From context | Array of navigation links to display |
Note: This component inherits all HTML nav element props.
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
import {ComponentProps, ReactNode} from 'react';
// Main component interface
interface SideNavigationProps extends Omit<ComponentProps<'aside'>, 'children'> {
isFloating?: boolean;
isMenuOpen?: boolean;
setIsMenuOpen: (isMenuOpen: boolean) => void;
header: { icon?: string; text?: ReactNode; href: string };
links: { icon?: string; text?: ReactNode; href: string }[];
}
// Usage example with comprehensive typing
interface CustomNavigationData {
headerItem: { icon?: string; text?: ReactNode; href: string };
menuItems: { icon?: string; text?: ReactNode; href: string }[];
isResponsive: boolean;
onMenuToggle: (isOpen: boolean) => void;
}
const NavigationComponent = ({headerItem, menuItems, isResponsive, onMenuToggle}: CustomNavigationData) => {
const [isOpen, setIsOpen] = useState(false);
const handleMenuToggle = (isMenuOpen: boolean) => {
setIsOpen(isMenuOpen);
onMenuToggle(isMenuOpen);
};
return (
<SideNavigation
isFloating={isResponsive}
isMenuOpen={isOpen}
setIsMenuOpen={handleMenuToggle}
header={headerItem}
links={menuItems}
onClick={e => console.log('Navigation clicked')}>
<SideNavigation.Links />
</SideNavigation>
);
};
Built with β€οΈ using React, TypeScript, and modern web standards.