Rating
Primitive

Rating

Headless slider-like rating input with fractional values and decorative item parts.

Live behavior

Rating in motion

Interactive
Atom behavior · App-owned appearance
Preparing behavior…

Interact with the specimen and inspect the behavior Atom contributes.

waiting for input

When to Use

Use Rating when a person chooses a score on a small ordered scale, such as one to five stars. Use Slider when the value is a general numeric setting like volume, and use RadioGroup when each choice has a different meaning rather than simply being more or less.

Features

The behavior Atom owns before your product adds appearance.

  • Implements rating as a WAI-ARIA slider.
  • Supports controlled and uncontrolled values.
  • Supports fractional values with configurable step.
  • Supports pointer selection, drag updates, keyboard control, and opt-in clear.
  • Preserves vertical page scrolling, reverts true pointer cancellation, and finalizes the live value if pointer capture is lost.
  • Mirrors horizontal pointer and keyboard behavior in RTL direction.
  • Supports disabled, read-only, invalid, and required states.
  • Renders an optional hidden input for form submission.

Import

tsx
import { Rating } from "@flowstack-ui/atom";

Anatomy

tsx
<Rating.Root>
  <Rating.Item value={1} />
  <Rating.Item value={2} />
  <Rating.Item value={3} />
  <Rating.Item value={4} />
  <Rating.Item value={5} />
</Rating.Root>

API Reference

Root

Owns the numeric rating, form value, and slider semantics. It is the single focusable control; Item parts only provide pointer targets and visual state.

PropTypeDefault
valuenumber-
defaultValuenumbermin
onValueChange(value: number) => void-
allowClearbooleanfalse
minnumber0
maxnumber5
stepnumber1
largeStepnumbermin(step * 10, half range snapped to step)
disabledbooleanfalse
readOnlybooleanfalse
invalidbooleanfalse
requiredbooleanfalse
validationBehavior"inline" | "native"Field/Form value or "native"
dir"ltr" | "rtl"Direction context
namestring-
formValuestringCurrent value
formstring-
aria-valuetextstring-
getValueLabel(value, min, max) => string-
tabIndexnumber0
onKeyDownKeyboardEventHandler<HTMLDivElement>-
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"slider"
aria-valueminNormalized min
aria-valuemaxNormalized max
aria-valuenowCurrent snapped value
aria-valuetextExplicit or generated rating label
aria-disabledtrue when disabled
aria-readonlytrue when read-only
aria-invalidtrue when invalid
aria-requiredtrue when required
Data attributeValues
[data-slot]"rating"
[data-value]Current value
[data-min]Minimum value
[data-max]Maximum value
[data-step]Step value
[data-disabled]Present when disabled
[data-readonly]Present when read-only
[data-invalid]Present when invalid
[data-required]Present when required

Item

Represents one point on the rating scale. It reports empty, partial, or full fill state and forwards pointer interaction to Root while remaining decorative to assistive technology. Item permits vertical page scrolling while reserving horizontal movement for rating selection.

PropTypeDefault
valuenumberrequired
onPointerDownPointerEventHandler<HTMLSpanElement>-
onPointerMovePointerEventHandler<HTMLSpanElement>-
onPointerUpPointerEventHandler<HTMLSpanElement>-
onPointerCancelPointerEventHandler<HTMLSpanElement>-
onLostPointerCapturePointerEventHandler<HTMLSpanElement>-
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
aria-hiddenAlways true; Root is the single slider control
Data attributeValues
[data-slot]"rating-item"
[data-value]Item value
[data-fill]Fill percentage from 0 to 100
[data-state]"empty" | "partial" | "full"
[data-disabled]Present when disabled
[data-readonly]Present when read-only
[data-invalid]Present when invalid

Advanced compound parts can read useRatingContext or use the exported RatingContextProvider. Public helpers normalizeRatingRange, clampRatingValue, snapRatingValue, getRatingValueLabel, and getRatingItemState expose the calculations used by Root and Item.

Examples

Whole Star Rating

