Rating
Displays a star rating that allows users to view and set ratings.
First release: 1.0.0 Latest update: July 1, 2025 Current version: 1.0.0
Import
import { PlusRating } from '@plusui/react';import { PlusRatingComponent } from '@plusui/angular';import { PlusRating } from '@plusui/vue';import PlusRating from '@plusui/svelte';<script src="https://cdn.jsdelivr.net/npm/@plusui/core"></script>Package
@plusui/react@plusui/angular@plusui/vue@plusui/svelte@plusui/coreDocs
Changelog
Rating Changelog
Recent changes and updates for the rating component
v1.0.0
Added Rating component for star ratings
- Customizable star count
- Half-star precision support
- Read-only and interactive modes
- Custom icons support
- Accessibility with ARIA attributes
The Rating component allows users to view or interactively select a rating, typically represented by stars. It supports different sizes, fractional steps, form validation, readonly/disabled states, label/description slots, and custom symbols.
Anatomy
Section titled “Anatomy”
Basic Example
Section titled “Basic Example”A simple rating component allowing users to select a value.
import { PlusRating } from '@plusui/react';import { useState } from 'react';
export default () => { const [rating, setRating] = useState(3);
const handleChange = (event: any) => { setRating(event.detail.value); };
return <PlusRating value={rating} onPlusChange={handleChange} />;};import { Component } from '@angular/core';
@Component({ selector: 'app-rating-basic', template: ` <plus-rating [value]="rating" (plus-change)="handleChange($event)"></plus-rating> <p>Current rating: {{ rating }}</p> `})export class RatingBasicComponent { rating = 3;
handleChange(event: any) { this.rating = event.detail.value; }}<template> <plus-rating :value="rating" @plus-change="handleChange"></plus-rating> <p>Current rating: {{ rating }}</p></template>
<script setup>import { ref } from 'vue';
const rating = ref(3);
const handleChange = (event) => { rating.value = event.detail.value;};</script><script> let rating = 3;
function handleChange(event) { rating = event.detail.value; }</script>
<plus-rating value={rating} on:plus-change={handleChange}></plus-rating><p>Current rating: {rating}</p>Use the size prop to control the rating item size.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating size="sm" value="3"> </PlusRating> <PlusRating size="md" value="3"> </PlusRating> <PlusRating size="lg" value="3"> </PlusRating> <PlusRating size="xl" value="3"> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating size="sm" value="3"> </plus-rating> <plus-rating size="md" value="3"> </plus-rating> <plus-rating size="lg" value="3"> </plus-rating> <plus-rating size="xl" value="3"> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating size="sm" value="3"> </plus-rating> <plus-rating size="md" value="3"> </plus-rating> <plus-rating size="lg" value="3"> </plus-rating> <plus-rating size="xl" value="3"> </plus-rating></template><plus-rating size="sm" value="3"></plus-rating><plus-rating size="md" value="3"></plus-rating><plus-rating size="lg" value="3"></plus-rating><plus-rating size="xl" value="3"></plus-rating><plus-rating size="sm" value="3"></plus-rating><plus-rating size="md" value="3"></plus-rating><plus-rating size="lg" value="3"></plus-rating><plus-rating size="xl" value="3"></plus-rating>Fractional Steps
Section titled “Fractional Steps”The step prop allows fractional ratings. The older precision prop is still supported as an alias.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating value="3.5" step="0.5"> </PlusRating> <PlusRating value="2.7" step="0.1"> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating value="3.5" step="0.5"> </plus-rating> <plus-rating value="2.7" step="0.1"> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating value="3.5" step="0.5"> </plus-rating> <plus-rating value="2.7" step="0.1"> </plus-rating></template><plus-rating value="3.5" step="0.5"></plus-rating><plus-rating value="2.7" step="0.1"></plus-rating><plus-rating value="3.5" step="0.5"></plus-rating><plus-rating value="2.7" step="0.1"></plus-rating>Max Value
Section titled “Max Value”Use the max prop to set the maximum number of rating items.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating value="7" max="10"> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating value="7" max="10"> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating value="7" max="10"> </plus-rating></template><plus-rating value="7" max="10"></plus-rating><plus-rating value="7" max="10"></plus-rating>Readonly & Disabled
Section titled “Readonly & Disabled”Set readonly to display a rating without allowing changes, or disabled to make it visually disabled and non-interactive.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating value="4" readonly> </PlusRating> <PlusRating value="2" disabled> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating value="4" readonly> </plus-rating> <plus-rating value="2" disabled> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating value="4" readonly> </plus-rating> <plus-rating value="2" disabled> </plus-rating></template><plus-rating value="4" readonly></plus-rating><plus-rating value="2" disabled></plus-rating><plus-rating value="4" readonly></plus-rating><plus-rating value="2" disabled></plus-rating>Custom Icons
Section titled “Custom Icons”Use empty-icon-name and filled-icon-name to specify different icons.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating value="3" empty-iconName="heart" empty-iconStyle="regular" filled-iconName="heart" filled-iconStyle="solid"> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating value="3" empty-icon-name="heart" empty-icon-style="regular" filled-icon-name="heart" filled-icon-style="solid"> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating value="3" empty-icon-name="heart" empty-icon-style="regular" filled-icon-name="heart" filled-icon-style="solid"> </plus-rating></template><plus-rating value="3" empty-icon-name="heart" empty-icon-style="regular" filled-icon-name="heart" filled-icon-style="solid"></plus-rating><plus-rating value="3" empty-icon-name="heart" empty-icon-style="regular" filled-icon-name="heart" filled-icon-style="solid"></plus-rating>Custom Symbols
Section titled “Custom Symbols”Use the symbolFormatter property when each symbol needs custom trusted HTML.
Label and Description
Section titled “Label and Description”Use label and description props to add context. Use the matching slots when the content needs markup. The older caption prop remains supported as an alias for description.
import { PlusRating } from '@plusui/react';
export default () => { return ( <> <PlusRating value="4" label="Product Rating" description="Based on user reviews"> </PlusRating> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <plus-rating value="4" label="Product Rating" description="Based on user reviews"> </plus-rating> `})export class ExampleComponent {}<template> <plus-rating value="4" label="Product Rating" description="Based on user reviews"> </plus-rating></template><plus-rating value="4" label="Product Rating" description="Based on user reviews"></plus-rating><plus-rating value="4" label="Product Rating" description="Based on user reviews"></plus-rating>Validation
Section titled “Validation”Set required and name to use the rating in a native form. The component supports form reset, native input/change events, and setCustomValidity().
import { PlusRating, PlusButton } from '@plusui/react';
export default () => { return ( <> <form action="about:blank" method="get" target="_blank"> <PlusRating name="score" label="Your rating" required> </PlusRating> <PlusButton type="submit" kind="filled"> Submit </PlusButton> <PlusButton type="reset"> Reset </PlusButton> </form> </> );};import { Component } from '@angular/core';
@Component({ selector: 'app-example', template: ` <form action="about:blank" method="get" target="_blank"> <plus-rating name="score" label="Your rating" required> </plus-rating> <plus-button type="submit" kind="filled"> Submit </plus-button> <plus-button type="reset"> Reset </plus-button> </form> `})export class ExampleComponent {}<template> <form action="about:blank" method="get" target="_blank"> <plus-rating name="score" label="Your rating" required> </plus-rating> <plus-button type="submit" kind="filled"> Submit </plus-button> <plus-button type="reset"> Reset </plus-button> </form></template><form action="about:blank" method="get" target="_blank"> <plus-rating name="score" label="Your rating" required> </plus-rating> <plus-button type="submit" kind="filled"> Submit </plus-button> <plus-button type="reset"> Reset </plus-button></form><form action="about:blank" method="get" target="_blank"> <plus-rating name="score" label="Your rating" required> </plus-rating> <plus-button type="submit" kind="filled"> Submit </plus-button> <plus-button type="reset"> Reset </plus-button></form>Handling Events
Section titled “Handling Events”Listen to rating changes and hover events for interactive feedback.
import { PlusRating } from '@plusui/react';import { useState } from 'react';
export default () => { const [rating, setRating] = useState(3);
const handleChange = (event: any) => { setRating(event.detail.value); console.log('Rating changed to:', event.detail.value); };
const handleHover = (event: any) => { console.log('Hover event:', event.detail.phase, 'value:', event.detail.value); };
return ( <PlusRating value={rating} onPlusChange={handleChange} onPlusHover={handleHover} /> );};import { Component } from '@angular/core';
@Component({ selector: 'app-rating-events', template: ` <plus-rating [value]="rating" (plus-change)="handleChange($event)" (plus-hover)="handleHover($event)" ></plus-rating> `})export class RatingEventsComponent { rating = 3;
handleChange(event: any) { this.rating = event.detail.value; console.log('Rating changed to:', event.detail.value); }
handleHover(event: any) { console.log('Hover event:', event.detail.phase, 'value:', event.detail.value); }}<template> <plus-rating :value="rating" @plus-change="handleChange" @plus-hover="handleHover" ></plus-rating></template>
<script setup>import { ref } from 'vue';
const rating = ref(3);
const handleChange = (event) => { rating.value = event.detail.value; console.log('Rating changed to:', event.detail.value);};
const handleHover = (event) => { console.log('Hover event:', event.detail.phase, 'value:', event.detail.value);};</script><script> let rating = 3;
function handleChange(event) { rating = event.detail.value; console.log('Rating changed to:', event.detail.value); }
function handleHover(event) { console.log('Hover event:', event.detail.phase, 'value:', event.detail.value); }</script>
<plus-rating value={rating} on:plus-change={handleChange} on:plus-hover={handleHover}></plus-rating><plus-rating value="3" id="event-rating"></plus-rating>
<script> const rating = document.getElementById('event-rating');
rating.addEventListener('plus-change', (event) => { console.log('Rating changed to:', event.detail.value); });
rating.addEventListener('plus-hover', (event) => { console.log('Hover event:', event.detail.phase, 'value:', event.detail.value); });</script>Visual Sections
Section titled “Visual Sections”Layout & Spacing
Section titled “Layout & Spacing”
Light & Dark Mode
Section titled “Light & Dark Mode”
Accessibility (a11y)
Section titled “Accessibility (a11y)”- Keyboard Behavior:
- The rating component is focusable (
Tab). - When focused,
ArrowLeft/ArrowDowndecreases the rating bystep. ArrowRight/ArrowUpincreases the rating bystep.Homesets the rating to 0.Endsets the rating tomax.PageUpandPageDownmove the value by 10% of the scale or at least one step.
- The rating component is focusable (
- Screen Reader:
- The component uses
role="slider". aria-valuemin="0",aria-valuemax, andaria-valuenowreflect the rating state.aria-labeloraria-labelledbyprovides the accessible name (useslabelprop if provided).aria-describedbypoints to the caption if present.aria-readonlyandaria-disabledreflect the respective states.aria-valuetextprovides a human-readable version of the current value (e.g., “3 out of 5 stars”).aria-requiredindicates if the rating is mandatory.aria-invalidindicates an error state (e.g., if required but no value set).
- The component uses
- Required Developer Actions:
- Provide a
labelprop or ensure an external label is associated viaaria-labelledbyfor context. - If used in a form and required, set the
requiredprop.
- Provide a
API Reference
Section titled “API Reference”Properties
Section titled “Properties”| Name | Type | Default | Description | Required |
|---|---|---|---|---|
value | number | 0 | The current rating value. | No |
max | number | 5 | The maximum rating value (number of items). | No |
step | number | 1 | The value step (e.g., 1 for full stars, 0.5 for half stars). | No |
precision | number | 1 | Backward-compatible alias for step. | No |
readonly | boolean | false | Makes the rating display-only, preventing user interaction. | No |
disabled | boolean | false | Disables the rating component entirely. | No |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Size of the rating items. | No |
name | string | undefined | Name attribute, potentially for form integration. | No |
emptyIconName | string | 'star' | The icon name to use for empty rating items. | No |
emptyIconStyle | 'solid' | 'regular' | 'light' | 'regular' | The icon style to use for empty rating items. | No |
filledIconName | string | 'star' | The icon name to use for filled rating items. | No |
filledIconStyle | 'solid' | 'regular' | 'light' | 'solid' | The icon style to use for filled rating items. | No |
symbolFormatter | (value: number, selected: boolean) => string | undefined | Returns trusted custom HTML for each symbol layer. | No |
label | string | undefined | An accessible label for the rating component. | No |
description | string | undefined | Optional descriptive text displayed below the rating. | No |
caption | string | undefined | Backward-compatible alias for description. | No |
required | boolean | false | Indicates if a rating value is required. | No |
Events
Section titled “Events”| Name | Payload Type | Description |
|---|---|---|
plus-input | CustomEvent<{ value: number }> | Fired when pointer or keyboard input changes the value. |
plus-change | CustomEvent<{ value: number }> | Fired when the rating value changes via user interaction. |
plus-hover | CustomEvent<{ phase: string, value: number }> | Fired when pointer hover previews a value (phase: move/end). |
plus-focus | CustomEvent<void> | Fired when the rating receives focus. |
plus-blur | CustomEvent<void> | Fired when the rating loses focus. |
| Name | Description |
|---|---|
label | Label content. |
description | Description content. |
CSS Shadow Parts
Section titled “CSS Shadow Parts”| Name | Description |
|---|---|
label | The rating label. |
description | The rating description or validation message. |
rating | The focusable rating control. |
symbol | Individual rating symbol. |
symbol-selected | Selected overlay for each symbol. |
symbol-unselected | Unselected symbol layer. |
CSS Custom Properties
Section titled “CSS Custom Properties”| Name | Default Value | Description |
|---|---|---|
--rating-active-color | var(--plus-color-text-primary) | Color of active/selected symbols. |
--rating-inactive-color | var(--plus-color-text-caption) | Color of inactive/empty symbols. |
--rating-focus-ring | var(--plus-color-border-ring) | Focus ring color. |
Join the Community
Plus UI is built by the community. Join us on our platforms to contribute, get help, and stay up to date.