Navigation
Displays a Navigation component that visualizes the page routing structure and allows users to navigate between different pages.
Basic Usage
To implement the Navigation component, you need to import it first:
import { Navigation } from 'rades_react';
And use it:
React.createElement(() => {
const [path, setPath] = React.useState("/");
return (
<Navigation
aria-label="Main"
currentPath={path}
items={[
{
label: 'Dashboard',
path: '/',
},
{
label: 'Settings',
path: '/settings',
},
{
label: 'Diagnostics',
path: '/diagnostics',
},
{
label: 'Users',
path: '/users',
},
]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
);
})
See API for all available options.
General Guidelines
-
Keep the navigation structure clear and logical. Group related items together and use descriptive labels that clearly indicate the destination.
-
Consider the depth of nesting. While Navigation supports up to 5 levels of nesting, try to keep your navigation structure as shallow as possible. Deep nesting can make navigation more difficult for users.
-
Use consistent labeling. Keep labels short and use consistent terminology throughout your navigation to help users understand where they are and where they can go.
-
Plan for mobile. Configure the responsive breakpoint via the
mobileBreakpointprop or the--rcm-navigation-breakpointCSS custom property to ensure your navigation adapts appropriately for smaller screens. The component automatically switches to a bottom bar layout below the breakpoint, where first-level items open dropdowns to display the second level.
Responsive Behavior
The Navigation component automatically switches between desktop and mobile layouts based on the breakpoint configuration.
- Desktop layout: Vertical collapsible stack
- Mobile layout: Horizontal bottom bar (first level items open dropdowns to display the second level)
Configuring the Breakpoint
The component determines the mobile breakpoint in the following order:
mobileBreakpointprop — If explicitly provided with a valid unit, this value is used.- CSS custom property — Reads
--rcm-navigation-breakpointfrom current context (must have explicit unit). - Default fallback — Uses 768 px if neither of the above is set.
⚠️ The mobileBreakpoint prop and CSS custom property must include an
explicit unit (px, em, or rem). Unitless values are rejected.
Supported Units
px- Pixels (e.g.,"768px","1024px")em- Relative to root font size (e.g.,"48em"= 768 px with 16 px root font size)rem- Relative to root font size (e.g.,"48rem"= 768 px with 16 px root font size)
Examples
/* Set breakpoint globally via CSS (various unit formats supported) */
:root {
--rcm-navigation-breakpoint: 1024px; /* Explicit pixels */
--rcm-navigation-breakpoint: 64em; /* Relative to root font size */
--rcm-navigation-breakpoint: 64rem; /* Root-relative unit */
}
/* Override per component instance with different units */
<Navigation
aria-label="Main"
currentPath={path}
items={items}
navigate={setPath}
mobileBreakpoint="1024px" // Must be string with unit
/>
/* Using em units (48 em = 768 px with 16 px root font size) */
<Navigation
aria-label="Main"
currentPath={path}
items={items}
navigate={setPath}
mobileBreakpoint="48em"
/>
/* Using rem units */
<Navigation
aria-label="Main"
currentPath={path}
items={items}
navigate={setPath}
mobileBreakpoint="48rem"
/>
Try toggling the buttons below to see how the navigation adapts to different screen sizes:
React.createElement(() => {
const [path, setPath] = React.useState("/");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '250px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
items={[
{
label: 'Dashboard',
path: '/',
},
{
label: 'Settings',
path: '/settings',
},
{
label: 'Diagnostics',
path: '/diagnostics',
},
{
label: 'Users',
path: '/users',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
In your application, simply set the mobileBreakpoint prop to match your
responsive design breakpoints, and the component will handle the rest.
Navigation with Icons
Icons can be added to navigation items to improve visual clarity and help users quickly identify different sections. Icons are supported in the first and second level of navigation.
When hasIcons is enabled, items without an icon property will display a
fallback icon automatically.
React.createElement(() => {
const [path, setPath] = React.useState("/");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '250px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
path: '/settings',
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
{
label: 'Users',
path: '/users',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
👉 Notice how the "Users" item displays a fallback icon since no icon
property was specified.
Nested Navigation
Navigation supports hierarchical navigation structures. Parent items can contain nested children to organize related pages together. Items with children expand inline within the collapsible stack. On mobile, first-level items open a dropdown to display the second level, and from there the same collapsible stack is used.
React.createElement(() => {
const [path, setPath] = React.useState("/settings/account/password");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '450px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
items: [
{
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
icon: 'globe',
label: 'Networks',
path: '/settings/networks',
},
{
icon: 'key',
label: 'Account',
items: [
{
label: 'Profile',
path: '/settings/account/profile',
},
{
label: 'Password',
path: '/settings/account/password',
},
{
label: 'Security',
path: '/settings/account/security',
},
],
},
],
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Deep Nesting
Navigation supports up to 5 levels of nesting to accommodate complex application structures. This example demonstrates the maximum nesting depth.
React.createElement(() => {
const [path, setPath] = React.useState("/settings/account/security/backup/codes");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '650px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
items: [
{
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
icon: 'globe',
label: 'Networks',
path: '/settings/networks',
},
{
icon: 'key',
label: 'Account',
items: [
{
label: 'Password',
path: '/settings/account/password',
},
{
label: 'Profile',
path: '/settings/account/profile',
},
{
label: 'Security',
items: [
{
label: '2FA Setup',
path: '/settings/account/security/2fa',
},
{
label: 'Backup Options',
items: [
{
label: 'Download Codes',
path: '/settings/account/security/backup/codes',
},
{
label: 'Email Recovery',
path: '/settings/account/security/backup/email',
},
],
},
],
},
],
},
],
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Item States
Navigation items can have different states to communicate their status to users.
Active Items
The active state is automatically applied to navigation items based on the
currentPath prop. When the current path matches an item's path property,
that item is visually highlighted as active. This helps users understand their
current location within the application.
👉 If a nested item is active, the navigation tree is automatically uncollapsed to show that item. This only applies to the stack mode (i.e., on desktop and inside dropdowns on mobile).
React.createElement(() => {
const [path, setPath] = React.useState("/settings/account/profile");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '450px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
items: [
{
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
icon: 'globe',
label: 'Networks',
path: '/settings/networks',
},
{
icon: 'key',
label: 'Account',
items: [
{
label: 'Profile',
path: '/settings/account/profile',
},
{
label: 'Password',
path: '/settings/account/password',
},
{
label: 'Security',
path: '/settings/account/security',
},
],
},
],
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Disabled Items
Disabled items are visible but not interactive. Use this state for navigation items that are temporarily unavailable or not applicable in the current context.
React.createElement(() => {
const [path, setPath] = React.useState("/");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '250px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
disabled: true,
icon: 'cogwheels',
label: 'Settings (Coming Soon)',
path: '/settings',
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
{
icon: 'old-man',
label: 'Users',
path: '/users',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Highlighted Items
Highlighted items draw attention to important actions or new features. Use the
isHighlighted prop to emphasize specific navigation items.
👉 When an item is highlighted, all its parent items are automatically highlighted as well.
React.createElement(() => {
const [path, setPath] = React.useState("/settings/account/security");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '400px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
items: [
{
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
disabled: true,
icon: 'globe',
label: 'Networks (Coming Soon)',
path: '/settings/networks',
},
{
icon: 'key',
label: 'Account',
items: [
{
label: 'Profile',
path: '/settings/account/profile',
},
{
isHighlighted: true,
label: 'Setup 2FA',
path: '/settings/account/security',
},
],
},
],
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Navigation Item IDs
Each navigation item can optionally include an id property, which will be
rendered as the HTML id attribute on the corresponding <li> element. This
is useful for easier element selection in test frameworks.
Usage Example
<Navigation
aria-label="Main"
currentPath={path}
items={[
{
id: 'nav_dashboard',
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
id: 'nav_settings',
icon: 'cogwheels',
label: 'Settings',
items: [
{
id: 'nav_settings_appearance',
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
id: 'nav_settings_account',
icon: 'key',
label: 'Account',
path: '/settings/account',
},
],
},
]}
navigate={setPath}
/>
Important Notes
- The
idproperty is optional. If not provided, noidattribute will be rendered on the<li>element. - Ensure all IDs are unique across your entire navigation structure to maintain valid HTML.
- IDs are used as-is (no automatic prefixing), giving you full control over naming conventions.
Complete Example
Here's a comprehensive example combining multiple features: icons, nested navigation, disabled items, highlighted items, and state management.
React.createElement(() => {
const [path, setPath] = React.useState("/");
const [breakpointMode, setBreakpointMode] = React.useState('responsive');
const mobileBreakpointMap = {
responsive: undefined,
mobile: '7680px', // 8k, maximum allowed width
desktop: '0px',
};
return (
<>
<ButtonGroup>
<Button
color={breakpointMode === 'responsive' ? 'selected' : 'secondary'}
label="Responsive"
onClick={() => setBreakpointMode('responsive')}
/>
<Button
color={breakpointMode === 'mobile' ? 'selected' : 'secondary'}
label="Force mobile"
onClick={() => setBreakpointMode('mobile')}
/>
<Button
color={breakpointMode === 'desktop' ? 'selected' : 'secondary'}
label="Force desktop"
onClick={() => setBreakpointMode('desktop')}
/>
</ButtonGroup>
<div
style={{
display: 'grid',
minHeight: '500px',
marginTop: '1rem',
overflow: 'hidden',
position: 'relative',
zIndex: 2,
}}
>
<Navigation
aria-label="Main"
currentPath={path}
hasIcons
items={[
{
icon: 'dashboard',
label: 'Dashboard',
path: '/',
},
{
icon: 'cogwheels',
label: 'Settings',
items: [
{
icon: 'adjust',
label: 'Appearance',
path: '/settings/appearance',
},
{
disabled: true,
icon: 'remote-connection',
label: 'Interfaces',
path: '/settings/interfaces',
},
{
icon: 'globe',
label: 'Networks',
path: '/settings/networks',
},
{
icon: 'key',
label: 'Account',
items: [
{
label: 'Password',
path: '/settings/account/password',
},
{
label: 'Profile',
path: '/settings/account/profile',
},
{
isHighlighted: true,
label: 'Setup 2FA',
path: '/settings/account/security',
},
],
},
],
},
{
icon: 'stethoscope',
label: 'Diagnostics',
path: '/diagnostics',
},
{
icon: 'old-man',
label: 'Users',
path: '/users',
},
]}
mobileBreakpoint={mobileBreakpointMap[breakpointMode]}
navigate={(path) => setPath(path)}
scrollToTopOnNavigate={false}
/>
</div>
</>
);
})
Scroll Behavior
By default, the Navigation component automatically scrolls the page to the top
when navigating to a new item. This behavior can be disabled using the
scrollToTopOnNavigate prop:
<Navigation
currentPath={path}
items={items}
navigate={setPath}
scrollToTopOnNavigate={false}
/>
When to disable: Useful in documentation pages or demos where multiple Navigation components are displayed together and automatic scrolling would disrupt the user experience.
Click-Outside Behavior
Mobile navigation dropdowns automatically close when clicking anywhere outside the dropdown boundaries. This includes clicks on elements with higher z-index than the dropdown backdrop, such as app headers or toolbars positioned above the navigation.
This behavior is automatic and works regardless of the z-index stacking context of your application layout. When clicking on interactive elements outside the dropdown (like buttons or links in your app header), both actions occur: the dropdown closes, and the clicked element's normal behavior executes (navigation, opening menus, etc.).
Accessibility
The Navigation component renders as a semantic <nav> element, which
serves as a navigation landmark for assistive technologies. To help users
understand the purpose of the navigation, you must provide an accessible
label using the aria-label prop.
The mobile variant uses the native HTML <dialog> element to display
the second-level navigation when first-level items are clicked. This provides
built-in accessibility features including focus management and keyboard
navigation.
<Navigation
aria-label="Main"
currentPath={path}
items={items}
navigate={setPath}
/>
Forwarding HTML Attributes
In addition to the options below in the component's API section, you
can specify React synthetic events or any HTML attribute you like. All
attributes that don't interfere with the API are forwarded to the root <nav>
HTML element. This enables making the component interactive and helps to improve
its accessibility.
👉 Refer to the MDN reference for the full list of supported attributes of the nav element.
API
Theming
| Custom Property | Description |
|---|---|
--rcm-navigation-breakpoint |
Breakpoint for switching to mobile layout (in px, em or rem) |