Navigation
ShellUI provides a flexible navigation system that supports icons, groups, localization, and multiple display modes.
Basic Navigation
The simplest navigation configuration uses an array of navigation items:
import type { ShellUIConfig } from '@shellui/core';
const config: ShellUIConfig = {
navigation: [
{
label: 'Home',
path: 'home',
url: 'http://localhost:4000/',
icon: '/icons/home.svg',
},
{
label: 'About',
path: 'about',
url: 'https://example.com/about',
},
],
};
Navigation Item Properties
Each navigation item supports the following properties:
label(string | LocalizedString, required): Display text for the navigation itempath(string, required): Unique path identifier used in the URL (e.g.,/home)url(string, required): URL to load when the navigation item is clickedicon(string, optional): Path to an SVG icon file (e.g.,/icons/home.svg)settings(string, optional): URL of a settings panel to display in Settings > Applications. See Application Settings for details.useHashRouter(boolean, optional): Whentrue, the app uses hash-based routing. If omitted, ShellUI infers this from theurlcontaining/#/(see Hash URL navigation below).
Hash URL navigation
ShellUI supports applications that use hash-based routing (e.g. React Router HashRouter, Vue Router in hash mode). For this to work, both the navigation configuration and any URLs opened in the shell must use the /#/ segment in the URL.
How ShellUI detects hash routing
- In configuration: A navigation item is treated as a hash-router app if its
urlcontains the literal sequence/#/(slash–hash–slash). For example:http://localhost:5173/#/orhttp://localhost:5173/#/themes. You can also setuseHashRouter: trueexplicitly. - When opening a link: When the user opens a URL (e.g. from the address bar or a link), ShellUI only applies hash-based navigation logic if the URL contains
/#/. For example,http://localhost:5173/#/themes/foowill be parsed: the part after/#/becomes the path used inside the shell, and the shell matches the base URL (before#) to a navigation item that is configured for hash routing.
If the URL does not contain /#/, ShellUI treats it as normal path-based routing (pathname + search only).
Example
const config: ShellUIConfig = {
navigation: [
{
label: 'Themes',
path: 'themes',
url: 'http://localhost:5173/#/themes', // Contains /#/ → hash routing
},
{
label: 'Home',
path: 'home',
url: 'http://localhost:5173/#/', // Root of hash app
},
],
};
With this setup, opening http://localhost:5173/#/themes/foo in the shell will navigate to the "Themes" app and pass the subpath foo to the iframe. The shell’s own URL remains path-based (no hash), so navigation stays consistent whether the embedded app uses hash or path routing.
Navigation Groups
Organize navigation items into groups with titles:
const config: ShellUIConfig = {
navigation: [
{
label: 'Dashboard',
path: 'dashboard',
url: 'http://localhost:4000/',
},
{
title: 'System',
items: [
{
label: 'Settings',
path: 'settings',
url: 'http://localhost:4000/settings',
icon: '/icons/settings.svg',
},
{
label: 'Profile',
path: 'profile',
url: 'http://localhost:4000/profile',
},
],
},
],
};
Groups can have a title (string or localized) and an array of items. The group title appears as a section header in the sidebar.
Localized Labels
Navigation labels and group titles can be localized for multi-language support:
const config: ShellUIConfig = {
language: ['en', 'fr'], // Enable English and French
navigation: [
{
// Simple string (backward compatible)
label: 'Home',
path: 'home',
url: '/',
},
{
// Localized label object
label: {
en: 'Documentation',
fr: 'Documentation',
},
path: 'docs',
url: '/docs',
},
{
// Group with localized title
title: {
en: 'System',
fr: 'Système',
},
items: [
{
label: {
en: 'Settings',
fr: 'Paramètres',
},
path: 'settings',
url: '/settings',
},
],
},
],
};
The label automatically updates based on the user's selected language. See the Internationalization guide for more details.
Visibility Control
Control when navigation items are visible:
Hidden Items
Hide items from the sidebar and 404 page (route remains valid):
{
label: 'Admin Panel',
path: 'admin',
url: '/admin',
hidden: true, // Hidden from sidebar, but route still works
}
Responsive Visibility
Hide items on specific screen sizes:
{
label: 'Desktop Only',
path: 'desktop',
url: '/desktop',
hiddenOnMobile: true, // Hidden on mobile (bottom nav)
}
{
label: 'Mobile Only',
path: 'mobile',
url: '/mobile',
hiddenOnDesktop: true, // Hidden on desktop (sidebar)
}
Note: hiddenOnMobile and hiddenOnDesktop have no effect if hidden is true.
Opening Modes
Control how navigation items open when clicked:
Default Mode
Opens in the main content area (default behavior):
{
label: 'Home',
path: 'home',
url: '/',
openIn: 'default', // Optional, this is the default
}
Modal Mode
Opens the URL in a modal overlay:
{
label: 'Settings',
path: 'settings',
url: '/settings',
openIn: 'modal',
}
The modal appears centered on the screen with a backdrop. Users can close it by clicking outside or pressing Escape.
Drawer Mode
Opens the URL in a side drawer panel:
{
label: 'Sidebar',
path: 'sidebar',
url: '/sidebar',
openIn: 'drawer',
drawerPosition: 'right', // Optional, defaults to 'right'
}
Drawer Positions:
'top'- Slides down from top'bottom'- Slides up from bottom'left'- Slides in from left'right'- Slides in from right (default)
External Mode
Opens the URL in a new browser tab:
{
label: 'External Site',
path: 'external',
url: 'https://example.com',
openIn: 'external',
}
This is equivalent to target="_blank" and opens the link in a new tab.
Sidebar Positioning
Control where items appear in the sidebar:
const config: ShellUIConfig = {
navigation: [
{
label: 'Top Item',
path: 'top',
url: '/',
position: 'start', // Default, appears in main sidebar area
},
{
label: 'Bottom Item',
path: 'bottom',
url: '/bottom',
position: 'end', // Appears in sidebar footer
},
{
title: 'Footer Group',
position: 'end', // Group appears in sidebar footer
items: [
{
label: 'Footer Item',
path: 'footer',
url: '/footer',
},
],
},
],
};
'start'(default): Items appear in the main sidebar area'end': Items appear in the sidebar footer (useful for settings, logout, etc.)
Complete Example
Here's a complete navigation configuration showcasing all features:
import type { ShellUIConfig } from '@shellui/core';
const config: ShellUIConfig = {
language: ['en', 'fr'],
navigation: [
{
label: 'Dashboard',
path: 'dashboard',
url: 'http://localhost:4000/',
icon: '/icons/dashboard.svg',
},
{
label: {
en: 'Documentation',
fr: 'Documentation',
},
path: 'docs',
url: 'https://docs.example.com',
icon: '/icons/book.svg',
},
{
label: 'External Link',
path: 'external',
url: 'https://example.com',
openIn: 'external',
},
{
label: 'Settings',
path: 'settings',
url: '/settings',
openIn: 'modal',
position: 'end',
},
{
label: 'Side Panel',
path: 'panel',
url: '/panel',
openIn: 'drawer',
drawerPosition: 'right',
},
{
title: {
en: 'System',
fr: 'Système',
},
items: [
{
label: {
en: 'Settings',
fr: 'Paramètres',
},
path: 'settings',
url: '/settings',
icon: '/icons/settings.svg',
},
{
label: 'Hidden Route',
path: 'hidden',
url: '/hidden',
hidden: true, // Not shown in sidebar
},
],
},
{
label: 'Mobile Only',
path: 'mobile',
url: '/mobile',
hiddenOnDesktop: true,
},
],
};
export default config;
Best Practices
- Use icons: Add SVG icons to make navigation more visual and easier to scan
- Group related items: Use navigation groups to organize related functionality
- Localize labels: Use localized strings when building multi-language apps
- Use appropriate open modes:
- Use
modalfor settings or quick actions - Use
drawerfor secondary content or sidebars - Use
externalfor links to other sites
- Use
- Position important items: Place frequently used items at the top (
position: 'start') and system items at the bottom (position: 'end')
Related Guides
- Layouts - Learn about different layout modes
- Internationalization - Multi-language support
- Modals & Drawers - Detailed guide on overlay modes