# Dot Rail: Site Header

> A print studio's header. The rail under it runs to whichever link you point at and parks under the current page when you leave.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/dot-rail-header-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/dot-rail-header-demo
- Screenshot: https://shadcn.exchange/shot/keyframeui/dot-rail-header-demo/light.png
- Registry item: https://keyframeui.com/r/dot-rail-header-demo.json
- Categories: navigation, progress, canvas
- Listed: 2026-11-02, source last changed 2026-11-02

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/keyframeui/dot-rail-header-demo.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `https://keyframeui.com/r/dot-rail.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/dot-rail#dot-rail-header-demo

## Files

### `registry/demos/dot-rail-header-demo.tsx`

```tsx
"use client";

import * as React from "react";

import { DotRail } from "@/components/ui/dot-rail";

const links = [
  { label: "Prints", href: "#prints" },
  { label: "Studio", href: "#studio" },
  { label: "Workshops", href: "#workshops" },
  { label: "Journal", href: "#journal" },
];

function Mark() {
  return (
    <svg viewBox="0 0 20 20" aria-hidden className="size-5">
      <circle cx="10" cy="10" r="8.25" className="fill-none stroke-current" strokeWidth="1.5" />
      <circle cx="10" cy="10" r="3.25" className="fill-[var(--dot-rail-accent)]" />
    </svg>
  );
}

export function DotRailHeaderDemo() {
  const navRef = React.useRef<HTMLElement>(null);
  const [current, setCurrent] = React.useState("#studio");

  return (
    <div className="@container w-full max-w-4xl overflow-hidden rounded-2xl border border-[#0b0b0d]/10 bg-[#fafaf9] text-[#0b0b0d] [--dot-rail-accent:#ff5a1f] dark:border-white/10 dark:bg-[#07080c] dark:text-[#f4f4f6] dark:[--dot-rail-accent:#ff6a2b]">
      <header className="px-5 pt-4 @[44rem]:px-8">
        <div className="flex flex-wrap items-center justify-between gap-x-6 gap-y-2">
          <a
            href="#"
            onClick={(e) => e.preventDefault()}
            className="flex items-center gap-2 rounded-md text-[15px] font-semibold tracking-tight focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-current"
          >
            <Mark />
            Pressroom
          </a>
          <nav
            ref={navRef}
            aria-label="Main"
            className="order-last -mx-3 flex w-[calc(100%+1.5rem)] justify-between @[28rem]:mx-0 @[28rem]:w-full @[28rem]:justify-center @[28rem]:gap-2 @[44rem]:order-none @[44rem]:w-auto"
          >
            {links.map((link) => (
              <a
                key={link.href}
                href={link.href}
                aria-current={current === link.href ? "page" : undefined}
                onClick={(e) => {
                  e.preventDefault();
                  setCurrent(link.href);
                }}
                className="rounded-full px-3 py-2 text-[13px] font-medium text-[#0b0b0d]/60 transition-colors duration-150 hover:text-[#0b0b0d] focus-visible:outline-2 focus-visible:outline-offset-0 focus-visible:outline-current aria-[current=page]:text-[#0b0b0d] dark:text-[#f4f4f6]/60 dark:hover:text-[#f4f4f6] dark:aria-[current=page]:text-[#f4f4f6]"
              >
                {link.label}
              </a>
            ))}
          </nav>
          <a
            href="#book"
            onClick={(e) => e.preventDefault()}
            className="rounded-full bg-[#0b0b0d] px-4 py-2 text-[13px] font-medium text-[#fafaf9] transition-transform duration-150 active:scale-[0.97] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current dark:bg-[#f4f4f6] dark:text-[#07080c]"
          >
            Book a print run
          </a>
        </div>
        <DotRail trackRef={navRef} className="mt-2" />
      </header>

      <section className="px-5 pt-10 pb-12 text-center @[44rem]:px-8 @[44rem]:pt-14 @[44rem]:pb-16">
        <h2 className="font-serif text-4xl tracking-tight text-balance @[44rem]:text-[3.25rem] @[44rem]:leading-[1.05]">
          Small runs, <em className="text-[#2747ff] dark:text-[#8292ff]">loud</em> colors
        </h2>
        <p className="mx-auto mt-4 max-w-md text-[15px] leading-relaxed text-[#0b0b0d]/70 dark:text-[#f4f4f6]/70">
          Zines, posters and lookbooks printed a hundred at a time on two riso drums, in a back room off Calder Street.
        </p>
        <p className="mt-6 font-mono text-[11px] tracking-[0.18em] text-[#0b0b0d]/60 uppercase dark:text-[#f4f4f6]/60">
          Riso · 2 drums · 11 inks
        </p>
      </section>
    </div>
  );
}
```
