Line Score
betaA baseball line score: each team's runs by inning on number plates, then lit runs, hits, and errors, with the half-inning in play marked.
Preview
A run scores in the half-inning in play, and the total rolls
| Inning 1 | Inning 2 | Inning 3 | Inning 4 | Inning 5 | Inning 6 | Inning 7 | Inning 8 | Inning 9 | R | H | E | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Harbor | 0 | 1 | 0 | 0 | no score | no score | no score | no score | no score | 1 | 4 | 1 |
| Rivers | 1 | 0 | 2 | 0 | no score | no score | no score | no score | no score | 3 | 3 | 0 |
A finished game, with "X" for the half the home side did not bat
| Inning 1 | Inning 2 | Inning 3 | Inning 4 | Inning 5 | Inning 6 | Inning 7 | Inning 8 | Inning 9 | R | H | E | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Harbor | 0 | 1 | 0 | 0 | 2 | 0 | 0 | 1 | 0 | 4 | 9 | 1 |
| Rivers | 1 | 0 | 2 | 1 | 0 | 0 | 1 | 0 | X | 5 | 8 | 0 |
Extra innings add columns, and the innings scroll in a narrow space
| Inning 1 | Inning 2 | Inning 3 | Inning 4 | Inning 5 | Inning 6 | Inning 7 | Inning 8 | Inning 9 | Inning 10 | Inning 11 | R | H | E | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Harbor | 0 | 1 | 0 | 0 | 2 | 0 | 0 | 1 | 0 | 0 | 1 | 5 | 11 | 1 |
| Rivers | 1 | 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | no score | 4 | 10 | 2 |
On a dark green board, with --line-score-surface set to match
| Inning 1 | Inning 2 | Inning 3 | Inning 4 | Inning 5 | Inning 6 | Inning 7 | Inning 8 | Inning 9 | R | H | E | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Harbor | 0 | 1 | 0 | 0 | no score | no score | no score | no score | no score | 1 | 4 | 1 |
| Rivers | 1 | 0 | 2 | 0 | no score | no score | no score | no score | no score | 3 | 3 | 0 |
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/line-score
Use it for
- The top of a baseball scoreboard, a game page, or a game card that needs every inning.
- Pass each team's runs by inning. Leave an inning out until it starts, and its plate stays empty.
- Pass "X" for a half that was never played, like the home side's last when it already leads.
- Pass inning while the game is on, like { number: 5, half: "top" }. Its plate is outlined and the caption says "Top of the 5th".
- Leave inning out once the game is over, and pass status, like "Final".
- Runs total themselves. Hits and errors come from your data.
- On a surface other than a card, set --line-score-surface to its color, so the team names cover the innings as they scroll.
Avoid it for
- A game with no innings, like football or rugby. Use MatchCard.
- Only the final score. Print it, or use MatchCard.
- More than two teams. A line score is one game.
Props
- away
The visitors, who bat first: { name, short?, runs, hits?, errors? }. runs is (number | "X")[], by inning.
LineScoreTeam
- home
The home side, who bat in the bottom of each inning. The same shape as away.
LineScoreTeam
- innings
How many innings the game is scheduled for. Extra innings add columns.
number · default 9
- inning
The half-inning being played now. Leave it out before the game and once it is over.
{ number: number; half: "top" | "bottom" }
- status
A word for the game's state when no inning is in play, like "Final" or "Rain delay".
string
- caption
The table's name.
string · default "Line score"
- className
Extra classes on the outer div, which holds the container query. Later classes win.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| away | LineScoreTeam | - | The visitors, who bat first: { name, short?, runs, hits?, errors? }. runs is (number | "X")[], by inning. |
| home | LineScoreTeam | - | The home side, who bat in the bottom of each inning. The same shape as away. |
| innings | number | 9 | How many innings the game is scheduled for. Extra innings add columns. |
| inning | { number: number; half: "top" | "bottom" } | - | The half-inning being played now. Leave it out before the game and once it is over. |
| status | string | - | A word for the game's state when no inning is in play, like "Final" or "Rain delay". |
| caption | string | "Line score" | The table's name. |
| className | string | - | Extra classes on the outer div, which holds the container query. Later classes win. |
Accessibility
- It is a table with a caption. Each team is a row header, and each inning, R, H, and E is a column header.
- Screen readers hear "Inning 5", not just "5", and Runs, Hits, and Errors in full.
- On a narrow board the short name shows, and screen readers still hear the full one.
- The half in play is outlined, and the caption says it in words, like "Top of the 5th". The outline still shows in forced colors.
- An inning that has not started reads "no score".
- One polite line says each scoring change once, like "Rivers score 2 runs in the 4th. Harbor 1, Rivers 5." Never on load, and never for a pitch.
- The innings take a Tab stop only when they scroll sideways, so a keyboard can scroll them too. Then they are a region named by the caption.
- Runs, hits, and errors roll to each new value. Reduced motion and motion off jump straight there.
Examples
A game in the bottom of the 4th
<LineScore
away={{ name: "Harbor", short: "HAR", runs: [0, 1, 0, 0], hits: 4, errors: 1 }}
home={{ name: "Rivers", short: "RIV", runs: [1, 0, 2], hits: 3 }}
inning={{ number: 4, half: "bottom" }}
/>A finished game where the home side did not bat in the 9th
<LineScore
away={{ name: "Harbor", runs: [0, 1, 0, 0, 2, 0, 0, 1, 0], hits: 9, errors: 1 }}
home={{ name: "Rivers", runs: [1, 0, 2, 1, 0, 0, 1, 0, "X"], hits: 8 }}
status="Final"
/>On a dark board of your own
<div className="dark bg-success-soft p-4 text-foreground [--line-score-surface:var(--success-soft)]">
<LineScore away={away} home={home} inning={inning} />
</div>