Overflow Nav
<x-wirekit::overflow-nav> shows a row of links that wraps onto at most lines rows, two by default. The links the rows have no room for move into a menu at the end of the last row, behind a button that shows how many it holds. The link marked current never moves into the menu, so the page on screen is always in the rows.
It suits a row of open records, recently viewed pages or filters, where the number of links changes and the width of the screen decides how many fit.
Usage
Pass the links as items. Each one takes a label and an href, and at most one should be current.
Lines
lines sets how many rows the links may take. With lines="1" the row never wraps, and everything that does not fit on one line goes into the menu.
Links that navigate with Livewire
Give an item attributes for anything its anchor should carry, such as wire:navigate. The same attributes go on the link in the rows and on its copy in the menu.
<x-wirekit::overflow-nav label="Open records" :items="$records->map(fn ($record) => [
'label' => $record->name,
'href' => route('records.show', $record),
'current' => $record->is($current),
'attributes' => ['wire:navigate' => true],
])->all()" />
How it decides what fits
The component lays every link out once, reads its width and replays the wrapping of the row in arithmetic. Links come off the end one at a time until the rest and the button fit in lines rows, so every row is full before anything moves into the menu. When only the current link would be left to move, nothing more moves, and the rows may then take one line more than lines.
Three details keep that measurement steady, and they matter if you build something like it yourself:
- It measures in one task. Showing every link through component state and measuring on the next tick lets the browser draw a frame in between; the row grows and shrinks, the resize observer sees it, and the row measures itself again on every frame. The component shows the links by hand, reads the widths and restores the styles before it sets any state.
x-showshows on the next frame. It hides at once but shows one animation frame later, so a link shown through state and measured right after still reads as hidden. The measurement reads the inline styles it set itself.- Only the width asks for a new measurement. The height changes every time a link moves into the menu, so the component measures again when the row's width changes or when links are added or removed, and never for a change of height.
Without JavaScript every link is shown, in as many rows as it takes, and there is no button.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items |
array |
[] |
The links, in order. Each takes label, href, and optionally current (the page on screen, never moved into the menu) and attributes (extra attributes for the anchor) |
lines |
int |
2 |
How many rows the links may take before the rest move into the menu |
label |
string|null |
null |
The landmark's name. With a label the row is a <nav>; without one it is a plain list, so two rows on a page never share a nameless landmark |
scope |
string|null |
null |
Scoped personalization key for the row, link and menu-link blocks |
Accessibility
- The current link carries
aria-current="page", and it stays in the rows at every width. - The button's accessible name counts the menu ("3 more links"), and its visible text is the count ("+3").
- The menu is a popover, named "More links", with a focus trap while it is open.
Escapecloses it and returns focus to the button. - A link that moves into the menu leaves the rows, so a screen reader meets every link exactly once.
Keyboard Interaction
| Key | Action |
|---|---|
Tab / Shift+Tab |
Move through the links in the rows, then to the button |
Enter (on a link) |
Follow the link |
Enter / Space (on the button) |
Open or close the menu |
Tab / Shift+Tab (inside the open menu) |
Move through the links in the menu, which keeps focus while it is open |
Escape |
Close the menu and return focus to the button |
Every entry is a link with the browser's own keyboard behavior; the menu is a popover.
Design Tokens
| Token | Used for |
|---|---|
--gap-wk-xs |
Space between links, and between rows |
--padding-wk-x-sm, --padding-wk-y-xs |
Padding of a link |
--radius-wk-md |
Corner radius of a link |
--color-wk-text-muted |
A link that is not current |
--color-wk-text, --color-wk-bg-muted |
The current link, and a link under the pointer |
--ring-wk-width, --color-wk-ring |
The focus ring |