Mobile tab bar on the brand chrome for four or five destinations. The active tab carries the accent top bar and accent icon, badges sit on the icon, and every target is 56px tall. It is the phone-width partner of sui-side-nav; use one or the other, never both at once.
The bar is a nav landmark named Primary and each tab is a button in document order, so Tab reaches them and Enter or Space activates. The active tab carries aria-current="page", and every target clears the 44px minimum.
A destination gated by plan or permission carries disabled rather than leaving the array, so the bar keeps its layout. It renders a native disabled button, which takes no focus and emits nothing.
A tab with href is a real link, so open in a new tab works and the browser follows it on Enter. suiNavigate still fires and active still updates on the tap; a disabled tab stays a disabled button.
Tapping a tab that is not active writes active and emits suiActiveChange; every tap then emits suiNavigate with the tab key, which is the item key when it has one and the label otherwise. Give every tab a key once the labels are translated. A disabled tab emits nothing.
// setup(root): properties and events
setup(root) {
const log = root.querySelector('#bn-log');
const el = root.querySelector('#bn-events');
el.items = tabs();
el.addEventListener('suiNavigate', (e) => {
log.textContent = `Navigated to ${e.detail}.`;
});
}
Keyboard
Key
Action
Tab
Moves through the tabs in order. A tab with href is a link and one without is a button; a disabled tab is skipped.
Enter
Activates the tab: emits suiActiveChange when it was not active, then suiNavigate with its key, marks it aria-current, and a link tab then follows its href.
Space
Activates a button tab. A link tab follows on Enter alone, as any link does.
API
<sui-bottom-nav>
Properties
Property
Attribute
Type
Default
Description
active
active
stringstring | undefined
Key of the active tab, its own key or its label. Mutable; defaults to the first tab; updated on tap and reported through suiActiveChange.
fixed
fixed
boolean
false
Pins the bar to the viewport bottom with the top corners rounded. Pair it with safe-area padding on real devices.
items
property only
SuiBottomNavItem[]
[]
Tabs to render: { label, icon, badge?, disabled?, href?, target? }[]. A tab the user may not reach carries disabled rather than leaving the array, so the bar keeps its layout; a tab with href is a real link. Property, not attribute.
Events
Event
Detail
React
Vue
Description
suiActiveChange
string
onSuiActiveChange
@sui-active-change
Fires whenever the element writes active, a tap on a tab that was not active, before suiNavigate; detail is the new active. Writing active from script emits nothing. Does not bubble.
suiNavigate
string
onSuiNavigate
@sui-navigate
Fires when a tab is activated; detail is the tab key, its own key or its label.
Methods
Method
Signature
Description
setFocus()
setFocus() => Promise<void>
Moves keyboard focus to the active tab, or the first enabled one.
Types
SuiBottomNavIteminterfaceOne tab: label, Font Awesome icon class, optional badge count.
label
string
key?
string
Identity for active and suiNavigate. Defaults to the label; set it once the labels are translated or edited, so a handler keys off something that does not move.
icon
string
badge?
string | number
disabled?
boolean
Inert tab (a destination gated by permission or plan). Renders a native disabled button.
href?
string
Renders the tab as a real link, so middle-click and open in a new tab work and Enter follows it. suiNavigate still fires and active still updates on the tap. A disabled tab stays a disabled button whatever href says.
target?
string
Link target for a tab with href, e.g. _blank. A _blank tab gets rel="noopener".
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.