# Agency: Header

> One line with the studio's availability, its pages as a list and the way in, then its name set bold, edge to edge.

A shadcn/ui block from the [@eased](https://eased.dev/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/eased/agency-header).

- Page, with a live preview: https://shadcn.exchange/r/eased/agency-header
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/eased/agency-header-light-c9515914d9ebdc53.png
- Registry item: https://eased.dev/r/agency-header.json
- Listed: 2026-10-23, source last changed 2026-10-23

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/eased/agency-header.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://eased.dev/r/eased-tokens.json`, `https://eased.dev/r/eased-motion.json`, `https://eased.dev/r/agency-core.json`

## Files

### `src/registry/eased/templates/agency/header.tsx`

```tsx
"use client";

import { useLayoutEffect, useRef, useState } from "react";
import { brand, nav } from "./content";
import { ArrowLink, COLUMN, useHref } from "./kit";

const LINK = "focus-ring rounded-control-xs text-text transition-colors duration-(--eased-duration-fast) ease-standard hover-fine:text-text-secondary";

/**
 * The masthead: one quiet line (when the studio can start; its pages written as a list, comma
 * after comma; and the way in), then the name set in the heavy sans as wide as the page. It scrolls
 * away with the page; nothing sticks over the reel. Below md the availability goes.
 */
export function Header() {
  const to = useHref();
  return (
    <header className={`${COLUMN} pt-pad-base`}>
      <div className="flex min-h-control-md flex-wrap items-center justify-between gap-x-pad-lg gap-y-2 text-ui">
        <p className="flex items-center gap-2 text-text-secondary max-md:hidden">
          <span aria-hidden className="size-2 rounded-[2px] bg-(--tessera-tile)" />
          {nav.availability}
        </p>
        <nav aria-label="Main">
          <ul className="flex flex-wrap items-center">
            {nav.links.map((link, i) => (
              <li key={link.label} className="whitespace-pre">
                <a href={to(link.href)} className={LINK}>
                  {link.label}
                </a>
                {i < nav.links.length - 1 && <span className="text-text-muted">, </span>}
              </li>
            ))}
          </ul>
        </nav>
        <ArrowLink href={nav.action.href}>{nav.action.label}</ArrowLink>
      </div>
      <a href={to("/")} aria-label={`${brand.name} home`} className="focus-ring mt-pad-md block rounded-control-sm sm:mt-pad-lg">
        <Wordmark />
      </a>
    </header>
  );
}

/**
 * The name, edge to edge, in the sans at 800 with tight tracking, mixed case, and a vermilion
 * tile for a full stop. It is the logo, so it is set heavier than any heading may be (rule 43 is
 * for headings). SVG text whose viewBox is measured to the text's own box, so it spans
 * the column exactly at any width once the font has loaded; an estimate holds the height until.
 */
function Wordmark() {
  const ref = useRef<SVGTextElement>(null);
  const [box, setBox] = useState({ x: 0, y: -84, w: 760, h: 104 });

  useLayoutEffect(() => {
    const el = ref.current;
    if (!el) return;
    const measure = () => {
      const b = el.getBBox();
      if (b.width) setBox({ x: b.x, y: b.y + b.height * 0.2, w: b.width, h: b.height * 0.72 });
    };
    measure();
    document.fonts?.ready.then(measure);
  }, []);

  // The tile sits on the baseline after the text, a gap's width beyond it.
  const tile = 17;
  return (
    <svg
      viewBox={`${box.x} ${box.y} ${box.w + tile * 1.6} ${box.h}`}
      className="block w-full overflow-visible text-text"
      role="img"
      aria-label={`${brand.wordmark.name} ${brand.wordmark.trade}`}
    >
      <text ref={ref} x="0" y="0" fill="currentColor" fontSize="112" fontWeight="800" letterSpacing="-6.5" className="font-display" aria-hidden>
        {brand.wordmark.name} {brand.wordmark.trade}
      </text>
      <rect x={box.x + box.w + tile * 0.6} y={-tile} width={tile} height={tile} rx="2" fill="var(--tessera-tile)" />
    </svg>
  );
}
```
