# Audience

> Who a message goes to, said before it is sent, with messages for juniors, people under 18, going to their parents or guardians.

- Name: `audience`
- Status: beta
- Categories: people, display
- File: the install writes `audience.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/avatar`, `@arbokui/avatar-stack`, `@arbokui/button`, `@arbokui/hover-card`, `@arbokui/peek-card`. The install adds them.
- Gallery: https://arbokui.com/components/audience
- Registry item: https://arbokui.com/r/audience.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/audience
   ```

## Use it for

- Above a message, before it is sent, so the sender knows who will read it.
- Pass everyone the message is for in to. Mark juniors and give their guardians.
- Set juniorMessages from your app's setting. "guardians" sends juniors' messages to their parents instead. "copy" sends them to the junior with their parents copied.
- Name a group with toLabel, like Group A. It titles the peek on the count.
- Pass onAddGuardian so a junior with no parent on file comes with the fix.
- Use audienceReach(to, juniorMessages) for the same count elsewhere, like on a Send button.

## Avoid it for

- Picking who a message goes to. This says who it reaches. It does not choose.
- A list of people who already read a message. Use Avatar Stack with a count.

## Props

- `to`: `{ person: string; photo?: string; id?: string; email?: string; junior?: boolean; guardians?: { person: string; photo?: string; id?: string; email?: string }[] }[]`. Required. Who the message is for. A parent of two juniors is counted once: by id, then email, then name.
- `toLabel`: `string`. What the group is called, like Group A. It titles the count's peek.
- `juniorMessages`: `"guardians" | "copy"`. Default `"guardians"`. Where messages to juniors go: to their parents instead, or to the junior with their parents copied.
- `onAddGuardian`: `(junior: { person: string; photo?: string }) => void`. The fix for a junior with no parent on file, like opening their profile.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. Text and face size: meta, body, or section type.
- `className`: `string`. Extra classes on the root. Later classes win.

## Accessibility

- Plain text: Goes to, then who. Faces are hidden from screen readers, since the names are in the text.
- A group's count is a peek trigger with a dotted underline. Focus or hover opens everyone, grouped by how they get it.
- The · before a phrase is hidden from screen readers, which hear a comma instead. When the phrase wraps, the · hides too.
- A junior it does not reach is said in danger text, with a button for the fix. It never relies on the color alone.

## Examples

### One person

```tsx
<Audience to={[{ person: "Josh Tait" }]} />
```

### A junior, through their parents

```tsx
<Audience
  to={[{ person: "Ella Clarke", junior: true, guardians: [{ person: "Kate Clarke" }, { person: "Mark Clarke" }] }]}
/>
```

### A group, with a junior who has no parent on file

```tsx
<Audience
  to={group}
  toLabel="Group A"
  juniorMessages="copy"
  onAddGuardian={(junior) => openProfile(junior.person)}
/>
```
