Match
Compact saved-preference match indicator.
Quick Preview
Usage
import { Match } from "@giddaa-housing/ui/match";
// Read-only: no handler, so no button and no chevron.
<Match value={95} variant="bar" />
// Interactive: opens a breakdown, so it renders as a button with a chevron.
<Match value={95} variant="donut" onClick={openBreakdown} />
<Match value={95} variant="donut" size="lg" />
<Match value={95} size={{ base: "sm", md: "md", lg: "lg" }} />Examples
Sizes
Use sm in dense rows, md for the standard control, and lg where the match score needs more emphasis. Both visualisation variants scale as one unit.
Read-only
A score with nothing behind it is not a control. Leave onClick off and Match
renders as a span with role="img" and no chevron — same geometry, no button
semantics, nothing for the keyboard to land on. Set readOnly to force either
side of that: readOnly keeps the static presentation even with a handler
attached, and readOnly={false} keeps the button for a root driven by something
other than onClick.
Above: no onClick, so the score renders as a static image with no chevron. Below: the same score with a handler.
Types
Use bar in dense list rows. Use donut in cards or standalone tiles where the score needs more visual emphasis.
Bar Chart
Best for list rows and dense scrollable surfaces where many properties stack.
40% MatchDonut Chart
Best for cards and standalone tiles where the match score deserves visual emphasis.
75% MatchProps
| Prop/API | Type | Default | Description |
|---|---|---|---|
value | number | - | Match score clamped to 0-100 and rounded. |
variant | "bar" | "donut" | "bar" | Visualisation style. |
size | "sm" | "md" | "lg" | { base, md?, lg? } | "md" | Scales the control, text, visualisation, and chevron together. Responsive values are mobile-first; missing breakpoints inherit the previous value. Inherits from SizeProvider. |
label | string | "Match" | Text rendered after the percentage. |
readOnly | boolean | inferred | Forces the read-only presentation on or off. Unset, the score is read-only unless it has an onClick. |
showChevron | boolean | interactive | Shows the flyout affordance chevron. Defaults to on for a button, off for a read-only score. |
className | string | - | Local layout or spacing overrides. |
onClick | MouseEventHandler | - | Opens the breakdown. Its presence is what makes the score a button. |
| native props | React HTML props | - | Passed through to the root button or span. |
Accessibility
- The root is a button only when there is a flyout to open. Without
onClickit is aspanwithrole="img", which keeps a static score out of the tab order and off the list of controls a reader is offered. - Both roots announce the same string —
"95% Match"— so the read-only form loses nothing but the affordance. - Provide
aria-labelwhen the visible label is not enough for the surrounding context. - Do not communicate the score with color alone; both variants render the percentage text.