Rating
A star-based rating input with hover preview, keyboard navigation, filled/unfilled SVG stars, and configurable max value.
<arc-rating>Overview
Rating renders a row of interactive SVG stars that let users select a numeric score from 1 to a configurable maximum. Filled stars display in accent-primary with a drop-shadow glow, while unfilled stars appear as outlined shapes in the default border color. As the user hovers over stars, a preview highlight scales up the hovered star and fills all stars up to that position, which previews the score before the user commits.
The component implements a slider ARIA role with aria-valuenow, aria-valuemin, and aria-valuemax attributes, so it works with arrow keys, Home, and End. Arrow right/up increments the value, arrow left/down decrements it, and Home/End jump to the minimum (1) and maximum values respectively. The entire star group is a single tab stop, which keeps keyboard navigation short within forms.
Rating supports both disabled and readonly modes. Disabled reduces opacity to 40% and blocks all interaction, while readonly blocks interaction but maintains full visual fidelity, which suits displaying existing ratings without allowing changes. The component fires arc-change with the selected value whenever the user clicks a star or navigates with the keyboard.
Guidelines
When to use
- Use Rating for collecting subjective scores like product reviews, satisfaction, or difficulty levels
- Set `readonly` when displaying an existing rating that the user should not change
- Pair Rating with a numeric label or text description (e.g. "4 out of 5") for added clarity
- Use the default `max="5"` for most use cases: it is the most universally understood scale
- Listen to `arc-change` to update your form state or submit the rating value
When not to use
- Do not use Rating for binary choices; use Toggle or Checkbox instead
- Do not set `max` higher than 10: too many stars become hard to distinguish at a glance
- Do not use Rating for precise numeric input; use Slider or NumberInput for exact values
- Do not rely on color alone to distinguish filled and unfilled states: the SVG fill style also differs
- Avoid placing Rating components too close together without labels: users may confuse which rating applies to which item
Features
- Filled stars in accent-primary with `drop-shadow` glow; unfilled stars rendered as outlined SVG paths
- Hover preview: stars scale up to 1.15x and fill with accent color up to the hovered position
- Configurable `max` prop to support rating scales beyond the default 5 stars
- ARIA `slider` role with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` for screen readers
- Full keyboard navigation: Arrow keys step the value, Home/End jump to min/max
- Separate `disabled` (dimmed, no interaction) and `readonly` (full appearance, no interaction) modes
- Single tab stop for the entire star group, with internal arrow-key navigation
- Fires `arc-change` on click or keyboard selection with `{ value }` in the event detail
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available. Use the Web Component directly or a framework wrapper.
<arc-rating value="3" max="5"></arc-rating>import { Rating } from '@arclux/arc-ui-react';
export default function Example() {
return (
<Rating value={3} max={5} />
);
}<script setup>
import { Rating } from '@arclux/arc-ui-vue';
</script>
<template>
<Rating :value="3" :max="5" />
</template><script>
import { Rating } from '@arclux/arc-ui-svelte';
</script>
<Rating value={3} max={5} />import { Component } from '@angular/core';
import { Rating } from '@arclux/arc-ui-angular';
@Component({
imports: [Rating],
template: `
<arc-rating [value]="3" [max]="5"></arc-rating>
`,
})
export class MyComponent {}import { Rating } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<Rating value={3} max={5} />
);
}import { Rating } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<Rating value={3} max={5} />
);
}API
namestring''labelstring''- Accessible name for the control. Several ratings on one page are indistinguishable without it. Defaults to "Rating".
disabledbooleanfalse- Disables interaction, reducing opacity to 40% and blocking pointer events.
valuenumber0- Current rating value, 0 to
max. **0 means unrated**; it is a legal state of the control, not a rating of zero: it submits nothing, announces as "No rating", and is what Home and a left-arrow at the first star return to. Clicking the star that is already selected also clears back to it. Reflected as an attribute and updated on user interaction. maxnumber5- Maximum number of stars to render. Determines the upper bound of the rating scale.
readonlybooleanfalse- Prevents interaction while maintaining full visual appearance. Useful for displaying existing ratings.
size'sm' | 'md' | 'lg''md'- Control size.
mdis the default;smandlgscale the star glyphs. formAssociatedbooleantruepropertiesobject{ // flag(), unlike `disabled`. The exclusion in props.js is specifically // about form-associated *platform* semantics: a `disabled` content // attribute that is merely present makes the element actually disabled // per the HTML spec, and formDisabledCallback assigns the property back, // so no converter can win. Neither of these is platform-mapped: // `required` is enforced by _computeValidity() below and `readonly` by // each component's own interaction handlers, so the stock converter buys // nothing here and costs the usual bug: `required="false"` read as true, // blocking submission of a form the author meant to leave optional. // Finding #48's shape, across all 26 form controls at once. required: flag(false), readonly: flag(false), }- Lit merges static properties up the prototype chain, so every consumer
gets these without declaring them.
requiredparticipates in constraint validation below;readonlyreflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state). autoValidatesbooleantrue- Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
formvalidityvalidationMessagerequiredbooleanfalse
Methods
checkValidity()boolean- Whether the control currently satisfies its constraints, per the native
constraint-validation API. Fires
invalidon the element when it does not, and reports nothing to the user. reportValidity()boolean- As checkValidity(), but also shows the browser's validation message against the control when it fails.
Events
arc-changedetail:{ value: number }- Fired when the rating value changes
See Also
- SliderRange input slider with a label, live numeric value display, accent-primary fill track, and customisable min/max/step.
- IconRenders icons by name from any registered library. Phosphor (1,500+) and Lucide (1,900+) ship in `@arclux/arc-ui-icons`, with one-line library switching and custom icon registration.