Match Card
betaA knockout match tile with a flat shape: the time and pitch, an FT or Live badge, and two team rows with kit, score, and the winner's caret.
Preview
before kick-off: no status, no badge
status: Live, then FT with the winner's caret
a level score with penalties reads FT (P), and the side with more kicks goes through
width={280}, and never under 240
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/match-card
Use it for
- A knockout match from data shaped as two teams, each with its own score, like a match day list.
- Pass when as the time and pitch, like "15:20 · Pitch 2".
- Pass status "FT" once it's finished, "Live 9'" while it's on, or leave it out before kick-off.
- At FT the side with the higher score gets the caret. On a level score, pass each side's penalties, and the one with more goes through.
- Pass onClick and selected to make it a match you choose.
Avoid it for
- A draw of many rounds. Use KnockoutBracket.
- A match that needs a peek with the round's name. Use BracketMatch.
- A league match that can end level. A level FT with no kicks shows no winner, which reads oddly in a cup but is right in a league, so say the result elsewhere.
Props
- when
The time and pitch, like "15:20 · Pitch 2".
string
- status
"FT", "Live 9'", or another word like "AET". Left out before kick-off. Any word but Live means it's over.
string
- home
{ name, score?, penalties?, colors?, pattern? }. colors are the kit's two colors, as KitColors.
MatchTeam
- away
The same shape as home.
MatchTeam
- selected
Draws it as the chosen match. Only a card with onClick can be chosen.
boolean · default false
- onClick
Makes the card a button that says whether it is pressed.
() => void
- width
A fixed width in px, never under 240. By default it fills its column.
number
- className
Extra classes. Later classes win.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| when | string | - | The time and pitch, like "15:20 · Pitch 2". |
| status | string | - | "FT", "Live 9'", or another word like "AET". Left out before kick-off. Any word but Live means it's over. |
| home | MatchTeam | - | { name, score?, penalties?, colors?, pattern? }. colors are the kit's two colors, as KitColors. |
| away | MatchTeam | - | The same shape as home. |
| selected | boolean | false | Draws it as the chosen match. Only a card with onClick can be chosen. |
| onClick | () => void | - | Makes the card a button that says whether it is pressed. |
| width | number | - | A fixed width in px, never under 240. By default it fills its column. |
| className | string | - | Extra classes. Later classes win. |
Accessibility
- The card names both teams and their scores, and says who won in text. The caret and the weight only show it.
- After kicks, it reads FT (P), shows each side's kicks in brackets, and says "won 4–3 on kicks".
- With onClick, it is a button with aria-pressed. A chosen card has a 2px outline that shows in forced colors.
- A Live badge says Live in words. Its red is not the only sign.
Examples
Before kick-off
<MatchCard when="15:20 · Pitch 2" home={{ name: "QF 3 winner" }} away={{ name: "QF 4 winner" }} />Finished, after kicks
<MatchCard
when="16:00 · Pitch 1"
status="FT"
home={{ name: "Hawks", score: 14, penalties: 3 }}
away={{ name: "Wolves", score: 14, penalties: 4 }}
/>Live, and chosen
<MatchCard
when="15:00 · Pitch 1"
status="Live 9'"
home={{ name: "Rovers", score: 7, colors: kit, pattern: "hoops" }}
away={{ name: "Lions", score: 0 }}
selected={selected === "final"}
onClick={() => setSelected("final")}
/>