Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Stacked Double Row Navbar Block for React

A two-row navbar: utilities on top (Support, Docs, Status, a language menu, an account menu) and the main tabs below, where only the lower row stays stuck on scroll, by CSS alone.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

A stacked double-row navbar for React with Base UI, the header of a property-management product called Rowhouse. The upper row is for utilities: the wordmark at the start, then Support, Docs and Status as plain links, a language menu and an account menu. The lower row carries the main tabs (Overview, Properties, Tenants, Maintenance, Payments, Reports; the current one is medium weight on a muted underlay and has aria-current="page") and a Shine Button, Add property. Each row has its own spine, so the rails and a top rule line up with the blocks above and below, and the whole header is 104 pixels tall (48 and 56). Only the lower row stays stuck: the header is sticky -top-12 z-40 bg-background, so scrolling slides the utility row off the top and leaves the tabs, with no script. On a phone the utilities and the button fold into a sheet from the top, and the tabs scroll sideways with fades at the edges. It's built from Dropdown Menu, Sheet, Avatar, Shine Button, Button and Guides, with your theme's tokens for every colour. For dashboards and admin sites with a few utilities and many sections.

FAQ

How does only the lower row stay stuck?

The header is sticky -top-12 z-40 bg-background: it sticks 48 pixels above the top of the viewport, which is exactly the height of the upper row, so once you have scrolled past it only the 56 pixel tab row is left in view. There is no script and no scroll listener. Put the header as a direct child of your page's scrolling container (the body, normally), and give nothing between them overflow: hidden, which would stop the sticking. In the gallery's preview the page doesn't scroll, so you see both rows at rest.

How do I change the tabs and the utilities?

Edit TABS (an id and a label each), UTILITIES, LANGUAGES and ACCOUNT at the top of the file. The links are href="#": point them at your routes and derive the current tab from your router instead of the block's current state, which only marks a tab when it is clicked. Choosing a tab marks it current and brings it to the middle of the row on a phone.

What does the language menu do?

It is a radio list: choosing a language checks it, changes the button's name to it and a polite status says "Español selected." Focus goes back to the button. Nothing else on the page is translated, because the block has no strings to swap; wire pickLanguage to your i18n. The Language Switcher block shows a bar that translates itself.

How does it work with a keyboard and a screen reader?

Two navs: Utility (Support, Docs, Status) and Main (the tabs), each a labelled landmark with a list of links. The language and account buttons say whether they are expanded and open menus: Enter, Space or the Down arrow opens one, the arrow keys move through it, Enter chooses and Escape closes it with focus back on its button. Enter, Space or the Down arrow opens a menu with focus on its first row.

How does it work on a phone?

Below the md breakpoint the upper row is the wordmark and a menu button. The button opens a sheet from the top with the same utilities, the languages (buttons that say which is in use), the account links and Add property; choosing a link closes it and Escape or the close button returns focus to the menu button. The lower row is the tabs alone, scrolling sideways with a fade at each edge that can still scroll, the current tab brought into view. Nothing wraps at 320 pixels.

Does it work right to left?

Yes. The rows mirror, the tabs scroll from the right and the fades move to the correct edges, the chevrons turn, and the menus open under the button's start edge. The wordmark is artwork and keeps its direction. Wrap the block in your direction provider (the catalog's DirectionProvider) so the menus follow the page.

What moves, and what about reduced motion?

Nothing moves on load. Tabs ease their colour, the chevrons turn, the menus fade in and the sheet slides down; scrolling a chosen tab into view is smooth. With reduced motion the colours and chevrons change at once, the sheet appears without sliding and the tab row jumps to the tab.

  • Pro

    A two-row shop navbar: wordmark, a search that jumps to a category and account and bag links on top, and below a strip of category chips with counts that snap-scrolls with edge fades and brings the current chip into view.

  • Pro

    A two-row settings header: the page title and one real edit (a Weekly digest switch) with Discard and Save that wake up when it changes, and a row of section tabs where the dirty one carries a dot and a spoken note.

  • Pro

    A two-row header whose second row shows the chosen section's four links, the three link sets cross-fading in one grid cell, with the current section and the current page both marked.

  • Pro

    A two-row navbar for a stationery subscription: a promo row with a discount code and a Copy button that folds away when dismissed, above a standard bar with four links, Sign in and a Shine Button.

  • Pro

    Tabs Underline Navbar

    Link highlights

    A navbar for a financial reporting tool built as cells: the wordmark in its own cell, full-height report tabs whose 2 px mark sits on the bar's bottom edge and slides on selection, and an Export action, with arrow-key navigation and a scrolling tab row on phones.

  • Pro

    A one-bar marketing navbar for a product roadmap tool: a wordmark, a Product menu of four areas with icons and one-line descriptions, plain links with the current page marked, Sign in and a Shine Button, and a sheet with the same links on phones.