Skip to content

Rating component

Rating is a star rating you can set or only show. Set, it is a slider you can click, tap or use with the arrow keys; shown, it is an image that reads "4.5 out of 5". It takes whole or half stars, 1 to 10 of them, your own icon, and it joins an oks-ui Form like any other field.

Forms19 propsAccessibility notes

Playground

Change a prop on the right and the preview updates. Switch to Code to copy what you see.

Setting a rating

Rating works uncontrolled with defaultValue, or controlled with value and onChange. The value is a number from 0 (no rating) to max. Give it a label, or an aria-label when there is no visible label, because the control needs a name.

<Rating aria-label="Quality" defaultValue={3} onChange={(v) => console.log(v)} />

const [stars, setStars] = useState(0);
<Rating label="How was it?" value={stars} onChange={setStars} precision={0.5} allowClear showValue />

Showing an average

isReadOnly turns the control into a picture: it is not focusable and is announced as an image ("4.5 out of 5"). With precision 0.5 the last star can be half filled, so an average of 4.5 shows as 4.5 stars.

<Rating isReadOnly value={4.5} precision={0.5} aria-label="Average rating" />

Inside a Form

With a name, Rating registers with the surrounding Form and is stored as a number, or null when there is no rating, so a required rule means "has a rating". Outside a Form the name becomes a hidden input for a native form post.

<Form onSubmit={save}>
  <Rating label="Score" name="score" validation={{ rules: { required: true } }} />
</Form>

Your own icon

icon and emptyIcon replace the star. Draw the icon with currentColor so the color prop still works. Without an emptyIcon the filled icon is shown in a muted colour for the empty ones.

<Rating aria-label="Love" icon={<HeartIcon />} color="danger" />

Props

The full public API for Rating. Every prop is stable and intentionally typed.

Data

value / defaultValue

number

default: 0

The rating, 0 (none) to max. value makes it controlled.

onChange

(value: number) => void

default: —

Called with the new rating (0 when cleared).

max

number

default: 5

How many icons, 1 to 10.

precision

1 | 0.5

default: 1

Whole or half steps. With 0.5 the left half of an icon is a half.

name

string

default: —

In a Form: the key it is stored under (null for no rating, so required means has a rating). Outside one: a hidden input for a native form.

validation

FieldValidation

default: —

Rules when inside a Form.

Appearance

size

"sm" | "md" | "lg"

default: md

Icon size (18, 24 and 32 px).

color

"default" | "primary" | "secondary" | "info" | "success" | "warning" | "danger"

default: warning

Colour of the filled icons.

icon / emptyIcon

ReactNode

default: a star

The filled and the empty icon. Without emptyIcon the filled one is drawn in a muted colour.

classNames

Partial<Record<slot, string>>

default: —

Class per part: base, label, control, star, icon, valueText, description, error.

Behavior & states

isReadOnly

boolean

default: false

Shows the rating; announced as an image.

isDisabled

boolean

default: false

Dimmed, not focusable, ignores input.

allowClear

boolean

default: false

Choosing the current rating again clears it; Delete, Backspace and 0 clear from the keyboard.

onHoverChange

(value: number | null) => void

default: —

The rating under a mouse pointer (a touch has no hover), null when it leaves.

Content

showValue

boolean

default: false

Shows the number beside the icons.

getValueText

(value, max) => string

default: "4 out of 5"

The spoken value; use it to translate.

label / description

ReactNode

default: —

A visible label (it names the control) and help text.

error

ReactNode | boolean

default: form's error for name

An error message, or true for the invalid look.

aria-label

string

default: —

Needed when there is no label.

Accessibility

  • Editable, it is role="slider" with aria-valuemin 0, aria-valuemax, aria-valuenow and aria-valuetext ("3 out of 5"), with one tab stop. getValueText changes the spoken text, for translation.
  • Keys: Arrow keys move one step (swapped in right-to-left pages), PageUp and PageDown move a whole icon, Home and End go to the ends, a digit goes to that rating, and Delete, Backspace or 0 clear it when allowClear is on.
  • Read-only, it is role="img" named "4.5 out of 5" and is not focusable.
  • The hover preview is for a mouse only. A touch rates on tap and the page still scrolls. Filled and empty icons differ by more than colour, and forced-colors mode uses system colours.

Best practices

  • Always give it a label or aria-label; a bare row of stars has no name for a screen reader.
  • Use allowClear when "no rating" is a valid answer, otherwise the keyboard cannot go below one step.
  • Show averages with isReadOnly and precision 0.5, and put the number next to them (showValue) so the exact figure is not left to the reader's eye.
  • Do not use a rating where a reader needs to compare many items precisely; ask for a number or a choice instead.