Skip to content
txbrendan/ui

Peek Spread

beta

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

Preview

peek

This week: and .

spread

Design workshop

Thu 1 Oct · 10:00 · Room 1

Plan

90 min

  1. Welcome15 min
  2. User research25 min
  3. Sketching20 min
  4. Prototype test30 min
Host
Steve Rowe
Bring
Laptop and notebook
By Sam CarterOpen plan

5 going

2 no reply

  • Tom HaleResearcherGoing
  • Finn ColeDesignerGoing
  • Kate ClarkeEngineerGoing
  • Mia OkaforEngineerGoing
  • Ben MossQAGoing
  • Leo BrandtWriterMaybe
  • Gus ReedDesign leadNo reply
  • Ana RuizTech leadNo reply
  • Josh TaitDesignerCan't make it

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. Add the component.

    npx shadcn@latest add @txbrendan/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

    Required. Names the peek.

    string

  • subtitle

    When and where, like "Thu 1 Oct · 10:00 · Room 1".

    string

  • icon

    An icon in a soft tile before the title.

    ReactNode

  • iconTone

    The icon tile's color role.

    "neutral" | "brand" | "danger" | "success" | "warning" · default "brand"

  • planTitle

    Heading over the plan.

    string · default "Plan"

  • plan

    Plan blocks in order. minutes draws the bar and the total. at shows a time instead.

    { label: string; minutes?: number; at?: string }[]

  • facts

    Rows under the plan. With a byline or an action, they sit at the foot of the column, just above it.

    [label: string, value: ReactNode | PersonValue][]

  • by

    Who made the plan, at its foot with their photo: "By Sam Carter".

    PersonValue

  • people

    Who is going. Each group lists going, maybe, no reply, then can't make it.

    { person; photo?; meta?; group?; rsvp?: "yes" | "maybe" | "none" | "no" }[]

  • peopleTitle

    Heading over the people. n counts going and no rsvp.

    string · default "{n} going"

  • peopleMeta

    A muted line beside the people title, like "6 no reply".

    string

  • action

    A link at the foot of the plan, like "Open plan".

    { label: string; href?: string; onClick? }

  • height

    Least height of both pages, in pixels. The plan grows past it. The people page scrolls inside it.

    number · default 252

  • className

    Extra classes on the spread. Later classes win.

    string

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

<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>