# Peek Spread

> A two-page peek for an event: the plan on the left, and who is going on the right.

- Name: `peek-spread`
- Status: beta
- Categories: overlays
- File: the install writes `peek-spread.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/avatar`, `@arbokui/button`, `@arbokui/hover-card`, `@arbokui/person`. The install adds them.
- Gallery: https://arbokui.com/components/peek-spread
- Registry item: https://arbokui.com/r/peek-spread.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/peek-spread
   ```

## Use it for

- As a HoverCard's content on an event's title, with width 480. Its title names the peek.
- plan lists the blocks in order. minutes draws the proportion bar and the total. at shows a time instead, like 15:00.
- facts are \[label, value\] rows under the plan. With a byline or an action, they sit at the foot, just above it. A PersonValue, like { person: 'Steve Rowe' }, shows with a photo.
- people lists who is going. rsvp adds a mark at the row's end, and group splits the list, like Design and Engineering. Leave group out when each row's meta already names the team.
- The plan sets the height and never scrolls. The people page takes that height and scrolls inside it.

## Avoid it for

- A peek about one person or one thing. Use PeekCard.
- A full event page. Link to it with action.
- A plan with more than 8 blocks. The peek is a glance. Put the rest on the plan's page.

## Props

- `title`: `string`. Required. Names the peek.
- `subtitle`: `string`. When and where, like "Thu 1 Oct · 10:00 · Room 1".
- `icon`: `ReactNode`. An icon in a soft tile before the title.
- `iconTone`: `"neutral" | "brand" | "danger" | "success" | "warning"`. Default `"brand"`. The icon tile's color role.
- `planTitle`: `string`. Default `"Plan"`. Heading over the plan.
- `plan`: `{ label: string; minutes?: number; at?: string }[]`. Plan blocks in order. minutes draws the bar and the total. at shows a time instead.
- `facts`: `[label: string, value: ReactNode | PersonValue][]`. Rows under the plan. With a byline or an action, they sit at the foot of the column, just above it.
- `by`: `PersonValue`. Who made the plan, at its foot with their photo: "By Sam Carter".
- `people`: `{ person; photo?; meta?; group?; rsvp?: "yes" | "maybe" | "none" | "no" }[]`. Who is going. Each group lists going, maybe, no reply, then can't make it.
- `peopleTitle`: `string`. Default `"{n} going"`. Heading over the people. n counts going and no rsvp.
- `peopleMeta`: `string`. A muted line beside the people title, like "6 no reply".
- `action`: `{ label: string; href?: string; onClick? }`. A link at the foot of the plan, like "Open plan".
- `height`: `number`. Default `252`. Least height of both pages, in pixels. The plan grows past it. The people page scrolls inside it.
- `className`: `string`. Extra classes on the spread. Later classes win.

## Accessibility

- In a HoverCard, the title names the peek's dialog.
- The plan is a group named by its heading. Its bar is hidden from screen readers, since each block reads its own minutes.
- The people list scrolls, so it is a Tab stop named by its heading, and the keyboard scrolls it with the arrow keys.
- Its pages are named groups, not landmarks, so two spreads with the same headings on one page never repeat a landmark.
- Each rsvp mark has words for screen readers: Going, Maybe, No reply, or Can't make it.
- In a narrow peek the pages stack, and the people page keeps its own height.

## Examples

### On an event's title

```tsx
<HoverCard
  width={480}
  glance={false}
  content={
    <PeekSpread
      title="Design workshop"
      subtitle="Thu 1 Oct · 10:00 · Room 1"
      plan={[
        { label: "Welcome", minutes: 15 },
        { label: "Research", minutes: 25 },
        { label: "Prototype", minutes: 30 },
      ]}
      facts={[["Host", { person: "Steve Rowe" }]]}
      by={{ person: "Sam Carter" }}
      people={[
        { person: "Josh Tait", meta: "Designer", rsvp: "yes" },
        { person: "Kate Clarke", meta: "Engineer", rsvp: "maybe" },
      ]}
      peopleMeta="6 no reply"
    />
  }
>
  Design workshop
</HoverCard>
```
