Skip to main content
brickwork
GitHub Log in Get started
Display
Theme
Density
Direction
Brand

Documentation

Components / Foundations

Navigation

One declarative NavItem tree rendered as a sidebar, header, or capability rail with route-aware active state.

Live demonstration

Use it

Read the pinned package source

  1. Build immutable NavItem values in a site module, use lazy translations for labels, then filter them per request.
  2. Resolve active state from request.resolver_match. Do not use path-prefix matching.
  3. Put the same filtered tree in the desktop and mobile shell seams so every destination remains reachable.
{% load brickwork_nav %}
<nav aria-label="Component library">{% bw_nav items=nav_items active=nav_active %}</nav>
<nav aria-label="Header navigation">{% bw_nav_header items=nav_items active=nav_active %}</nav>
<nav aria-label="Capabilities">{% bw_nav_rail items=nav_items active=nav_active density=rail_density %}</nav>

Python context

from brickwork.models import NavContext, NavItem
from brickwork.services.navigation import resolve_active_item, visible_items

items = (
    NavItem(key="components", label="Components", url_name="components:index", active_url_names=("components:detail",)),
    NavItem(key="guides", label="Guides", href="/docs/"),
    NavItem(key="docs", label="Documentation", section_header=True, children=(
        NavItem(key="forms", label="Forms", url_name="components:foundation_detail", url_kwargs={"slug": "forms"}),
    )),
)
visible = visible_items(items, NavContext(request=request))
active = resolve_active_item(visible, request.resolver_match)

Public API

NameSignature or valuesContract
NavItemfrozen dataclassExactly one of url_name, external_url, href, section_header, or menu_trigger defines its link shape.
bw_navitems, active=None, resolver_match=NoneRecursive sidebar and mobile-drawer tree.
bw_nav_headeritems, active=None, resolver_match=NoneFlat horizontal header renderer.
bw_nav_railitems, active=None, resolver_match=None, density='labelled'Capability rail. Density is labelled or icons.
visible_itemsitems, NavContextApplies declared permissions, features and visibility policies. It is display only, never authorisation.
resolve_active_itemitems, resolver_matchMatches route name and declared route kwargs, including active_url_names.

Accessibility and no-JavaScript behaviour

The renderers output ordinary links and native disclosure behaviour. A rail menu trigger declares aria-haspopup, while the consumer owns its progressive panel.

Sidebar and mobile drawer links remain ordinary anchors. Visibility is resolved server-side.

Troubleshooting

A navigation entry causes a render error.
Use a registered icon name and only one URL source. Validate the tree at import or application startup.
The wrong item stays active.
Declare active_url_names for detail routes and supply fixed url_kwargs for parameterised routes.
Documentation