Icon Rail Flyouts

About this block

Icon Rail FlyoutsPRO

A fixed left rail of icon buttons with the brand mark on top and a create button at the bottom, beside a demo app content area. Hovering, focusing or clicking a rail item opens a flyout card to its right with a heading and described links. On a phone a top bar with the brand and a hamburger opens a fullscreen grid of icon tiles. The flyouts and the phone menu stay in the markup and are toggled with CSS.

An app-style navigation: a fixed left rail of icon buttons with the brand mark on top and a create button at the bottom, next to a demo content area. Each rail item opens a flyout card to its right with a heading and described links; on a phone a top bar with the brand and a hamburger opens a fullscreen grid of icon tiles.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://beste.dev/r/navbar87?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://beste.dev/r-base/navbar87?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/navbar87.tsx plus the shadcn button primitive it uses.

Quick start

The installed file exports navbar87Demo alongside the block: the exact props behind the preview above. Spread it to get a working navbar in one line.

tsx
import { Navbar87, navbar87Demo } from "@/components/beste/block/navbar87";

export default function Page() {
  return <Navbar87 {...navbar87Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Navbar87 } from "@/components/beste/block/navbar87";

export default function Page() {
  return (
    <Navbar87
      brand="Orbit"
      items={[
        {
          icon: "folder",
          label: "Projects",
          href: "/projects",
          heading: "Projects",
          links: [
            { title: "All projects", description: "Every board you can open.", href: "/projects" },
            { title: "Starred", description: "The ones you pinned.", href: "/projects/starred" },
          ],
        },
        {
          icon: "inbox",
          label: "Inbox",
          href: "/inbox",
          heading: "Inbox",
          links: [{ title: "Mentions", description: "Comments that name you.", href: "/inbox/mentions" }],
        },
      ]}
      button={{ label: "New project", href: "/projects/new" }}
      labels={{ open: "Open menu", close: "Close menu", home: "Home" }}
    />
  );
}

Leave content out in a real app and render your page as a sibling with md:pl-16, so it clears the rail.

Props

PropTypeDefaultDescription
brandstring–Brand name; its first letter becomes the mark on top of the rail
itemsRailItem[][]Rail buttons, each with its own flyout and mobile tile
buttonActionButton–Create button at the bottom of the rail and the foot of the mobile grid
contentDemoContent–Demo content area rendered beside the rail
labels{ open?: string; close?: string; home?: string }{}Accessible names for the mobile toggle, the close button and the brand mark
classNamestring–Extra classes for the outer wrapper
ts
type RailItem = {
  icon: IconName;
  label: string;
  href: string;
  heading: string;
  links: FlyoutLink[];
};

type FlyoutLink = {
  title: string;
  description: string;
  href: string;
};

type IconName = "folder" | "inbox" | "chart" | "users" | "settings";

type ActionButton = {
  label: string;
  href: string;
};

type DemoContent = {
  heading: string;
  description: string;
  cards: { title: string; description: string }[];
};

Behavior notes

  • Every flyout and the mobile tile grid are always rendered and toggled with CSS classes, so every link is in the server-rendered HTML. Closed flyouts and the closed grid carry aria-hidden and inert, which keeps their links out of the tab order.
  • A rail item opens its flyout on hover, on focus and on click, with aria-expanded and aria-controls; flyouts close when the pointer leaves the rail, when focus moves out of it, on Escape and on a pointer down outside it.
  • Each flyout sits in a padded wrapper that touches the rail, so the pointer can travel from the icon into the card without the flyout closing.
  • On a phone the rail is hidden and a sticky top bar takes its place. The tile grid fades in fullscreen with staggered tiles, locks body scroll while open and closes from its close button, Escape or any tile.

More Navigation blocks

View all Navigation
PRO

navbar94

Cascading Flyouts

PRO

navbar93

App Launcher Grid

PRO

navbar118

Navbar With Contact Bar and Hanging Logo

Get Pro