tsx
import { Rating } from "@flowstack-ui/atom";

export default function WholeStarRating() {
  return (
    <Rating.Root defaultValue={3} aria-label="Rating">
      {[1, 2, 3, 4, 5].map((value) => (
        <Rating.Item key={value} value={value}>Star</Rating.Item>
      ))}
    </Rating.Root>
  );
}

Fractional Rating

tsx
import { Rating } from "@flowstack-ui/atom";

export default function FractionalRating() {
  return (
    <Rating.Root
      defaultValue={4.6}
      step={0.1}
      aria-label="Rating"
      getValueLabel={(value) => `${value} stars`}
    >
      {[1, 2, 3, 4, 5].map((value) => (
        <Rating.Item key={value} value={value}>Star</Rating.Item>
      ))}
    </Rating.Root>
  );
}

Form Value

tsx
import { Rating } from "@flowstack-ui/atom";

export default function ReviewRating() {
  return (
    <form>
      <Rating.Root name="rating" defaultValue={5} aria-label="Your rating">
        {[1, 2, 3, 4, 5].map((value) => (
          <Rating.Item key={value} value={value}>Star</Rating.Item>
        ))}
      </Rating.Root>
      <button type="submit">Submit review</button>
    </form>
  );
}

Accessibility

Required validity is owned by the aligned native proxy and means a value above the minimum. A validation attempt is mirrored to the visible slider and Field. Inline behavior suppresses the browser bubble; native behavior keeps it.

Rating follows the WAI-ARIA slider pattern so the whole control is one Tab stop. Items are decorative and hidden from assistive technology. Provide an accessible name on Root with aria-label or aria-labelledby. Inside Field, Rating inherits the generated control ID, accessible name, description relationships, and state unless a local prop is supplied. Uncontrolled value returns to defaultValue on native form reset. When required, a transparent native proxy aligned with Root treats the minimum value as empty and redirects browser validation focus to the visible slider. The optional named hidden input remains submission-only. True pointer cancellation restores the value present at pointer down. Lost pointer capture finalizes the current value because browsers can release capture during a valid interaction. Activating the selected segment remains stable unless allowClear is enabled. Only one pointer session can control a Rating at a time.

KeyDescription
ArrowRight / ArrowUpIncreases value by step; ArrowRight decreases in RTL.
ArrowLeft / ArrowDownDecreases value by step; ArrowLeft increases in RTL.
PageUpIncreases value by largeStep.
PageDownDecreases value by largeStep.
HomeMoves value to min.
EndMoves value to max.

Changelog

Unreleased

0.24.0

  • Added public Agent Knowledge for component selection, required composition, recurring mistakes, and validation.

0.19.6

  • Resolved drag coordinates against the nearest Rating Item so a captured pointer can move continuously across the complete scale, including gaps and RTL layouts.

0.19.5

  • Kept repeated activation on the selected value stable by default and added opt-in allowClear behavior, including fractional values.
  • Finalized the live Rating value when pointer capture is lost; true pointercancel still restores the pointer-down value.

0.19.3

  • Preserved vertical page scrolling, limited Rating to one active pointer, and restored the pointer-down value when interaction is cancelled or capture is lost.

0.6.16

  • Explicitly scrolled inline validation-directed focus into view.

0.6.15

  • Exposed inline validation-directed focus through [data-focus-visible] until blur.

0.6.13

  • Mirrored aligned required validity to Rating, Field, and Form under the shared inline/native validation contract.

0.6.12

  • Added aligned native required validation that treats the minimum rating as empty and redirects browser focus to Root.

0.5.0

  • Added Field state, generated ID, label, and description integration plus uncontrolled form reset behavior.

0.2.0

  • Added direction-aware Rating pointer and keyboard behavior for RTL contexts.
  • Improved fractional Rating pointer selection so pointer down can select half-step values directly.
  • Reduced Rating.Item callback churn by destructuring context dependencies while preserving pointer and clear behavior.

0.1.0

  • Initial Atom release.