# Agency: Clients

> Client names as wordmarks in a ruled grid, then three numbers that roll up once.

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-clients).

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

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/eased/agency-clients.json
```

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

## Dependencies

- npm packages: `motion`
- Registry items: `https://eased.dev/r/eased-tokens.json`, `https://eased.dev/r/eased-motion.json`, `https://eased.dev/r/agency-core.json`, `https://eased.dev/r/number-roll.json`

## Files

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

```tsx
"use client";

import { useInView } from "motion/react";
import { useRef } from "react";
import { NumberRoll } from "../../number-roll/number-roll";
import { clients } from "./content";
import { Reveal, Section } from "./kit";

const TYPE = {
  sans: "font-sans font-semibold tracking-[-0.03em]",
  serif: "font-serif",
  mono: "font-mono",
} as const;

/**
 * Who the studio has worked for: the clients' names set as wordmarks in a ruled grid, each in
 * its own kind of type, then three numbers that roll up once, the first time they are seen
 * (rule 115).
 */
export function Clients() {
  const ref = useRef<HTMLDListElement>(null);
  const seen = useInView(ref, { once: true, amount: 0.5 });
  return (
    <Section id="clients" label={clients.label} className="flex flex-col gap-group">
      <Reveal>
        <p className="max-w-2xl font-display text-display-3xl font-medium tracking-display text-balance text-text">{clients.title}</p>
      </Reveal>
      <Reveal index={1}>
        <ul className="grid grid-cols-2 border-t border-l border-line-subtle md:grid-cols-4">
          {clients.names.map((c) => (
            <li
              key={c.name}
              className={`flex h-28 items-center justify-center border-r border-b border-line-subtle px-in text-display-xl text-text-secondary sm:h-36 sm:text-display-2xl ${TYPE[c.style]}`}
            >
              {c.name}
            </li>
          ))}
        </ul>
      </Reveal>
      <dl ref={ref} className="grid gap-pad-lg sm:grid-cols-3">
        {clients.numbers.map((n, i) => (
          <Reveal key={n.label} index={i} className="flex flex-col gap-1">
            <dt className="text-ui text-pretty text-text-secondary">{n.label}</dt>
            {/* The number reads first; the term stays first in the markup, as a dl needs. */}
            <dd className="order-first font-display text-display-5xl font-medium tracking-display text-text tabular-nums">
              <NumberRoll value={seen ? n.value : 0} locale="en-US" />
            </dd>
          </Reveal>
        ))}
      </dl>
    </Section>
  );
}
```
