rc-navigation-bar
Bottom navigation layout that styles consumer-authored links.
Use this for compact PWA navigation where native anchors should remain router
friendly and work before custom element upgrade. Wrap it in a native <nav> to
provide navigation landmark semantics. The component deliberately provides no
landmark role of its own because the app owns page structure and may render
multiple navigation surfaces. Mark the current link with aria-current="page"
or provide active-selector for router active classes.
- Package
@rcarls/rc-navigation-bar- Element
<rc-navigation-bar>- Native dependency
- Consumer-authored <a> links
- State model
- Current page comes from aria-current or active-selector
- Main events
- None
Installation
- npm
- Yarn
npm install @rcarls/rc-navigation-bar
yarn add @rcarls/rc-navigation-bar
import '@rcarls/rc-navigation-bar/define';
Usage
<nav aria-label="Main navigation">
<rc-navigation-bar>
<a href="/library" aria-current="page">
<span data-rc-navigation-icon aria-hidden="true">local_library</span>
<span>Library</span>
</a>
<a href="/saved">
<span data-rc-navigation-icon aria-hidden="true">bookmark</span>
<span>Saved</span>
</a>
<a href="/settings">
<span data-rc-navigation-icon aria-hidden="true">settings</span>
<span>Settings</span>
</a>
</rc-navigation-bar>
</nav>
The native <nav> is the navigation landmark and owns its accessible label,
just as <search> owns landmark semantics around rc-search-bar.
rc-navigation-bar only provides layout, active-state styling, and indicator
positioning.
The active indicator measures [data-rc-navigation-indicator], then
[data-rc-navigation-icon], then the active link itself. Use
indicator-target when your markup needs a different measured element.
The bundled themes set the tagged icon target's line-height equal to its
block-size, keeping icon-font glyphs centered within the same box used for
hover and indicator geometry. Native <img>, <svg>, and Iconify icons use that
same target geometry without requiring a separate font offset. The higher-order
--rc-icon-font-size and --rc-icon-font-line-height theme tokens also apply to
button, rail, and generic [data-rc-icon] markup. Override either token at the
theme root or on one component; for example, set --rc-icon-font-line-height: 1
to restore an icon font's em-based line height.
Live demo
Router active classes
<nav aria-label="Main navigation">
<rc-navigation-bar active-selector="a.router-active">
<a class="router-active" href="/library">Library</a>
<a href="/settings">Settings</a>
</rc-navigation-bar>
</nav>
Adaptive navigation
Keep breakpoint policy in app/layout code. The navigation components do not own media queries, route matching, or persistence; they only style the native links you render into them.
Use the Material window classes from your app shell:
| Window width | App-owned navigation surface |
|---|---|
<600px compact | rc-navigation-bar in the bottom app chrome |
>=600px medium | collapsed rc-navigation-rail in the leading app chrome |
>=840px expanded | rc-navigation-rail, optionally expandable/persisted |
Render both surfaces from the same destination data and mark the current native
link in exactly one place, either with aria-current="page" or with a router
class matched by active-selector.
const destinations = [
{ href: '/', label: 'Home', icon: 'home' },
{ href: '/library', label: 'Library', icon: 'local_library' },
{ href: '/settings', label: 'Settings', icon: 'settings' },
];
const isMedium = matchMedia('(min-width: 600px)').matches;
const isExpanded = matchMedia('(min-width: 840px)').matches;
<!-- compact: <600px -->
<nav aria-label="Main navigation">
<rc-navigation-bar>
<a href="/library" aria-current="page">
<span data-rc-navigation-icon aria-hidden="true">local_library</span>
<span>Library</span>
</a>
<a href="/settings">
<span data-rc-navigation-icon aria-hidden="true">settings</span>
<span>Settings</span>
</a>
</rc-navigation-bar>
</nav>
<!-- medium and expanded: >=600px -->
<nav aria-label="Main navigation">
<rc-navigation-rail>
<a href="/library" aria-current="page">
<span data-rc-navigation-icon aria-hidden="true">local_library</span>
<span>Library</span>
</a>
<a href="/settings">
<span data-rc-navigation-icon aria-hidden="true">settings</span>
<span>Settings</span>
</a>
</rc-navigation-rail>
</nav>
At >=840px, let the app decide whether users may expand the rail and whether
that preference is persisted:
const key = 'app.navigation-rail-expanded';
const rail = document.querySelector('rc-navigation-rail');
rail.toggleable = isExpanded;
rail.expanded = isExpanded && localStorage.getItem(key) === 'true';
rail.addEventListener('rc-navigation-rail-toggle', (event) => {
localStorage.setItem(key, String(event.detail.expanded));
});
When switching modes in an SPA, wrap the app-owned state update in
document.startViewTransition() when available and assign stable transition
names in CSS:
rc-navigation-bar,
rc-navigation-rail {
view-transition-name: app-navigation;
}
rc-navigation-bar::part(indicator),
rc-navigation-rail::part(indicator) {
view-transition-name: app-navigation-indicator;
}
For measured morphs across unrelated layout regions, use a FLIP/Web Animations helper in the app layer. That code needs page geometry and should stay outside the component core.
Material theme
rc-theme-material/components.css applies the Material 3 bottom navigation
metrics used by the official Material Components implementation: an 80dp
surface, 64×32dp active indicator target, centered 24dp icon, safe-area padding,
label-medium typography, and state-layer hover treatment.
The Substrate theme highlights the active link itself and disables the moving indicator. The Material theme retains its separate animated indicator behind the icon target.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
activeSelector | active-selector | string | 'a[aria-current]:not([aria-current="false"])' | Selector used to find the active link. Defaults to `aria-current`. |
indicatorTarget | indicator-target | string | '[data-rc-navigation-indicator], [data-rc-navigation-icon]' | Selector inside the active link used for indicator geometry. |
Methods
No public methods are documented in the custom elements manifest.
Events
No custom events are documented in the custom elements manifest.
Slots
| Name | Description |
|---|---|
default | Navigation links. Direct `<a>` children are recommended. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-navigation-bar-bg | Canvas | Navigation surface background. |
--rc-navigation-bar-color | CanvasText | Navigation text color. |
--rc-navigation-bar-block-size | 4rem | Minimum block size for the bar. |
--rc-navigation-bar-padding-block | 0 | Bar block-axis padding. |
--rc-navigation-bar-padding-inline | 0 | Bar inline-axis padding. |
--rc-navigation-bar-gap | 0 | Gap between slotted items. |
--rc-navigation-bar-item-gap | 0.25rem | Gap between item icon and label. |
--rc-navigation-bar-item-min-block-size | 3rem | Minimum item block size. |
--rc-navigation-bar-item-padding-block | 0.5rem | Item block-axis padding. |
--rc-navigation-bar-item-padding-inline | 0.75rem | Item inline-axis padding. |
--rc-navigation-bar-item-color | inherit | Resting item text color. |
--rc-navigation-bar-item-text-decoration | Not specified | Slotted link text decoration (defers to native anchor text-decoration when unset). |
--rc-navigation-bar-active-color | Not specified | Active item text color. Falls back to `--rc-navigation-bar-item-color`, then `inherit`. |
--rc-navigation-bar-indicator-bg | transparent | Active indicator background. |
--rc-navigation-bar-indicator-border | 1px solid Highlight | Active indicator border. |
--rc-navigation-bar-indicator-radius | 0 | Active indicator corner radius. |
--rc-navigation-bar-indicator-duration | 0ms | Active indicator transition duration. |
--rc-navigation-bar-indicator-easing | ease | Active indicator transition easing. |
--rc-navigation-bar-focus-ring | Not specified | Slotted link focus outline (defers to native outline when unset). |
--rc-navigation-bar-focus-ring-offset | 2px | Slotted link outline offset. |
CSS Parts
| Part | Description |
|---|---|
nav | The navigation layout container. |
indicator | The active item indicator. |