A bar of icon tabs along the bottom of the screen: the primary navigation on phones.
import { BottomNav } from 'frontile';
Each tab is an Item with an @icon and its label as the block. The label
names the tab and shows as a tooltip. Mark the current tab with @isActive,
or pass @route and let the router decide. Items take the same arguments as
Sidebar items, including @badge.
On its own the bar is fixed to the bottom of the viewport. The demos keep it inside a frame.
More adds a last tab that opens a sheet of further navigation from the
bottom of the screen. It yields Item and Folder, the sidebar's items and
folders as full-width rows. Following an item closes the sheet.
Tabs never move into the sheet on their own: choose which destinations are
tabs and which go in the sheet. The tab shows active when an item inside is
the current page, and a dot when an item inside has a badge. It is not shown
when every item inside is hidden, or with @isHidden.
@label names the tab (default More), @icon replaces its ellipsis, and
@sheetLabel names the sheet (default the label).
Note:
Morerenders its block twice, once hidden to track the active and badged items and once in the open sheet. Keepids and side effects (modifiers, analytics, data loading, a folder's@onOpenChange) out of it.
The sheet is as tall as its items, up to 80% of the viewport, and then scrolls.
Inside an AppLayout with
@mobileNav='bottom', use the yielded layout.BottomNav. It shows only below
the layout's breakpoint, in place of the sidebar, as the layout's bottom row.
Above the breakpoint it renders nothing and an open sheet closes.
The bar and the sheet pad their bottom edge by the device's safe-area inset, so tabs stay clear of the home indicator. The inset is only non-zero when the page opts in to the full screen:
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
Set --bottomnav-safe-area on the bar or an ancestor to use another inset.
<BottomNav style='--bottomnav-safe-area: 0px' as |bar|>
...
</BottomNav>
Modals, drawers and other overlays cover the bar. On its own the bar sets no
z-index, so render it before any overlay. In an AppLayout with
@scrollMode='page' it also rises above in-page layers such as sticky table
headers; keep any PortalTarget outside the AppLayout, or its overlays
render under the bar.
nav landmark named by @label (default Main). Give it a
distinct name if the page has another primary navigation.aria-current="page".@badge is hidden from assistive technology; its text is read after the
label. Pass @badgeLabel when the bare value is unclear.More tab is a button with aria-haspopup="dialog" and
aria-expanded. Its label is its accessible name; it shows no tooltip.
When it carries a dot, "has updates" is read after the label.@sheetLabel, holding a nav
landmark of the same name. Focus moves into it when it opens and is trapped
there. Escape, the drag handle (a button) or a click on the backdrop closes
it, and following an item closes it too. Focus then returns to the More
tab.Element: HTMLElement
A bar of icon tabs along the bottom of the screen, for the primary
navigation on small viewports. Rendered as a nav landmark. Each tab is a
NavItem in its icon layout, so the label is its accessible name and
shows as a tooltip. More adds a last tab that opens a bottom sheet of
further navigation.
On its own the bar is fixed to the bottom of the viewport and always
rendered. Yielded by AppLayout, it renders only with
@mobileNav="bottom" below the layout's breakpoint, as the grid's bottom
row (sticky in scrollMode="page"); otherwise it renders nothing, and an
open More sheet goes with it.
| Name | Type | Default | Description |
|---|---|---|---|
label
|
string
|
'Main'
|
The navigation landmark's accessible name. |
layout
|
Object
|
- |
Supplied by AppLayout. Not part of the public API.
|
| Name | Type | Default | Description |
|---|---|---|---|
default
*
|
Array
|
- |
The last tab of a BottomNav: it opens a bottom sheet holding more
navigation, as inline items and folders. The tab is a button with
aria-haspopup="dialog"; the sheet is a bottom Drawer with a nav
inside. The tab shows active when an item inside is active and a dot
when an item inside has a badge, even while the sheet is closed. It is
never aria-current: the current page is the item, not the tab.
The sheet takes exactly the content given; nothing overflows into it.
| Name | Type | Default | Description |
|---|---|---|---|
icon
|
ComponentLike
|
- | The tab's icon component. Defaults to a horizontal ellipsis. |
isHidden
|
boolean
|
false
|
Renders no tab. The tab is also not rendered when every item inside is hidden. |
label
|
string
|
'More'
|
The tab's label: its accessible name and tooltip. |
sheetLabel
|
string
|
- |
The sheet's accessible name, for both the dialog and the nav inside it.
Defaults to the label.
|
| Name | Type | Default | Description |
|---|---|---|---|
default
*
|
Array
|
- |
The sheet's content. Yields The block is rendered twice: once hidden, always, to track which item
is active or badged, and once in the open sheet. Avoid |