# Agency: Work index

> Every project in one ruled grid: a small cover, the client, the project, its disciplines and its year.

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-work-page).

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

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/eased/agency-work-page.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`

## Files

### `src/registry/eased/templates/agency/work-page.tsx`

```tsx
"use client";

import { ClientArt } from "./client-art";
import { projects, workPage } from "./content";
import { COLUMN, LABEL, Reveal } from "./kit";

/**
 * The full index of work: the page's title and a line, then every project as a row of one
 * shared grid (rule 103): a small cover, the client, the project, its disciplines and its year,
 * each column starting on one line. Below sm a row stacks to cover and text.
 */
export function WorkPage() {
  return (
    <section aria-labelledby="work-title" className={`${COLUMN} pt-section-sm pb-group`}>
      <Reveal className="flex flex-col gap-pad-base">
        <h1 id="work-title" className="font-display text-display-5xl font-medium tracking-display text-text sm:text-display-6xl">
          {workPage.title}
        </h1>
        <p className="max-w-xl text-ui-md text-pretty text-text-secondary">{workPage.lead}</p>
      </Reveal>
      <div className="mt-group grid grid-cols-[7rem_minmax(0,1fr)] gap-x-pad-md md:grid-cols-[10rem_minmax(0,1fr)_minmax(0,1.4fr)_minmax(0,1fr)_auto]">
        {/* Column names for sighted readers; each row says what it is on its own. */}
        <div aria-hidden className={`col-span-full grid grid-cols-subgrid border-b border-line-subtle pb-in ${LABEL} max-md:hidden`}>
          <span />
          <span>{workPage.columns.client}</span>
          <span>{workPage.columns.project}</span>
          <span>{workPage.columns.disciplines}</span>
          <span className="text-right">{workPage.columns.year}</span>
        </div>
        <ol className="col-span-full grid grid-cols-subgrid">
          {projects.map((p, i) => (
            <li key={p.id} id={p.id} className="col-span-full grid scroll-mt-4 grid-cols-subgrid">
              <Reveal index={Math.min(i, 4)} className="col-span-full grid grid-cols-subgrid items-center border-b border-line-subtle py-pad-sm">
                <span aria-hidden className="image-ring relative aspect-[4/3] overflow-hidden rounded-control-sm [--art-min:0]">
                  <span className="absolute inset-0">
                    <ClientArt id={p.id} />
                  </span>
                </span>
                <span className="flex min-w-0 flex-col gap-1 md:contents">
                  <span className="text-ui-lg font-medium text-text md:text-display-xl">{p.client}</span>
                  <span className="text-ui text-pretty text-text-secondary">{p.title}</span>
                  <span className="text-ui-sm text-text-muted md:text-ui">{p.disciplines.join(", ")}</span>
                  <span className="text-ui-sm text-text-muted tabular-nums md:text-right md:text-ui">{p.year}</span>
                </span>
              </Reveal>
            </li>
          ))}
        </ol>
      </div>
    </section>
  );
}
```
