Skip to content

RatingScale

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/rating-scale.json
See it liveScored, not judged yet, a longer scale, and disabled.→

Marks rather than stars. Stars carry a meaning of their own — a review, a public verdict — and this is as often “how hard was this” or “how finished is it” as it is “how good”.

Not judged yet is a state, not a zero. This is the whole reason the component exists and the reason it is not a Slider with a small range or a RadioGroup with five options. “I have not scored this” and “I scored it nothing” are different facts, and a control that collapses them makes the difference unrecoverable the moment it saves.

<RatingScale
scale={5}
value={score} // number | undefined
onValueChange={setScore} // receives undefined when cleared
label="Difficulty"
emptyLabel="Not judged"
/>

There are two ways back to it, and both exist because losing either one loses the state:

  • the pointer — click the mark already chosen;
  • the keyboard — Backspace or Delete.

emptyLabel is required. It is what a screen reader hears in place of a number, and a default here would be English shipped inside a primitive. Same for label: a bare row of marks names nothing.

One control, not five. The container is the slider — one tab stop, arrows within it — and the marks are plain elements. A <button> per mark would be a nested interactive control inside a slider, which assistive technology is not promised to announce or reach; the donor this came from had them as aria-hidden buttons, which hides them from a reader without making them stop being controls.

Props

Read from the types in ui/rating-scale.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.

PropTypeDefault
scalerequirednumberHow many marks.
valuerequirednumberThe score, or undefined for not judged yet.
onValueChangerequired(value: number | undefined) => voidCalled with the new score by a click or a key, and with undefined when the score is taken back to not judged.
labelrequiredstringWhat is being judged. Required: a bare row of marks names nothing, and this is the only thing a screen reader has to go on.
emptyLabelrequiredstringWhat a screen reader hears in place of a number when nothing is chosen. Required rather than defaulted, because a default here would be English shipped inside a primitive.
disabledbooleanfalseStops the scale taking a click or a key.
classNamestring

Accessibility

The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 17 rules applied and passed, and none failed. The accessibility report has every item.

History

Each release that changed ui/rating-scale.tsx - the file a product copies - newest first.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.28.0
    • feat measure in steps, and name the step that was missing 8dd8a28
  3. v0.17.0
    • feat numbers, scales, and the two fields with no foundation ead7461