# Suspension Row

> A player in the sin bin, sent off, or off for a temporary replacement, as a row in a card, counting down on the same clock value as MatchClock.

- Name: `suspension-row`
- Status: beta
- Categories: sport, display
- File: the install writes `suspension-row.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `lucide-react`. The install adds them.
- Other registry items: `@arbokui/avatar`, `@arbokui/button`, `@arbokui/match-clock`, `@arbokui/rolling-number`, `@arbokui/tooltip`. The install adds them.
- Gallery: https://arbokui.com/components/suspension-row
- Registry item: https://arbokui.com/r/suspension-row.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/suspension-row
   ```

## Use it for

- One row per player off, in a Card, beside the MatchClock on a scorer's or timekeeper's screen.
- Pass the match's clock value and format, the same ones the MatchClock gets. A card counts down on playing time: it stops when the clock stops, carries over half-time, and counts the time played after time is up.
- Record at as matchPlayed(clock) and time as matchClockDisplay(clock, format) when the card is shown.
- yellow uses the format's sin bin: 10 minutes in 15s, 2 in sevens and 10s, 5 to 7 in the age grades. Pass minutes when a competition sets its own.
- red reads Sent off for the rest of the match. red20 is elite rugby's 20-minute red card: after 20 minutes of playing time a replacement may come on.
- blood and hia are temporary replacements on the wall clock, from since: 15 minutes for blood, 12 for an HIA, or minutes={17} for both.
- Pass onReturn. A person button beside Can return, or Back within, brings them back on.
- Remove the row once the player is back on. A team's players on the field is its format's players less its rows.

## Avoid it for

- A row for a suspected concussion in community or age-grade rugby. Recognise and Remove takes them off for good, which is a permanent replacement, not a row.
- Your own countdown timer. The row works out the time from the clock value, so every device agrees.
- Telling the cards apart by the mark's color alone. The words under the name say which card it is.

## Props

- `player`: `{ person: string; photo?: string; number?: number }`. The player, with their photo and shirt number.
- `team`: `string`. The player's team, in the line under the name.
- `reason`: `"yellow" | "red" | "red20" | "blood" | "hia"`. Why the player is off: a card, or a temporary replacement.
- `clock`: `MatchClockValue | null`. The match's MatchClock value.
- `format`: `MatchFormatId | MatchFormat`. Default `"15s"`. The same format as the MatchClock. It sets the sin bin.
- `at`: `number`. Default `0`. matchPlayed(clock) when the card was shown. Cards only.
- `time`: `string`. What the clock read when it was shown, like "8:25".
- `minutes`: `number`. Minutes off, when a competition sets its own sin bin, or 17 for blood and an HIA together.
- `since`: `number`. blood and hia: when the player left, in ms since the epoch.
- `onReturn`: `() => void`. Brings them back on, or a replacement on. A person button shows once it can.
- `index`: `number`. Place in a list. Rows fade up one after another as they first show.
- `divider`: `boolean`. Default `false`. A hairline above the row, inset from the card's edges.
- `className`: `string`. Extra classes. Later classes win.

## Accessibility

- The row reads as one line: the number, the name, and the status, like "#3 Owen Price · Back in 4:12".
- Which card it is, or why they are off, is in words in the line under the name. The card mark before those words is hidden from screen readers.
- The return button is a native button named for what it does, like "Bring Owen Price back on", with the same words in its tooltip.
- A polite live region says once when the time is served, like "Owen Price: Can return". The countdown itself is not read out each second.
- Can return, Sent off, and Replacement stays are words in the tone's soft text, which the theme holds to 4.5:1. A card mark keeps a border in forced-colors mode.

## Examples

### A yellow card counting down beside the clock

```tsx
// clock is the match's MatchClock value. at and time were recorded when the card was shown.
<Card className="gap-0 px-0">
  <SuspensionRow
    player={{ person: "Owen Price", number: 3 }}
    team="Rovers"
    reason="yellow"
    at={card.at}
    time={card.time}
    clock={clock}
    format="15s"
    onReturn={() => bringBack("owen")}
  />
</Card>
```

### A blood replacement on the wall clock

```tsx
<SuspensionRow
  player={{ person: "Will Hardy", number: 1 }}
  team="Saints"
  reason="blood"
  since={leftAt}
  clock={clock}
  onReturn={() => bringBack("will")}
  divider
/>
```
