GrRating

  • core
  • forms
  • API · 17 props
  • ⌨ keys

Collect and display a star rating, with half steps and a read-only mode.

import { GrRating } from '@feugene/granularity/components/GrRating'

Overview

When to take it

  • the rating is given in one click — a review, the quality of support, the difficulty of a task;
  • the rating is fractional — allowHalf for halves;
  • an explanation is needed beside it — texts labels the steps with words: “Poor”, “Excellent”;
  • the rating is shown rather than given — readonly for the average rating in a product card.

When to take something else

NeedTake
The scale is numeric and wideGrSlider
An exact number is neededGrNumberInput
There are few options and they are namedGrRadioGroup
Show a share rather than a ratingGrProgressBar

Variants every tone and view, rendered by the real component

tone

  • primary
  • neutral
  • success
  • warning
  • danger
  • info
  • slate
  • azure

Sizes

  • xs
  • sm
  • md
  • lg

States

  • normal
  • disabled
  • readonly
  • invalid

The grid is live: hover and press it. Hover, focus and active states are not drawn here — they belong to the browser, not to a prop.

Playground controls come from the API, not from hand

Stage

Loading…

0 changed· state is in the URL

Examples 3 each with a live demo and its code

  • A review after delivery

    The rating is a radio group in disguise: arrows walk it, and clearable lets a second click on the same star take the answer back. texts names each step — «Good», not just «4» — and the word also goes into aria-valuetext.

    How was your order?Linen shirt, sand, M · delivered yesterday
    Choose a star

    Fit, fabric, colour — it helps the next buyer

    0 / 500
  • Rating a support conversation

    The symbol slot draws faces instead of stars, and filled lights up every face up to the answer while the rest stay grey. The scale stays a radio group for the keyboard, and texts still names the steps for the screen reader.

    DKChat with Daniel · closedAbout: export to CSV cuts long notes
    How did we do?
  • Average ratings in a catalogue

    Someone else’s average is not a control: readonly takes the scale out of the tab order and draws it as a picture. allow-half shows 4.5 as four and a half stars, compact drops the empty ones — in a list grey stars are noise — and show-text adds the number.

    Linen shirt, sand€64.00
    4.5
    42 reviews
    Wool cardigan, navy€129.00
    4
    18 reviews
    Canvas tote€18.00
    3.5
    7 reviews
    Silk scarf, rust€45.00
    5
    3 reviews

API generated from the package · cannot drift

Props

PropTypedefaultDescription
disabledboolean | undefinedfalseThe scale is unavailable: it stays a slider with `aria-disabled`, but leaves the tab order and does not change.
tone
"primary" | "neutral" | "success" | "warning" | "danger" | ""primary" | "neutral" | "success" | "warning" | "danger" | "info" | "slate" | "azure" | undefined
"warning"The tone of the fill; overridden pointwise by the `--gr-rating-color` variable.
iconstring | Component | undefinedundefinedA symbol instead of the built-in star: a Vue component or an icon class (`'i-lucide-heart'` — the application sets up the rule for the class: in the engine factory or through a provider, see the “Icons” section of `docs/installation.md`).
readonlyboolean | undefinedfalseDisplay only: without input and without focus.
invalidboolean | undefinedfalseThe visual and ARIA state of an error.
requiredboolean | undefinedfalseA mandatory field (`aria-required`).
size"xs" | "sm" | "md" | "lg" | undefinedundefinedThe size of the symbols and the label. Unset — from `GrConfigProvider`, otherwise `md`.
ariaLabelstring | undefinedundefinedThe accessible name of the scale: what is being rated — "Delivery quality". By default — from the locale (`Rating`).
clearableboolean | undefinedfalseA repeated click on the current score resets it to `0`.
namestring | undefinedundefinedThe name for a native form: a hidden input with the value; `0` means "not chosen", and the input is not rendered.
maxnumber | undefined5The number of symbols on the scale.
compactboolean | undefinedfalseA compact look: only the filled symbols are drawn. It makes sense together with `readonly` — in lists and tables five stars in every row eat the width.
allowHalfboolean | undefinedfalseHalf scores: a click on the left half of a symbol gives `.5`.
showTextboolean | undefinedfalseShow a numeric label to the right of the scale.

Slots

SlotTypeDescription
symbol{ index: number; filled: boolean; }A symbol of your own instead of the star. `filled` is the filled half of the symbol.
text{ value: number; }A label beside the score.

Events

