Rating
Tier C. Follows the anatomy template and the conventions.
1. Purpose and native element
Section titled “1. Purpose and native element”A score out of a small maximum (5 by default), shown as stars. Two forms:
- Input: native radios in a
<fieldset>named by its<legend>, one per score, each named “1 star”, “2 stars” and so on. Each radio is visually hidden over its star, so the star is its hit area. The WAI-ARIA Radio Group pattern comes from the browser: one tab stop, arrow keys change the score, and the value takes part in a form. - Display: a read-only score, which may be fractional (4.5), as one
role="img"element named “4.5 out of 5 stars”.
2. Object
Section titled “2. Object”Stars printed on the panel: captured content, not relief. A star is not a rounded box, so it has no primitive.
| Part | Shape | Height at 50% | Moves |
|---|---|---|---|
| Star (input) | A 24 px target holding a five-point star | Flat | No |
| Stars (display) | A row of stars, font.size.base high, filled to the score |
Flat | No |
3. Faces and materials
Section titled “3. Faces and materials”| Part | Colour |
|---|---|
| Star up to the score | accent |
| Star above the score | edge (3:1 against the panel) |
| Star under the pointer, and the stars before it | accent at 55% over edge: a preview of that score |
4. Elevation per state
Section titled “4. Elevation per state”| State | Relief | Objects | CSS |
|---|---|---|---|
| Rest | Flat stars | Same | Same |
| Hover (input) | The preview colours | Same | Same |
| Focus-visible | outline: focus.width solid accent around the focused star’s target |
Same | Same |
| Disabled | Stars at 38% | Same | Same |
5. Relief primitives
Section titled “5. Relief primitives”None. The stars are captured content in every presentation.
6. Tokens it reads
Section titled “6. Tokens it reads”colour.accent, colour.edge, colour.text, space.1, space.2, target.min, font.size.small,
font.weight.strong, focus.*.
7. DOM structure and overlay needs
Section titled “7. DOM structure and overlay needs”<fieldset class="ug-rating"> <legend class="ug-rating__legend">Your rating</legend> <div class="ug-rating__stars"> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="1"> <span class="ug-rating__star" aria-hidden="true"></span> <span class="ug-rating__label">1 star</span> </label> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="2" checked> <span class="ug-rating__star" aria-hidden="true"></span> <span class="ug-rating__label">2 stars</span> </label> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="3"> <span class="ug-rating__star" aria-hidden="true"></span> <span class="ug-rating__label">3 stars</span> </label> </div></fieldset><span class="ug-rating-display" role="img" aria-label="4.5 out of 5 stars" style="--strata-rating: 0.9; --strata-rating-max: 5;"></span>- Each item’s label is visually hidden; it names its radio.
itemLabel(score, max)in the bindings changes the wording. Ratingtakeslabel,max(5),name(generated when absent),valueordefaultValue, a change callback anddisabled.RatingDisplaytakesvalueandmax, and an optionallabelfor its name; its--strata-rating(0–1) is the score overmax, and--strata-rating-maxsets how many stars it shows.- No overlay.
8. Keyboard and screen reader
Section titled “8. Keyboard and screen reader”| Key | Action |
|---|---|
| Tab | Moves to the checked star (or the first) and out of the group |
| Arrow keys | Change the score by one, wrapping |
| Space | Selects the focused star |
- Announced as a radio group named by the legend, each star as “3 stars, radio button, 3 of 5”. The display is an image named by its score.
9. CSS presentation
Section titled “9. CSS presentation”Each star is a 24 px target whose ::before is the star shape (clip-path), so the focus outline is not clipped.
Stars up to the checked one are filled, through :has(); with none checked, all are unfilled. The display paints
two rows of stars with a mask: unfilled, and filled clipped to --strata-rating. Under forced-colors filled stars
are Highlight and unfilled ones CanvasText.
10. Tests
Section titled “10. Tests”- Bindings: matches this markup; a click and arrow keys set and report the score; the value is submitted; filled stars follow the score; the display is an image named by its score.
- GPU: the stars are captured with no primitive; a real click on a star sets the score, and GPU stays on.
11. Indicator form: lamps
Section titled “11. Indicator form: lamps”Instrument, everyday forms (plan). form="lamps" draws the same native radios
as a row of lamps: each star’s place holds a lens, lit up to the score. It is the Lamp’s lens and the
StatusLight’s emitter on the Rating’s radio group. flush, or no form, is the Rating above, in the markup and the look it
had before, pixel for pixel; any other form string is the native form attribute (the id of the fieldset’s form owner), as before.
colour names the lit lenses’ role (glowOn, the lamp’s amber, by default). As with the Switch’s hardware forms, the premium character’s default
form is reached by naming it: with no form the Rating is its flush look, so a page that does not opt in is unchanged. RatingDisplay stays a
printed image.
| Part | Shape | Moves |
|---|---|---|
| Item | A square, the lens plus 16 px (the bloom’s halo), at least target.min: 28, 32 or 36 px at small, medium and large; the native radio covers it |
No |
| Socket | The dark disc under the lens, printed on the face at every level | No |
| Lens | A glass lens Ø size.rating (12, 16 or 20 px, so 0.35 of its diameter high at the Instrument level), with its emitter |
Lit 0 to 1 by --strata-lit |
- State and cues. Lit up to the checked radio and dark above it, as the stars fill; the radio group’s role, name, position and state are
native, so the lamps never carry the score alone. A hovered star and the ones before it show a lens half lit (
--strata-lit: 0.55), the preview of that score, while the rest of the row goes dark, as the stars do; the preview is only for a real hover (hover: hover), so on a touch screen a tap leaves the score lit, not half lit. Focus-visible is the CSS outline round the focused item (captured content, at every level). A disabled rating keeps its score, its lenses dimmed to 38% and throwing 30% of the light, so what it is set to is still said. - The native control stays the control. Each
<input type="radio">covers its item, invisible (opacity: 0), so every press and every key lands on it: one tab stop, arrows change the score, Space selects, the value takes part in a form, exactly as before. The lens isaria-hiddeninside the star’saria-hiddenspan; the accessibility snapshot of a Rating is the same with and without the form. - Emitters. A lit lens is an emitter at every GPU level, from the lamp’s tokens (
emitter.lamp.*: 3,200 at the 28 px reference lens, so 1,045 at 16 px; reach 6 lens diameters, 96 px; height 0.7): a 5-star rating is 5 emitters, and a score is a uniform write (no capture, upload or hit-geometry update). A panel with lamps takes a version 4 scene with itsemitters, theprotectedrects of its text and afeather, so a legend beside a lit lamp keeps the contrast guard. Underprefers-contrast: morethe emitters are off and a lit lens is flat colour. - GPU. Relief draws each lens as a ring face in its colour (the socket printed on the face under it), Objects as a dome standing on the face, fitted so its shadow stays in the item’s box; at the Instrument level each lens is a glass LED lens (StatusLight: 0.35 of its diameter high) with its emitter, its bounds the radio’s box.
- Presentation. Forced colours:
Highlightlit lenses andCanvasdark ones, each edged inCanvasText. Reduced motion changes nothing (nothing moves). Underprefers-reduced-transparencythe lens is opaque lacquer. At 320 px the row wraps, at 200% text the legend wraps and the items keep their size.
<fieldset class="ug-rating" data-strata-form="lamps"> <legend class="ug-rating__legend">Your rating</legend> <div class="ug-rating__stars"> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="1"> <span class="ug-rating__star" aria-hidden="true"><span class="ug-rating__lens" data-strata-face="knob"></span></span> <span class="ug-rating__label">1 star</span> </label> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="2" checked> <span class="ug-rating__star" aria-hidden="true"><span class="ug-rating__lens" data-strata-face="knob"></span></span> <span class="ug-rating__label">2 stars</span> </label> <label class="ug-rating__item"> <input class="ug-rating__input" type="radio" name="score" value="3"> <span class="ug-rating__star" aria-hidden="true"><span class="ug-rating__lens" data-strata-face="knob"></span></span> <span class="ug-rating__label">3 stars</span> </label> </div></fieldset>data-strata-colour(colourin the bindings) is on the fieldset. React:<Rating form="lamps" colour="success" label="Your rating" name="score">; Vue: the same props withv-model; Astro:<Rating form="lamps" ...>. No behaviour script is needed.- Tests:
ui-indicator-forms.test.mjs(plain DOM, touch, reflow, preferences, GPU at Relief, Objects and Instrument),ui-indicator-forms-bindings.test.mjs,ui-indicator-forms-astro.test.mjs.