Rating Group

Star rating input.

Usage

Root hands you an items array through a snippet — each with an index and a state of active, partial or inactive — so the icon is yours to choose. Half-star readings are expressible through partial.

value: 3 — try the arrow keys

Always set aria-valuetext

Pass the function form: (v, max) => `${v} of ${max} stars`. Without it the rating is announced as a bare number, and "3" tells the user nothing — three out of five? out of ten? A rating is meaningless without its scale, and that is precisely what a sighted user gets for free from seeing five stars.

Root also needs a name via aria-label. Bits supplies the role and the numeric values; it cannot invent what is being rated.

It is a slider, not buttons

Bits gives Root role="slider" with the aria-value* attributes, so the arrow keys adjust the rating and the whole control is one tab stop. The items are role="presentation" — decorative, with the value living on the Root.

That is why you name and describe the Root and not each star. It is also why a hand-rolled row of clickable icons is not the same component: it looks identical and is unusable by keyboard.

Props

RatingGroup.Rootvalue is bindable.

PropTypeDefault
value Current rating. Bindable.number0
size 'sm' | 'md' | 'lg''md'
invalid Marks the control as failing validation. Always applies the invalid styling. Also sets `aria-invalid`, which this element's `slider` role supports. Prefer letting `Field` drive this: passing `Field` an `error` is what makes a field invalid, so the message the user reads and the state of the control cannot disagree.booleanfalse
class string
allowHalf bits-ui Whether to allow half-star ratings.boolean | undefinedfalse
aria-valuetext bits-ui An extended `aria-valuetext` property to use for the rating group. Can either be a string, or a function that receives the current value and max value and returns a string.RatingGroupAriaValuetext((value: number, max: number) => `${value} out of ${max}`)
child bits-ui Snippet<[RatingGroupRootSnippetProps & { props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[RatingGroupRootSnippetProps]> | undefined
disabled bits-ui Whether the rating group is disabled.boolean | undefinedfalse
hoverPreview bits-ui Whether to show a preview when hovering over rating items. Touch events are ignored to prevent accidental previews.boolean | undefinedtrue
id bits-ui string | undefined
max bits-ui The maximum rating value (number of items).number | undefined5
min bits-ui The minimum rating value.number | undefined0
name bits-ui The name to apply to the rating group's input element for form submission. If not provided, a hidden input will not be rendered and the rating group will not be part of a form.string | undefinedundefined
onValueChange bits-ui The callback to call when the rating value changes.OnChangeFn<number> | undefined
orientation bits-ui The orientation of the rating group. Used to determine how keyboard interactions work.Orientation | undefined"horizontal"
readonly bits-ui Whether the rating group is readonly.boolean | undefinedfalse
ref bits-ui HTMLElement | null | undefined
required bits-ui Whether the rating group is required for form submission. If `true`, ensure you provide a `name` prop so the hidden input is rendered.boolean | undefinedfalse

RatingGroup.Item takes index from the snippet plus class.

PropTypeDefault
class Extra classes merged onto the item.string
child bits-ui Snippet<[RatingGroupItemSnippetProps & { props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[RatingGroupItemSnippetProps]> | undefined
disabled bits-ui Whether the rating item is disabled.boolean | null | undefinedfalse
id bits-ui string | undefined
index required bits-ui The index of the rating item (0-based index).number
ref bits-ui HTMLElement | null | undefined