EventSignatureDescription
update:modelValue(event: "update:modelValue", value: number): void—
change(event: "change", value: number): void—
clear(event: "clear"): void—
focus(event: "focus", event: FocusEvent): void—
blur(event: "blur", event: FocusEvent): void—
hoverChange(event: "hoverChange", value: number | null): void—

Methods

MethodsSignatureDescription
focus() => voidFocus the scale from code. In `readonly` the scale is a picture and does not take focus.
blur() => voidRemove the focus from the scale.

Types

Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.

Import
import type { GrRatingConfigurableProps, GrRatingProps, GrRatingEmits } from '@feugene/granularity/components/GrRating'

Filedist/types/components/GrRating/config.d.ts

grRatingConfigconst
const grRatingConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrRating">;

Filedist/types/components/GrRating/defaults.d.ts

GrRatingConfigurablePropsinterface
interface GrRatingConfigurableProps {
    size: GrRatingSize;
}

Filedist/types/components/GrRating/GrRating.vue.d.ts

GrRatingPropsinterface
interface GrRatingProps {
    modelValue: number;
    max?: number;
    size?: GrRatingSize;
    tone?: GrRatingTone;
    allowHalf?: boolean;
    readonly?: boolean;
    disabled?: boolean;
    invalid?: boolean;
    required?: boolean;
    clearable?: boolean;
    icon?: string | Component;
    showText?: boolean;
    formatText?: (value: number) => string;
GrRatingEmitsinterface
interface GrRatingEmits {
    (e: 'update:modelValue', value: number): void;
    (e: 'change', value: number): void;
    (e: 'hoverChange', value: number | null): void;
    (e: 'clear'): void;
    (e: 'focus', event: FocusEvent): void;
    (e: 'blur', event: FocusEvent): void;
}

Filedist/types/components/GrRating/grRatingStyles.d.ts

GrRatingSizetype
type GrRatingSize = GrComponentSize;
GrRatingTonetype
type GrRatingTone = GrTone;

Filedist/types/components/GrRating/safelist.d.ts

grRatingSafelistconst
const grRatingSafelist: string[];

Filedist/types/components/GrRating/index.d.ts

GrRatingInstancetype
type GrRatingInstance = ComponentExposed<typeof GrRatingComponent>;

Accessibility

APG pattern

slider (интерактивный) / img (readonly)

Keys

→ / ↑← / ↓Home / End

Usage from the library prose

The rating in words
vue
<GrRating v-model="score" :texts="['Awful', 'Poor', 'Fair', 'Good', 'Excellent']" show-text />

texts holds one label per division. The label goes both into the visible text and into aria-valuetext (“4 of 5, good”): that is the whole point of a rating — a screen reader reads the score in words rather than as a bare number. A fractional value is rounded up to its division, and an array shorter than max leaves the upper divisions without a label.

formatText is stronger than texts for the visible text — the consumer may have a wording of their own.

The preview

Hovering shows the rating under the cursor and emits hoverChange; leaving the scale and losing the focus return the model and send hoverChange(null).

The handler hangs on the scale itself rather than on the whole component: the caption lies beside the scale, and a cursor moved onto it has to put the preview out — otherwise it sticks. In readonly and disabled there is no preview at all.

There is no preview from the keyboard: the arrows commit the rating at once, and hoverChange is not emitted there.

The compact look
vue
<GrRating :model-value="3" readonly compact show-text />

compact draws only the filled symbols — for tables and lists, where five stars in every row eat up the width. A half counts as a symbol: “2.5” is drawn with three. For a screen reader the compact mode is no different — the role and the text label are the same.

The modes and accessibility

An interactive scale implements the slider pattern: role="slider", aria-valuemin/max/now/valuetext, the arrows, Home/End. The read-only mode is a role="img" with a text label, so that the rating is read as a single phrase rather than as a set of elements.

disabled dims the scale with the --gr-disabled-fg token rather than with transparency: opacity dilutes colours tuned to AA.

Styling
PointWhat it sets
sizexs…lg, read from GrConfigProvider
tonethe colour of the fill from the tone scale
--gr-rating-colorthe colour of the fill pointwise, stronger than tone
--gr-rating-void-colorthe colour of an unfilled symbol
icon / the #symbol slota symbol of your own instead of the built-in star

The default symbol is an inline SVG: the icon masks of i-lucide-star give an outline only. A symbol of your own is a Vue component or an icon class (i-lucide-* — the application sets up the rule for it: in the engine factory or through a provider, otherwise a Vue component; see “Icons”).

The native form

The name prop renders an input[type="hidden"] with the value of the rating. 0 means “not selected”: the input is not rendered, as with an unchecked radio button.