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 subtle 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, giving immediate visual feedback before committing a selection.
The component implements a slider ARIA role with aria-valuenow, aria-valuemin, and aria-valuemax attributes, making it fully navigable 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, keeping keyboard navigation efficient 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 — useful for 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. -
formAssociatedbooleantrue -
propertiesobject{ // 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.
-
form -
validity -
validationMessage -
requiredbooleanfalse
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
- Slider Range input slider with a label, live numeric value display, accent-primary fill track, and customisable min/max/step.
- Icon Renders 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.