enes

TopNav

TopNav gives a single selection from a row of items, with a bar that marks the selected one. Each item carries a short label and often an icon.

Everything landing in the next hour.

The bar belongs to the strip rather than to any one item: when the selection moves it travels to the item that took it, staying on screen the whole way instead of disappearing from one and reappearing under the next.

The strip owns the selection and nothing else. What an item opens is rendered by you, wherever it belongs on the page, so an item can open a panel underneath it, swap a region somewhere else, or drive a route.

To create a top nav, you will need to use the following components:

  • TopNav: The root component that creates the context every item reads: which item is selected, the appearance, the size and the axis. It renders the `tablist` and the bar that travels across it.
  • TopNavItem: A single item of the strip. It reports its own selection and can carry an icon.

Usage

A top nav expects a `value` on every item and a `selectedValue` to match it against. Bind `selectedValue` to follow the selection, and render whatever the selected item opens yourself.

<script>
	import { TopNav, TopNavItem } from 'fluentui-svelte';

	let selectedValue = $state('arrivals');
</script>

<TopNav bind:selectedValue aria-label="Flights">
	<TopNavItem id="tab-arrivals" value="arrivals">Arrivals</TopNavItem>
	<TopNavItem id="tab-departures" value="departures">Departures</TopNavItem>
</TopNav>

{#if selectedValue === 'arrivals'}
	<div role="tabpanel" aria-labelledby="tab-arrivals">Everything landing in the next hour.</div>
{:else}
	<div role="tabpanel" aria-labelledby="tab-departures">Everything leaving in the next hour.</div>
{/if}

Appearance

`appearance` decides how the strip is painted. `transparent` has no background of its own and `subtle` fills an item while it is engaged; both mark the selection with the travelling bar. The two circular appearances trade that bar for a pill: `subtle-circular` outlines the selected item and `filled-circular` fills it.

Size

`size` sets the padding, the type and the thickness of the bar for every item at once.

Vertical

`vertical` stacks the items in a column and moves the bar to their leading edge, where it travels up and down instead of across. The arrow keys follow the same turn.

Icon

`icon` takes a snippet or a component and renders it before the label.

As an Anchor

`as="a"` renders the item as an anchor and takes the attributes of one, `href` among them, so the item has a real URL to open in a new tab or copy. It still reports as a `tab`, which is what a strip of tabs over one page should be; if the items are navigation between pages rather than tabs, a `nav` of plain links is the better shape.

Disabled

`disabled` on the strip disables every item at once, and a single item can be disabled on its own. The arrow keys pass over a disabled item rather than landing on it.

Select on Focus

`selectTabOnFocus` selects an item as soon as the focus reaches it, so the arrow keys move the selection rather than only the focus. Use it when what an item opens is already on the page; leave it off when opening one costs a request.

Reserved Space

A selected item sets its label in semibold, which is wider than the same label at rest. `reserveSelectedTabSpace` is on by default and holds that width from the start, so selecting an item never shoves the ones beside it along. Turning it off lets the items size to what they are showing, and the row shifts as the selection moves.

Component Props (TopNav)

NameTypeDefaultDescription
ref bindableHTMLDivElementThe DOM reference of the strip.
selectedValue bindablestringThe value of the selected item.
onTabSelect(event: Event, value: string) => voidFired when an item is selected.
appearanceTopNavAppearance'transparent'How the strip is painted: `transparent` has no background of its own, `subtle` fills an item while it is engaged, and the two circular appearances trade the moving bar for a pill.
size'small' | 'medium' | 'large''medium'The size of every item of the strip.
verticalbooleanfalseArranges the items in a column, with the bar down their leading edge.
disabledbooleanfalseDisables the user interaction on every item.
selectTabOnFocusbooleanfalseSelects an item as soon as the focus reaches it, rather than waiting to be asked.
reserveSelectedTabSpacebooleantrueA selected item sets its label in semibold, which is wider than the same label at rest. This holds that width from the start, so selecting an item never shifts the ones beside it.
disableTabspotbooleanfalseOpts the strip out of the tabspot focus management, to wire your own.
Element Attributes (div)

Component Props (TopNavItem)

NameTypeDefaultDescription
ref bindableTopNavItemElementDOMType[T]The DOM reference of the item.
as'button' | 'a''button'The DOM element to render. An anchor takes the attributes of one, `href` among them, and is what an item that navigates should be.
valuestringThe value that identifies the item. Defaults to a generated id.
iconSnippet | ComponentThe icon to display before the label.
disabledbooleanDisables the user interaction.
HTML Attributes

Keyboard Navigation

The strip is a single tab stop. The arrows walk the items along the axis they are laid out on, `Home` and `End` jump to the ends, and `Enter` and `Space` select the focused item — or `selectTabOnFocus` selects it on arrival. `disableTabspot` hands the focus management back to you.

Accessibility

The strip renders a `tablist` and every item a `tab`, so give it a name through `aria-label`. Since you render what an item opens, give that element a `tabpanel` role and point its `aria-labelledby` at the `id` of its item. An item with an icon and no label needs an `aria-label` of its own.