Navbar
Build responsive site and application navigation with branding, nav links, forms, and a drawer-based mobile menu.
Overview
The navbar is the primary navigation surface for a site or application. It composes a branding area, a set of navigation links, optional forms or text, and a drawer-based mobile menu — all wrapped in a single <nav> element (rendered by <Navbar>) that is responsive by default.
<Navbar> accepts a handful of sub-components as needed: <NavbarBrand> for a project or product name, <NavbarNav> for navigation links, <NavbarToggler> for opening the mobile <Drawer>, <NavbarText> for inline text, and standard form components for search boxes or other controls.
Basic usage
A complete navbar combines a <NavbarBrand>, a <NavbarToggler>, and a <Drawer> that holds the navigation below the expand breakpoint. The expand prop controls when the drawer's contents flow inline instead — set on a container-query basis, so the transition responds to the navbar's own width rather than the viewport width.
import { useState } from 'react'
import {
Button,
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Form,
Icon,
Menu,
MenuDivider,
MenuItem,
MenuList,
MenuToggle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink,
TextInput
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="md" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarBasicUsage"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarBasicUsage"
placement="end"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody className="mb-sm md:mb-0">
<NavbarNav className="me-auto">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<Menu component="li" className="nav-item">
<MenuToggle component={NavLink}>Menu</MenuToggle>
<MenuList>
<MenuItem href="#">Action</MenuItem>
<MenuItem href="#">Another action</MenuItem>
<MenuDivider />
<MenuItem href="#">Something else here</MenuItem>
</MenuList>
</Menu>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
<Form className="hstack gap-sm" role="search">
<TextInput type="search" placeholder="Search" aria-label="Search" />
<Button
type="submit"
color="neutral"
variant="smooth"
className="icon-only"
aria-label="Search"
>
<Icon name="search-solid" />
</Button>
</Form>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}Brand
<NavbarBrand> sets the project or product identity at the start of the navbar. It works on any element, but an anchor is the most common choice since the brand typically links to the home page.
import { Container, Navbar, NavbarBrand } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
</Container>
</Navbar>
)
}Replace the text with an <img> for an image-only brand.
import { Container, Navbar, NavbarBrand } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">
<img src="https://placehold.co/24" alt="Navbar" width="24" height="24" />
</NavbarBrand>
</Container>
</Navbar>
)
}Combine an image and text in the same brand element. The d-inline-block and align-text-top utilities keep the image aligned with the surrounding text baseline.
import { Container, Navbar, NavbarBrand } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">
<img
src="https://placehold.co/24"
alt=""
width="24"
height="24"
className="d-inline-block align-text-top"
/>
<span className="ms-xs font-strong">Chassis</span>
</NavbarBrand>
</Container>
</Navbar>
)
}Nav
Navbar navigation uses <NavbarNav> wrapping <NavItem>/<NavLink> pairs. Its links grow to occupy the available horizontal space once the navbar expands inline. Mark the current link with active, which renders aria-current="page".
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="sm" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarNav"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer id="navbarNav" placement="end" visible={visible} onClose={() => setVisible(false)}>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav>
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">About</NavLink>
</NavItem>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}The <NavItem>/<NavLink> pairing is optional — rendering <NavbarNav component="div"> with direct <NavLink> children produces the same result, and pairs naturally with the nav-segments class.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="sm" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarNavAltMarkup"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarNavAltMarkup"
placement="end"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav component="div" className="nav-segments">
<NavLink href="#" active>
Home
</NavLink>
<NavLink href="#">Link</NavLink>
<NavLink href="#">About</NavLink>
<NavLink disabled>Disabled</NavLink>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}<Menu> nests inside a <NavbarNav> with component="li" and className="nav-item", so the toggle and menu share the same nav item wrapper. Set <MenuToggle>'s own component to NavLink so the trigger renders with .nav-link styling instead of its default .button look.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Menu,
MenuDivider,
MenuItem,
MenuList,
MenuToggle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="md" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarNavMenu"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarNavMenu"
placement="end"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav>
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">About</NavLink>
</NavItem>
<Menu component="li" className="nav-item">
<MenuToggle component={NavLink}>Menu</MenuToggle>
<MenuList>
<MenuItem href="#">Action</MenuItem>
<MenuItem href="#">Another action</MenuItem>
<MenuDivider />
<MenuItem href="#">Something else here</MenuItem>
</MenuList>
</Menu>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}Forms
Form controls placed inside a navbar use the standard form components. The navbar's flex layout defaults to justify-content: space-between, so a brand at the start and a form at the end align automatically without additional utilities.
import { Button, Container, Form, Navbar, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<Form className="d-flex" role="search">
<TextInput type="search" className="me-sm" placeholder="Search" aria-label="Search" />
<Button type="submit" color="primary" variant="outline">
Search
</Button>
</Form>
</Container>
</Navbar>
)
}The same form alongside a brand — the flex layout pushes the form to the opposite edge.
import { Button, Container, Form, Navbar, NavbarBrand, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<Form className="d-flex" role="search">
<TextInput type="search" className="me-sm" placeholder="Search" aria-label="Search" />
<Button type="submit" color="primary" variant="outline">
Search
</Button>
</Form>
</Container>
</Navbar>
)
}Input groups work too. When the navbar is essentially a form, rendering <Form> as the inner container saves a level of markup.
import { Button, Form, InputGroup, InputGroupAddon, Navbar, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Form className="container fluid">
<InputGroup>
<InputGroupAddon id="basic-addon1">@</InputGroupAddon>
<TextInput placeholder="Username" aria-label="Username" aria-describedby="basic-addon1" />
<Button type="submit" color="primary">
Submit
</Button>
</InputGroup>
</Form>
</Navbar>
)
}Mixed button sizes inside a navbar form align via the same flex layout, with vertical alignment utilities available for finer adjustment.
import { Button, Form, Navbar } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Form className="container fluid justify-content-start">
<Button type="button" color="primary" variant="outline" className="me-sm">
Main button
</Button>
<Button type="button" color="secondary" variant="outline" size="sm">
Smaller button
</Button>
<button type="submit" hidden>
Submit
</button>
</Form>
</Navbar>
)
}Text
<NavbarText> adjusts vertical alignment and horizontal spacing for inline strings of text inside the navbar.
import { Container, Navbar, NavbarText } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarText>Navbar text with an inline element</NavbarText>
</Container>
</Navbar>
)
}Text combines naturally with other navbar components inside the drawer body.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarText,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="md" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar w/ text</NavbarBrand>
<NavbarToggler
aria-controls="navbarText"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer id="navbarText" placement="end" visible={visible} onClose={() => setVisible(false)}>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav className="me-auto mb-sm md:mb-0">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">About</NavLink>
</NavItem>
</NavbarNav>
<NavbarText>Navbar text with an inline element</NavbarText>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}Dark mode
Set data-cx-theme="dark" directly on <Navbar> to opt a single navbar into the dark theme regardless of the page's own color scheme.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Menu,
MenuDivider,
MenuItem,
MenuList,
MenuToggle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="md" className="bg-even" data-cx-theme="dark">
<Container fluid>
<NavbarBrand href="#">Dark navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarDark"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer id="navbarDark" placement="end" visible={visible} onClose={() => setVisible(false)}>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody className="mb-sm md:mb-0">
<NavbarNav className="me-auto">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<Menu component="li" className="nav-item">
<MenuToggle component={NavLink}>Menu</MenuToggle>
<MenuList>
<MenuItem href="#">Action</MenuItem>
<MenuItem href="#">Another action</MenuItem>
<MenuDivider />
<MenuItem href="#">Something else here</MenuItem>
</MenuList>
</Menu>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}Context variants
The color prop swaps the navbar's color palette to a semantic context, matching the context class family used across this library (Card, List, and others). Combine with variant="solid" for a saturated fill, className="bg-*" for a custom background, or data-cx-theme to mix theme and context independently.
import { useState } from 'react'
import {
Button,
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Form,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink,
TextInput
} from '@chassis-ui/react'
const NavLinks = () => (
<NavbarNav className="me-auto mb-sm md:mb-0">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">About</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Contact</NavLink>
</NavItem>
</NavbarNav>
)
export const Example = () => {
const [visibleSolid, setVisibleSolid] = useState(false)
const [visibleDark, setVisibleDark] = useState(false)
const [visibleLight, setVisibleLight] = useState(false)
return (
<>
<Navbar expand="md" color="primary" variant="solid">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarColorSolid"
aria-expanded={visibleSolid}
aria-label="Toggle navigation"
onClick={() => setVisibleSolid(!visibleSolid)}
/>
<Drawer
id="navbarColorSolid"
placement="end"
visible={visibleSolid}
onClose={() => setVisibleSolid(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavLinks />
<Form className="d-flex" role="search">
<TextInput
type="search"
className="me-sm"
placeholder="Search"
aria-label="Search"
/>
<Button type="submit" color="default">
Search
</Button>
</Form>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
<br />
<Navbar expand="md" color="primary" className="bg-even" data-cx-theme="dark">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarColorDark"
aria-expanded={visibleDark}
aria-label="Toggle navigation"
onClick={() => setVisibleDark(!visibleDark)}
/>
<Drawer
id="navbarColorDark"
placement="end"
visible={visibleDark}
onClose={() => setVisibleDark(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavLinks />
<Form className="d-flex" role="search">
<TextInput
type="search"
className="me-sm"
data-cx-theme="light"
placeholder="Search"
aria-label="Search"
/>
<Button type="submit" color="default">
Search
</Button>
</Form>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
<br />
<Navbar expand="md" color="primary" className="bg-even" data-cx-theme="light">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarToggler
aria-controls="navbarColorLight"
aria-expanded={visibleLight}
aria-label="Toggle navigation"
onClick={() => setVisibleLight(!visibleLight)}
/>
<Drawer
id="navbarColorLight"
placement="end"
visible={visibleLight}
onClose={() => setVisibleLight(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavLinks />
<Form className="d-flex" role="search">
<TextInput
type="search"
className="me-sm"
placeholder="Search"
aria-label="Search"
/>
<Button type="submit" color="primary" variant="outline">
Search
</Button>
</Form>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
</>
)
}Translucent
The translucent prop blurs and saturates whatever sits behind the navbar — useful when the navbar is positioned over a hero image, video, or scrollable content.
import { Container, Navbar, NavbarBrand, NavbarNav, NavItem, NavLink } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar expand="md" translucent>
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
<NavbarNav>
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">About</NavLink>
</NavItem>
</NavbarNav>
</Container>
</Navbar>
)
}Containers
Wrapping <Navbar> in a <Container> centers it on the page; the inner <Container> is still required for the navbar's own padding. Placing the inner container directly inside <Navbar> instead centers only the navbar's contents while keeping its background full-width.
import { Container, Navbar, NavbarBrand } from '@chassis-ui/react'
export const Example = () => {
return (
<Container>
<Navbar expand="lg" className="bg-even">
<Container fluid>
<NavbarBrand href="#">Navbar</NavbarBrand>
</Container>
</Navbar>
</Container>
)
}Any responsive container variant is available to control how wide the navbar's contents appear.
import { Container, Navbar, NavbarBrand } from '@chassis-ui/react'
export const Example = () => {
return (
<Navbar expand="lg" className="bg-even">
<Container fluidUntil="md">
<NavbarBrand href="#">Navbar</NavbarBrand>
</Container>
</Navbar>
)
}Placement
The placement prop pulls the navbar out of normal flow or pins it during scroll: fixed-top/fixed-bottom use position: fixed and may require a compensating offset on the body (e.g. padding-top) to prevent content overlap; sticky-top/sticky-bottom use position: sticky.
import { useState, type ChangeEvent } from 'react'
import { Container, Navbar, NavbarBrand, Select } from '@chassis-ui/react'
type Placement = 'fixed-top' | 'fixed-bottom' | 'sticky-top' | 'sticky-bottom'
export const Example = () => {
const [placement, setPlacement] = useState<Placement>('fixed-top')
const handlePlacementChange = (e: ChangeEvent<HTMLSelectElement>) => {
setPlacement(e.target.value as Placement)
}
return (
<Navbar className="bg-even" placement={placement}>
<Container fluid>
<NavbarBrand>Navbar</NavbarBrand>
<Select
id="navbar-placement"
aria-label="Navbar placement"
className="w-auto"
value={placement}
onChange={handlePlacementChange}
options={[
{ label: 'Fixed top', value: 'fixed-top' },
{ label: 'Fixed bottom', value: 'fixed-bottom' },
{ label: 'Sticky top', value: 'sticky-top' },
{ label: 'Sticky bottom', value: 'sticky-bottom' }
]}
/>
</Container>
</Navbar>
)
}Responsive behavior
The expand prop controls when the navbar transitions between drawer mode and inline mode, implemented with container queries so the transition responds to the navbar's own width:
expand="sm"— drawer below the sm breakpoint, inline at sm and aboveexpand="md"— drawer below md, inline at md and aboveexpand="lg"— drawer below lg, inline at lg and aboveexpand="xl"— drawer below xl, inline at xl and aboveexpand="2xl"— drawer below 2xl, inline at 2xl and aboveexpand={true}— inline at all widths (toggler hidden, drawer contents render flat inside the navbar)expandomitted — drawer at all widths (toggler always visible, the drawer must be opened to access the nav)
Drawer placement
<Drawer>'s placement prop slides the panel in from any side. The examples below omit expand so the drawer stays visible regardless of viewport width.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">Left drawer</NavbarBrand>
<NavbarToggler
aria-controls="navbarLeftDrawer"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarLeftDrawer"
placement="start"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav className="me-auto mb-sm md:mb-0">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar className="bg-even">
<Container fluid>
<NavbarBrand href="#">Top drawer</NavbarBrand>
<NavbarToggler
aria-controls="navbarTopDrawer"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarTopDrawer"
placement="top"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarNav className="me-auto mb-sm md:mb-0">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}Toggle button
<NavbarToggler> has no fixed position — its location within the navbar is determined by its order in the markup relative to other flex siblings. Placing it before <NavbarBrand> renders it on the left; placing it after renders it on the right. The flex container distributes spacing between siblings automatically, so no positioning utility classes are required.
With no <NavbarBrand> visible (the brand lives inside the drawer):
import { useState } from 'react'
import {
Button,
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Form,
Navbar,
NavbarBrand,
NavbarNav,
NavbarToggler,
NavItem,
NavLink,
TextInput
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<Navbar expand="md" className="bg-even">
<Container fluid>
<NavbarToggler
aria-controls="navbarTogglerNoBrand"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
<Drawer
id="navbarTogglerNoBrand"
placement="end"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Hidden brand</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<NavbarBrand href="#">Hidden brand</NavbarBrand>
<NavbarNav className="me-auto mb-sm md:mb-0">
<NavItem>
<NavLink href="#" active>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled>Disabled</NavLink>
</NavItem>
</NavbarNav>
<Form className="d-flex" role="search">
<TextInput type="search" className="me-sm" placeholder="Search" aria-label="Search" />
<Button type="submit" color="success" variant="outline">
Search
</Button>
</Form>
</DrawerBody>
</Drawer>
</Container>
</Navbar>
)
}External content
<Drawer> and <NavbarToggler> are only linked by the visible/onClose/onClick state a consumer wires between them, so the controlled drawer can live anywhere in the document — not necessarily inside <Navbar>. Use this when the controlled content is structurally separate from the navigation surface.
import { useState } from 'react'
import {
Container,
Drawer,
DrawerBody,
DrawerHeader,
DrawerTitle,
Navbar,
NavbarToggler
} from '@chassis-ui/react'
export const Example = () => {
const [visible, setVisible] = useState(false)
return (
<>
<Drawer
id="navbarToggleExternalContent"
placement="top"
data-cx-theme="dark"
visible={visible}
onClose={() => setVisible(false)}
>
<DrawerHeader>
<DrawerTitle>Collapsed content</DrawerTitle>
</DrawerHeader>
<DrawerBody>
<span className="fg-main">Toggleable via the navbar toggler.</span>
</DrawerBody>
</Drawer>
<Navbar className="bg-main" data-cx-theme="dark">
<Container fluid>
<NavbarToggler
aria-controls="navbarToggleExternalContent"
aria-expanded={visible}
aria-label="Toggle navigation"
onClick={() => setVisible(!visible)}
/>
</Container>
</Navbar>
</>
)
}When the controlled drawer precedes its toggler in document order, keyboard and assistive technology users may have trouble locating the newly revealed content. Move focus into the drawer on open (<Drawer> does this automatically), and keep aria-controls pointing at the drawer's id so the toggler-to-content relationship is exposed.
Accessibility
An accessible navbar relies on semantic markup and ARIA attributes that assistive technologies can interpret.
<Navbar>renders a<nav>element by default, exposing it as a landmark region. Pass anaria-labelwhen a page has more than one navbar.- Mark the current page with
activeon the relevant<NavLink>, which rendersaria-current="page". <NavbarToggler>doesn't sync its ARIA attributes automatically — unlike the underlying CSS framework's vanilla JavaScript plugin, this component is a plain controlled button. Setaria-label,aria-controls(pointing at the drawer'sid), andaria-expanded(kept in sync with theDrawer's ownvisiblestate) explicitly, as every example above does.
API
Navbar
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
color? | ContextColor | — |
| Sets the color of the component to one of Chassis context colors. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
container? | boolean | "sm" | "md" | "lg" | "xl" | "2xl" | "fluid" | — |
Wraps the children in a .container, as Container renders one: true for the default,
'fluid' for one as wide as the navbar, or a breakpoint for one that is fluid until it. | ||
data-cx-theme? | "dark" | "light" | — |
| Opts this navbar into the framework's dark or light theming, independent of the page's own theme. | ||
expand? | boolean | Breakpoint | — |
Renders inline at and above this breakpoint, as a drawer below it. true renders inline at
every width; omit to keep the drawer at every width. | ||
placement? | "fixed-top" | "fixed-bottom" | "sticky-top" | "sticky-bottom" | — |
| Place component in non-static positions. | ||
ref? | any | — |
translucent? | boolean | — |
| Blurs and saturates whatever sits behind the navbar — useful when it's positioned over a hero image, video, or scrollable content. | ||
variant? | ContextStyle | — |
Sets the context style of the component. basic (the default) renders with no extra class. | ||
NavbarBrand
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
Component used for the root node. Either a string to use a HTML element or a component.
Defaults to span, or a when href is set. | ||
href? | string | — |
The href attribute specifies the URL of the page the link goes to. Defaults component to
a. | ||
ref? | any | — |
NavbarNav
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
NavbarText
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
NavbarToggler
| Prop | Type | Default |
|---|---|---|
className? | string | — |
| A string of all className you want applied to the base component. | ||
icon? | IconValue | — |
The toggler icon: an icon name, or an element of your own icon set. Defaults to
IconProvider's menu icon. | ||
label? | string | Toggle navigation |
| The accessible label announced by assistive technology when no children are provided. | ||