esc

Type to search...

Rail Sidebar

With showRail, closing the sidebar on desktop leaves a narrow icon column visible (the rail) instead of fully hiding. The rail is interactive, so users can click icons or tap an expand button to come back to the full panel. On viewports below mediaQueryWidth, rail is suppressed and the sidebar reverts to the traditional overlay close behavior.

Live Demo

Source

Add showRail and an optional railWidthPx (defaults to 64). Read isLeftRail from context to render compact content while in rail mode:

RailExample.tsx
import {
  SwipeBarProvider,
  SwipeBarLeft,
  useSwipeBarContext,
} from "@luciodale/swipe-bar";

function App() {
  return (
    <SwipeBarProvider>
      <Layout />
    </SwipeBarProvider>
  );
}

function Layout() {
  const { openSidebar, closeSidebar, isLeftOpen, isLeftRail } =
    useSwipeBarContext();

  const showLabels = isLeftOpen;

  return (
    <div className="flex h-full w-full">
      <SwipeBarLeft showRail railWidthPx={64} sidebarWidthPx={240}>
        <div className="flex flex-col p-2">
          <button
            onClick={() => (isLeftOpen ? closeSidebar("left") : openSidebar("left"))}
            aria-label={isLeftOpen ? "Collapse" : "Expand"}
          >
            {isLeftOpen ? "" : ""}
          </button>
          <nav>
            <button>
              <span aria-hidden="true"></span>
              {showLabels && <span>Dashboard</span>}
            </button>
            {/* ...more items */}
          </nav>
        </div>
      </SwipeBarLeft>

      <main>{/* page content */}</main>
    </div>
  );
}

How it behaves

  • Mounting with showRail and no defaultOpen on desktop renders the rail immediately at railWidthPx.
  • closeSidebar on desktop transitions to the rail; on small viewports it fully hides.
  • openSidebar always lands in the open mode (full sidebarWidthPx) and clears the rail flag.
  • The built-in toggle is hidden when the rail is showing on desktop — the rail itself is the affordance. On small viewports, the toggle reappears since the rail is suppressed.
  • Rail items are interactive (inert is cleared); the focus trap only activates in the open mode.
  • Crossing mediaQueryWidth reconciles automatically. Any open sidebar is closed first (no animation), then the new viewport's close-state takes over: rail on desktop, fully hidden on mobile. Open does not survive a viewport cross — it always resets to the appropriate close-state.