Rating
A rating control — interactive or read-only — that scores with any icon and shows fractional values as a partial icon.
Live demo
Rating draws max icons and overlays a colored copy clipped to value / max, so a fractional value like 4.5 shows an exact partial icon rather than rounding. It renders two rows: a neutral base row (the icon silhouetted to a muted track color) and a filled row (the icon in full color) clipped to the value fraction.
Both rows are the component's fill, not markup the element hardcodes, so a mod filling component.rating can swap the star for a heart, clip the fill by mask or by count instead of by width, or restructure the row entirely — the element keeps the value, the keys, the pointer, and the ARIA either way. Any icon works: the default star, any functional glyph (heart, bolt, …), or a composed colorful mark spec (taco--…), drawn through the icon system. A monochrome glyph takes its fill from tone (a register hue), a colorful mark draws its palette from colors. By default it is an interactive slider — focusable, role="slider", driven by pointer drag, click, and Arrow/Home/End keys, with a hover preview, firing input and change and posting through a hidden input when name is set. Add readonly and it becomes a fixed role="img" display for an average score, a product rating, a survey result. The element's own text is the no-JS fallback and the accessible label. Override --rating-track (base color, defaults to --neutral-bg) or --rating-fill (fill color, defaults to --accent) per instance to retune it.
When to use
How this component composes with the rest of the set.
Props
11 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
0..max. Two-way bindable in Svelte. | ||||
star (default), any functional glyph by name (heart, bolt, …), or a composed mark spec (a -- name like taco--…) for a colorful multi-layer mark. | ||||
role="img") instead of the interactive slider. Omit it (the default) for an editable control. | ||||
allow-half; the older all-lowercase allowhalf is still read. | ||||
accent, success, red, …). Sets --rating-fill. | ||||
accents, skittles, …). | ||||
sm, md, or lg. | ||||
"{value} out of {max} stars". | ||||
readonly already opts out of. The Svelte and raw-element paths always upgrade, so they carry no equivalent. |
Events
What the component emits, and what rides along on event.detail. The name in the
first column is the one addEventListener takes.
| Event | Detail | Bindings | Description |
|---|---|---|---|
Appearance
Sizes
sm
Small icons.
md
Default.
lg
Large icons.
States
interactive
Editable (the default, readonly absent): role="slider", focusable, pointer- and key-driven, with a pointer cursor.
hover
Pointer over an interactive control: the filled row previews the value under the cursor without committing it.
focus-visible
Keyboard focus on an interactive control: a token-colored ring around the rounded control.
readonly
Non-interactive display (readonly set): a fixed role="img" with no cursor, tab stop, or events.
Anatomy
The named parts that make up the component. A ::part() handle is reachable from your own stylesheet; the class beside it is the component's internal selector, which a shadow boundary keeps to itself.
root
The control wrapper. Sizes the icons, stacks the two rows, and carries the interactive class, focus ring, and the --rating-track / --rating-fill override vars.
rows
The fill's own region, holding whatever rows it draws. Laid out as display: contents so the rows are the control's own flex children; a mod filling component.rating renders into it.
row
The base row of silhouetted icons (part="track"); sets the neutral track color (--rating-track) and the overall size. A real node the fill renders, so a mod can restructure it.
fill
The full-color copy of the row (part="fill"), clipped by width to the value fraction and laid over the base row. The element writes the hover preview to whatever node carries part="fill", so a mod that keeps the part keeps the preview.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent--border-thick--neutral-bg--radius-sm--ring--text-2xl--text-lg--text-smSlots
The no-JS fallback text, adopted as the accessible label. Give a human-readable score or prompt like 4.5 out of 5 or Rate this product.
Accessibility
Code
Interactive, read-only, and custom icons
An editable star rating, a fractional read-only score, a heart rating tinted red, a half-step control, a colorful mark drawn from a palette, a form-posting control, and a compact 10-point display.
<xtyle-rating value="3" label="Rate this product"></xtyle-rating>
<xtyle-rating value="4.5" readonly label="4.5 out of 5 stars"></xtyle-rating>
<xtyle-rating value="4" icon="heart" tone="red" label="Rate this recipe"></xtyle-rating>
<xtyle-rating value="3.5" allow-half label="Rate this stay"></xtyle-rating>
<xtyle-rating value="4" icon="crest--shield-c1--star-s45-cf" colors="skittles" label="Rate this guild"></xtyle-rating>
<form>
<xtyle-rating value="4" name="score" label="Rate this stay"></xtyle-rating>
</form>
<xtyle-rating value="7" max="10" size="sm" readonly label="7 out of 10"></xtyle-rating><script lang="ts">
import { Rating } from "@xtyle/svelte";
let score = $state(3);
</script>
<Rating bind:value={score} label="Rate this product" />
<Rating value={4.5} readonly label="4.5 out of 5 stars" />
<Rating value={4} icon="heart" tone="red" label="Rate this recipe" />
<Rating value={3.5} allowHalf label="Rate this stay" />
<Rating value={4} icon="crest--shield-c1--star-s45-cf" colors="skittles" label="Rate this guild" />
<form>
<Rating value={4} name="score" label="Rate this stay" />
</form>
<Rating value={7} max={10} size="sm" readonly label="7 out of 10" />---
import Rating from "@xtyle/astro/Rating.astro";
import { FULL_TONES } from "../vocab.js";
---
<Rating value={3} label="Rate this product" />
<Rating value={4.5} readonly label="4.5 out of 5 stars" />
<Rating value={4} icon="heart" tone="red" label="Rate this recipe" />
<Rating value={3.5} allowHalf label="Rate this stay" />
<Rating value={4} icon="crest--shield-c1--star-s45-cf" colors="skittles" label="Rate this guild" />
<form>
<Rating value={4} name="score" label="Rate this stay" />
</form>
<Rating value={7} max={10} size="sm" readonly label="7 out of 10" />