InputsReact
A row of stars that sets a rating from 1 to max (5 by default).
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<Rating.Root>
<Rating.Item />
<Rating.Value />
<Rating.Clear />
</Rating.Root>Examples
Half
step of 0.5 from 2.5: the pointer previews the half star it is over, Value shows the preview in italics, and the text under it says the value and preview.
Form
A required rating in a Field of a Form: Send without a rating shows "Choose a rating before you send.", and a rated form submits stay=4.
Read Only
readOnly at 4, focusable and submitted, and disabled at 2, out of the Tab order, each with its state in its label.
Custom
Five faces from "Very bad" to "Very good", each with its own icon and aria-label, in a column with orientation="vertical", right to left through Direction Provider.
API reference
25 props across 4 parts, in React syntax. className, style, render are listed once, under Shared props.
ClearRating.Clear
Clears the rating. Place it after Rating.Root's stars, outside the group: a Tab stop inside a radio group is skipped by arrow key users. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
focusableWhenDisabledWhether the button stays focusable while there is nothing to clear, so focus stays on it | boolean | true |
| Data attribute | Description |
|---|---|
data-disabled | Present when there is no rating to clear, or the rating is disabled or read-only. |
ItemRating.Item
One star of the rating: a radio whose name carries its value ("3 stars"), or the exact value on the checked star ("2.5 stars"). Renders a <span>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | false |
valuerequiredThe star, from 1 to max. | number | — |
disabledWhether the star cannot be chosen. | boolean | false |
| Data attribute | Description |
|---|---|
data-checked | Present when the rating's value is in this star. |
data-unchecked | Present when the rating's value is not in this star. |
data-fill | How much of the star the shown value (the preview, else the value) fills. |
data-disabled | Present when the star cannot be chosen: it or the rating is disabled, or it is below min. |
data-readonly | Present when the rating is read-only. |
data-required | Present when the rating is required. |
data-valid | Present when the rating is in a valid state (when wrapped in Field.Root). |
data-invalid | Present when the rating is in an invalid state (when wrapped in Field.Root). |
data-touched | Present when the rating has been touched (when wrapped in Field.Root). |
data-dirty | Present when the rating's value has changed (when wrapped in Field.Root). |
data-filled | Present when the rating has a value (when wrapped in Field.Root). |
data-focused | Present when a star is focused (when wrapped in Field.Root). |
data-previewing | Present while a hover preview is shown. |
| CSS variable | Description |
|---|---|
--rating-item-fill | How much of the star the shown value fills, from 0% to 100%. |
RootRating.Root
Groups the stars of a rating: a radio group with one radio per star, and the hidden input that submits the value. and a hidden <input> beside it. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valueThe rating, a multiple of step from min to max, or null for no rating. | number | null | — |
defaultValueThe rating when the component is initially rendered. | number | null | null |
onValueChangeEvent handler called when the rating changes. | ((value: number | null, eventDetails: RatingRootChangeEventDetails) => void) | — |
onPreviewValueChangeEvent handler called when the hover preview changes: the value under a mouse or pen pointer, | ((value: number | null, eventDetails: RatingRootPreviewChangeEventDetails) => void) | — |
maxThe number of stars. | number | 5 |
stepThe smallest change: 1 / n for an integer n from 1 to 10 (1, 0.5, 0.25, 0.2, 0.1). | number | 1 |
minThe smallest value that can be set. | number | — |
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to change the rating. | boolean | false |
requiredWhether the user must choose a rating before submitting a form. | boolean | false |
allowClearWhether pressing the checked star, or Space on it, clears the rating. | boolean | false |
previewOnHoverWhether a mouse or pen hovering the stars previews the value under the pointer. | boolean | true |
loopFocusWhether the arrow keys wrap from the last value to the first and back. | boolean | false |
orientationThe layout of the stars, set as aria-orientation. | Orientation | 'horizontal' |
labelsThe texts, in English by default. | Partial<RatingLabels> | — |
localeThe locale used by Intl.NumberFormat when formatting the numbers of the names. | Intl.LocalesArgument | — |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the hidden input. | string | — |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
| Data attribute | Description |
|---|---|
data-disabled | Present when the rating is disabled. |
data-readonly | Present when the rating is read-only. |
data-required | Present when the rating is required. |
data-previewing | Present while a hover preview is shown. |
data-valid | Present when the rating is in a valid state (when wrapped in Field.Root). |
data-invalid | Present when the rating is in an invalid state (when wrapped in Field.Root). |
data-touched | Present when the rating has been touched (when wrapped in Field.Root). |
data-dirty | Present when the rating's value has changed (when wrapped in Field.Root). |
data-filled | Present when the rating has a value (when wrapped in Field.Root). |
data-focused | Present when a star is focused (when wrapped in Field.Root). |
ValueRating.Value
The shown rating as visual text: "3 out of 5", or what its children function returns ("Good"). Hidden from assistive technology, since the stars' names carry the value. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
childrenThe text, or a function of the value and the hover preview (each null when there is none). | React.ReactNode | ((value: number | null, previewValue: number | null) => React.ReactNode) | — |
| Data attribute | Description |
|---|---|
data-previewing | Present while a hover preview is shown. |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| Tab | Moves into the group on the checked star, or the first star when there is no value, and checks nothing | Root |
| ArrowRightArrowDown | Raises the value by one step and moves focus to the star that holds it | Item |
| ArrowLeftArrowUp | Lowers the value by one step; in RTL ArrowRight lowers and ArrowLeft raises, the up and down stay | Item |
| ArrowUpArrowDown | With orientation="vertical": the only arrows that move; left and right do nothing | Root |
| HomeEnd | Sets the lowest value (min, step by default) or max | Item |
Stop at the first and last value; with loopFocus they wrap | Root | |
| Space | Checks the focused star; on the checked star it clears when allowClear | Item |
| 1max | Sets that whole value; 0 clears when allowClear | Item |
| Enter | Nothing: a star is not a button | Item |
| EnterSpaceClear | Clears the value with reason clear-press; focus stays on Clear | Clear |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Root | role="radiogroup", aria-orientation, aria-readonly, aria-required, aria-disabled; its name from Field.Label, aria-label or aria-labelledby | the stars are read as one choice with its name and state; a development build warns when it has no name |
| Item | role="radio", aria-checked on the star that holds the value only, aria-label "1 star", "3 stars" | the value is one checked radio among max stars |
| Item | on the checked star of a fractional value, the exact value: "2.5 stars" | the half is in the name of the focused star, not only in its fill |
| Item | aria-disabled and tabIndex -1 on a disabled star, never disabled | a disabled star stays in the group and the arrows skip it |
| Clear | a button with type="button", named "Clear rating" (labels.clear) or by its text | clearing is a control of its own, reached without a gesture on a star |
| Value | aria-hidden="true" | "3 out of 5" is not read again after the checked star |
Focus order
- The group is one Tab stop: the checked star, or the first star that is not disabled when there is no value. Nothing takes focus on mount, and Tab into the group checks nothing.
- The arrows, Home, End and the digits move focus to the star that holds the new value as they change it; a change within one star (a half step) keeps focus there.
Clearis a Tab stop of its own after the stars, focusable while disabled; after a press focus stays on it.- A read-only group keeps its Tab stop; a disabled one has none. A required, invalid group in a Form gets focus on submit, on its checked or first star.