Nav
import Nav from "@intility/bifrost-react/Nav";Responsive navigation
By default, the <Nav> provides a responsive layout for your app with a logo,
sidebar, top bar, mobile nav and hamburger menu button.
- Mobile -
0px-599px- Sidebar is hidden
- Top bar is visible, with
logo,topcontents, and menu toggle button - Top bar hides when scrolling down, and re-appears when scrolling upwards
- Menu button in top bar toggles fullscreen mobile menu
- Mobile navigation menu displays content from
sideprop. If you want completely separate navigation from sidebar you can usemobileprop instead.
- Tablet -
600px-1599px- Same as mobile, but the menu is placed on the left hand side with an overlay covering the rest of the page
- Desktop -
1600pxand wider- No hamburger button
- Sidebar is displayed only if
sideprop has content - Top bar is displayed only if
topprop has content
<Nav
// if you only supply a string to `logo` you'll get an "it" logo graphic
logo="Demo App"
side={
<>
<a href="/">
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
<a href="/profile">
<Nav.Item icon={faUser}>Profile</Nav.Item>
</a>
</>
}
top={
<>
<a href="/profile" title="User profile">
<Nav.Item icon={faUser} />
</a>
<button type="button">
<Nav.Item>Button</Nav.Item>
</button>
</>
}
>
Your app content goes here
</Nav>
Logo
<Nav.Logo> is a helper component to make it easier to style the logo and app
name uniformly across applications.
<Nav.Logo logo={<img src="myLogo.svg" alt="" />}>App Name</Nav.Logo>
<Nav.Logo logo> also accepts a string URL which is equivalent to the above.
<Nav.Logo logo="myLogo.svg">App Name</Nav.Logo>
The logo prop on <Nav> lets you supply any JSX content which will be placed
in the top bar.
We recommend wrapping <Nav.Logo> in a.bf-neutral-link linking to the home
page (if you're using a routing lib, you probably want to use <Link> instead
of <a>)
<Nav
logo={
<a href="/" className="bf-neutral-link">
<Nav.Logo logo="myLogo.svg">App Name</Nav.Logo>
</a>
}
top={...}
/>
If you only have a standalone sidebar, the logo will be placed in the top of the sidebar. Mobile devices always have a top bar.
<Nav
logo={
<a href="/" className="bf-neutral-link">
<Nav.Logo logo="myLogo.svg">App Name</Nav.Logo>
</a>
}
side={...}
/>
Internal badge
Some Intility apps have separate public facing and internal versions. To
distinguish them, you can place a <Badge> alongside the app name.
This example uses <Inline> to create an 8px gap, and .from-small to hide
it for screens below 600px width.
<Nav
logo={
<a href="/" className="bf-neutral-link">
<Nav.Logo logo="/home/bifrostLogo2025.svg">
<Inline gap={8}>
<span>App Name</span>
<Badge state="neutral" className="from-small">Internal</Badge>
</Inline>
</Nav.Logo>
</a>
}
top={...}
/>
Collapsible sidebar
If you want the sidebar to be collapsible, first make sure that each menu item
is a <Nav.Item> or <Nav.Group> with an icon.
Pass a boolean state to the sideProps.collapsed prop, and a function to the
sideProps.onCollapsedChange event.
Consider using
use-local-storage-state
if you want to persist the state between page reloads.
import { faEnvelopeOpenText, faHome } from "@fortawesome/free-solid-svg-icons";
import Nav from "@intility/bifrost-react/Nav";
import { useState } from "react";
export default function NavSideCollapseDemo() {
const [sideCollapsed, setSideCollapsed] = useState(false);
return (
<Nav
logo="Demo App"
sideProps={{
collapsed: sideCollapsed,
onCollapsedChange: (collapsed) => setSideCollapsed(collapsed),
}}
side={
<>
<a href="#path">
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
<a href="#path">
<Nav.Item icon={faEnvelopeOpenText}>Tickets</Nav.Item>
</a>
</>
}
>
Your app content goes here
</Nav>
);
}
Standalone sidebar
If you only supply content to side prop, no top bar will be rendered for
desktop screens.
For mobile screens the sidebar will be hidden and you will get a top bar with logo, app name and mobile menu button.
<Nav
logo="Demo App"
side={
<>
<a href="#path">
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
<a href="#path">
<Nav.Item icon={faEnvelopeOpenText}>Tickets</Nav.Item>
</a>
</>
}
>
Your app content goes here
</Nav>
Standalone top bar
<Nav
logo="Demo App"
top={
<>
<a href="#path">
<Nav.Item>Home</Nav.Item>
</a>
<a href="#path" title="User profile">
<Nav.Item icon={faUser} />
</a>
</>
}
>
Your app content goes here
</Nav>
External link
Use <Nav.Item external> prop to render an arrow, signaling that the link will
open another web page or application in a separate tab.
<a href="https://www.intility.com" target="_blank">
<Nav.Item icon={faGlobe} external>
intility.com
</Nav.Item>
</a>
In a collapsed sidebar, it will render as a small triangle instead:
Grouped items
You can have grouped sections of links by wrapping them (or other content) in a
<Nav.Group>. Avoid using icons on items inside a group.
- Renders as a popup on hover (or enter/space for keyboard users) for top bar, and for sidebar when collapsed
- Renders as a expandable submenu for mobile nav and sidebar when expanded
- Will be marked as active if there are any active sublinks (
.activeclass on a link or button inside the group). Can be overridden with theactiveprop.
<Nav.Group icon={faPencilRuler} name="Applications">
<a href="/overview">
<Nav.Item>Overview</Nav.Item>
</a>
<a href="/apps">
<Nav.Item>Applications</Nav.Item>
</a>
</Nav.Group>
Can be used inside <Nav side={...}> and will be rendered as an expandable
section. When the sidebar is collapsed it will be rendered as a pop-out instead.
Collapsed sidebar renders groups as pop-outs instead of expandable sections:
Or inside <Nav top={...}>, will be rendered as a dropdown.
Profile picture
To create a profile picture dropdown, use the .bf-nav-profile class on an
<img>.
<Nav.Group
name={<img className="bf-nav-profile" src="..." alt="Profile menu" />}
>
[dropdown content...]
</Nav.Group>
See full code and demo in the Profile Picture Example.
Search input
You can have a search input in either sidebar or top bar by using <Nav.Search>.
It renders as an <input> and accepts the same value and onChange props.
Use the optional onSubmit for handling clicks on the search icon (or enter keypress).
<Nav.Search
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
onSubmit={() => alert("search for " + searchValue)}
/>
When used in sidebar, we recommend placing it as the first menu item. It will be rendered inside a dropout when sidebar is collapsed, and a simple input for mobile/tablet menu.
useNav hook
Allows you to access internal state of the Nav, like sideCollapsed and
mobileOpen.
See details and usage at useNav hook docs
Highlight active page
You can add an .active class to the <a> link (or <button>) to mark it as
active for the current page.
<a href="/home" className="active">
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
Next.js App Router
When using Next.JS 13's App Router you can get the current path using the
usePathname hook,
then apply the .active class when appropriate.
// app/layout.tsx
import { type PropsWithChildren } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import Nav from "@intility/bifrost-react/Nav";
import { faHome } from "@fortawesome/pro-regular-svg-icons";
export default function RootLayout({ children }: PropsWithChildren) {
const pathname = usePathname();
return (
<html lang="en" className="bf-scrollbar">
<body>
<Nav
logo={
<Link href="/">
<Nav.Logo>Example app</Nav.Logo>
</Link>
}
side={
<>
<Link className={pathname === "/" ? "active" : ""} href="/">
<Nav.Item icon={faHome}>Home</Nav.Item>
</Link>
<Link
className={pathname === "/profile" ? "active" : ""}
href="/profile"
>
<Nav.Item icon={faUser}>Profile</Nav.Item>
</Link>
</>
}
>
{children}
</Nav>
</body>
</html>
);
}
React Router
When using <NavLink> from
react-router-dom,
an .active CSS class will automatically be added on the link, which is styled
by bifrost.
import {
Link,
NavLink,
BrowserRouter as Router,
Routes,
Route,
} from "react-router-dom"; // v6
import { faHome, faUser, faTools } from "@fortawesome/pro-regular-svg-icons";
import Nav from "@intility/bifrost-react/Nav";
export default function MyApp() {
return (
<Router>
<Nav
logo={
<Link to="/">
<Nav.Logo>Example app</Nav.Logo>
</Link>
}
side={
<>
<NavLink to="/">
<Nav.Item icon={faHome}>Home</Nav.Item>
</NavLink>
<NavLink to="/profile">
<Nav.Item icon={faUser}>Profile</Nav.Item>
</NavLink>
<NavLink to="/app">
<Nav.Item icon={faTools}>Applications</Nav.Item>
</NavLink>
</>
}
>
<Routes>
<Route path="/" element={<div>Home page</div>} />
<Route path="/profile" element={<div>profile page</div>} />
<Route path="/app" element={<div>Applications page</div>} />
</Routes>
</Nav>
</Router>
);
}
hideBranding
Since bifrost-react@4.2.0 we include "an intility service" at the bottom of
sidebar. If you need to remove it for some reason, you can use the
hideBranding prop.
Separate sub-components
The <Nav> component is built internally using
CSS breakpoints and sub-components: <Nav.Side>,
<Nav.Top>, and <Nav.Mobile>.
These components are basic HTML elements with Bifrost classnames applied. For advanced usage (for instance, sidebar only appears on certain pages) you can use these components yourself to compose whatever responsive navigation layout you want.
The useNav hook is tied to the <Nav> component and will not do anything when
working with the sub-components separately.
Nav.Side
LocalStorage/cookie state persistance is implemented in <Nav> component, when
using <Nav.Side> directly you can persist its state yourself with collapsed
and onCollapseChange props.
<Nav.Side
logo='Demo App'
>
<a href='#path'>
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
<a href='#path'>
<Nav.Item icon={faEnvelopeOpenText}>Tickets</Nav.Item>
</a>
</Nav.Side>
<main>App content goes here</main>
Nav.Top
<Nav.Top logo='Demo App'>
<a href='#path'>
<Nav.Item>Home</Nav.Item>
</a>
<a href='#path' title='User profile'>
<Nav.Item icon={faUser} />
</a>
</Nav.Top>
<main>App content goes here</main>
Nav.Mobile
Basically a big, fixed element that takes up the whole screen (leaves space for
top bar), suitable for mobile navigation popup. You will need to toggle it
yourself when not using the full <Nav> component. Add an onOverlayClick
callback to get an overlay over the page content.
<Nav.Mobile onOverlayClick={handleOverlayClick}>
<a href="#path">
<Nav.Item icon={faHome}>Home</Nav.Item>
</a>
<a href="#path">
<Nav.Item icon={faUser}>Profile</Nav.Item>
</a>
</Nav.Mobile>
In order to open and close, you have to toggle between .bf-nav-mobile-open and
.bf-nav-mobile-close classes on the <Nav.Mobile> element.
<Nav.Mobile className='bf-nav-mobile-open' />
<Nav.Mobile className='bf-nav-mobile-close' />