# Rating

A row of indicator lamps, each in its own round recess, lit up to your score. It is a native radio group underneath, so arrows, Space, the label and the form all work with no script; a number is printed under each lamp, so the score is never told by colour alone. A read-only row shows a score someone else gave.

Kit part · Free · https://tactileui.dev/parts/rating

- Element: `<fieldset class="tui-rating">`
- Needs: `kit.css` and `kit.mjs` ([how to install the kit](https://tactileui.dev/docs/installation#the-kit))
- Categories: Radio groups
- Finishes: Aluminium, Graphite, Oak, Walnut, Porcelain, Black, Daylight, Night, Paper, Phosphor, E-paper, AMOLED
- Volumes: Tactile, Quiet

## Variants

### Not rated

```html
<fieldset class="tui-rating"><legend class="tui-label">Rate this release</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt17" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt17" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt17" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt17" value="4" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt17" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">Not rated</span></div></fieldset>
```

### A score of 3

```html
<fieldset class="tui-rating"><legend class="tui-label">Rate this release</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt18" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt18" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt18" value="3" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt18" value="4" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt18" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">3 of 5</span></div></fieldset>
```

### Lamp colours · data-lamp

```html
<div style="display:grid;gap:12px"><fieldset class="tui-rating tui-rating--sm" data-lamp="green"><legend class="tui-label">Green</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt19" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt19" value="2" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt19" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt19" value="4" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt19" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">2 of 5</span></div></fieldset><fieldset class="tui-rating tui-rating--sm" data-lamp="red"><legend class="tui-label">Red</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt20" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt20" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt20" value="3" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt20" value="4" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt20" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">3 of 5</span></div></fieldset><fieldset class="tui-rating tui-rating--sm" data-lamp="blue"><legend class="tui-label">Blue</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt21" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt21" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt21" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt21" value="4" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt21" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">4 of 5</span></div></fieldset></div>
```

### Sizes · --sm and --lg

```html
<div style="display:grid;gap:12px"><fieldset class="tui-rating tui-rating--sm"><legend class="tui-label">Small</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt22" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt22" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt22" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt22" value="4" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt22" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">4 of 5</span></div></fieldset><fieldset class="tui-rating tui-rating--lg"><legend class="tui-label">Large</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt23" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt23" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt23" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt23" value="4" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt23" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">4 of 5</span></div></fieldset></div>
```

### Out of ten

```html
<div style="width:min(100%,380px)"><fieldset class="tui-rating tui-rating--sm"><legend class="tui-label">Likelihood to recommend</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt24" value="1" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt24" value="2" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt24" value="3" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt24" value="4" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt24" value="5" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label><label><input type="radio" name="rt24" value="6" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">6</span></label><label><input type="radio" name="rt24" value="7" checked tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">7</span></label><label><input type="radio" name="rt24" value="8" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">8</span></label><label><input type="radio" name="rt24" value="9" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">9</span></label><label><input type="radio" name="rt24" value="10" tabindex="-1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">10</span></label></div><span class="tui-rating__out" aria-hidden="true">7 of 10</span></div></fieldset></div>
```

### Read-only

```html
<div style="display:grid;gap:10px"><div class="tui-rating tui-rating--readonly" role="img" aria-label="Rated 5 out of 5"><span class="tui-rating__lamps"><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span></span><span class="tui-rating__out" aria-hidden="true">5 of 5</span></div><div class="tui-rating tui-rating--readonly" role="img" aria-label="Rated 3 out of 5"><span class="tui-rating__lamps"><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp"></span><span class="tui-rating__lamp"></span></span><span class="tui-rating__out" aria-hidden="true">3 of 5</span></div><div class="tui-rating tui-rating--readonly" role="img" aria-label="Rated 0 out of 5"><span class="tui-rating__lamps"><span class="tui-rating__lamp"></span><span class="tui-rating__lamp"></span><span class="tui-rating__lamp"></span><span class="tui-rating__lamp"></span><span class="tui-rating__lamp"></span></span><span class="tui-rating__out" aria-hidden="true">0 of 5</span></div></div>
```

### Disabled

```html
<fieldset class="tui-rating" disabled><legend class="tui-label">Rating closed</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="rt25" value="1" tabindex="-1" disabled><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="rt25" value="2" checked tabindex="-1" disabled><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="rt25" value="3" tabindex="-1" disabled><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="rt25" value="4" tabindex="-1" disabled><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="rt25" value="5" tabindex="-1" disabled><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">2 of 5</span></div></fieldset>
```

## Every state

- None
- Hover
- Focus
- Chosen
- Disabled
- Read-only

Hover, pressed and focus are forced with `.is-hover`, `.is-down` and `.is-focus`; checked and disabled are real.

## API

| Name | Kind | Values | What it does |
| - | - | - | - |
|  | element | with a legend | The group and its name. Add --sm or --lg for the lamp’s size, and data-lamp="green" \| "red" \| "blue" \| "white" to light a lamp of another colour (amber is the default). |
| label > input[type=radio] + .tui-rating__lamp + .tui-rating__n | element | one to a lamp | The radio is the real control and posts with the form; the lamp is its recess; the number is printed under it. Give the radios one name and the values 1 to the top score. |
| .tui-rating__out | element | optional, aria-hidden | The score in words beside the lamps, filled by the script: “4 of 5”. A screen reader already hears the radios, so it is hidden from one. |
| .tui-rating--readonly | class | on a div with role="img" | The same row as a picture of a score. Put data-on on each lamp that is lit and the score in aria-label. |
| tui-rating-change | event | detail { value, max } | Bubbles from the fieldset when a lamp is chosen. The radio’s own change fires as ever. |
| ratingText(value, max) · ratingLabel(value, max) | function | pure | The printed words (“4 of 5”, “Not rated”) and the name of a read-only row (“Rated 4 out of 5”). |
| ← → ↑ ↓ | key | in the row | The browser’s own radio keys: move to the next lamp and choose it. Tab leaves the row. |

## Markup

```html
<fieldset class="tui-rating" data-lamp="amber">
  <legend class="tui-label">Rate this release</legend>
  <div class="tui-rating__row">
    <div class="tui-rating__lamps">
      <label><input type="radio" name="score" value="1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label>
      <label><input type="radio" name="score" value="2"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label>
      <!-- … to 5 -->
    </div>
    <span class="tui-rating__out" aria-hidden="true">Not rated</span>
  </div>
</fieldset>

<!-- Read-only: an image with the score in its name -->
<div class="tui-rating tui-rating--readonly" role="img" aria-label="Rated 4 out of 5">
  <span class="tui-rating__lamps">
    <span class="tui-rating__lamp" data-on></span> … <span class="tui-rating__lamp"></span>
  </span>
</div>
```

```js
import { ratingText, ratingLabel } from '/kit/kit.mjs';

document.querySelector('.tui-rating').addEventListener('tui-rating-change', (e) => {
  save(e.detail.value, e.detail.max);        // 4, 5
});

ratingText(4, 5);                             // '4 of 5'
ratingLabel(4, 5);                            // 'Rated 4 out of 5'
```

The demo on the page:

```html
<form class="tui-panel" style="width:min(100%,460px);display:grid;gap:16px;text-align:left" action="/parts/rating" method="get" data-rt-form><div class="tui-panel__head" style="margin-bottom:0"><span class="tui-label">Release 4.12 · Northwind API</span><span class="tui-status"><span class="tui-lamp" data-on></span>Shipped</span></div>
  <fieldset class="tui-rating"><legend class="tui-label">How did the upgrade go?</legend><div class="tui-rating__row"><div class="tui-rating__lamps"><label><input type="radio" name="score" value="1"><span class="tui-rating__lamp"></span><span class="tui-rating__n">1</span></label><label><input type="radio" name="score" value="2"><span class="tui-rating__lamp"></span><span class="tui-rating__n">2</span></label><label><input type="radio" name="score" value="3"><span class="tui-rating__lamp"></span><span class="tui-rating__n">3</span></label><label><input type="radio" name="score" value="4"><span class="tui-rating__lamp"></span><span class="tui-rating__n">4</span></label><label><input type="radio" name="score" value="5"><span class="tui-rating__lamp"></span><span class="tui-rating__n">5</span></label></div><span class="tui-rating__out" aria-hidden="true">Not rated</span></div></fieldset>
  <div style="display:grid;gap:8px"><span class="tui-label">What others gave it</span><div class="tui-rating tui-rating--readonly" role="img" aria-label="Rated 4 out of 5"><span class="tui-rating__lamps"><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp" data-on></span><span class="tui-rating__lamp"></span></span><span class="tui-rating__out" aria-hidden="true">4 of 5</span></div></div>
  <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap"><output class="tui-muted" style="font-size:var(--tui-t-small)" data-rt-out aria-live="polite">Nothing sent yet</output><button class="tui-key" type="submit">Send</button></div></form>
```

## Usage notes

Press the fourth lamp, or Tab into the row and arrow along it: every lamp up to the one you choose lights, and the score is printed beside them. Move the pointer along the row to see what each press would light. The row of five below is the same lamps, read-only.

## Accessibility

- It is a radio group in a `<fieldset>` with a `<legend>`, which every screen reader says as “Rate this release, group, 4, radio button, 4 of 5”, with no script and no ARIA.
- The score is told three ways that are not colour: how many lamps are lit, the number printed under each lamp, and, with the script, the words “4 of 5”. A lit lamp is also brighter and haloed, an unlit one is dark in its recess.
- A read-only row is a `role="img"` named “Rated 4 out of 5”, so it is one thing to a screen reader, not five lamps. The lamps past the score carry a dash in the recess, so even a printout shows the score.
- Focus is a 2px ring round the lamp’s recess. The hover preview lights what a press would light and puts it back when the pointer leaves; it is for the pointer only, and a keyboard move shows the real thing.
- On a phone each lamp’s target is 44px square, five fit in a row at 390px, and the lamps take no transition under reduced motion.

## How it’s built

The radio is the browser’s, kept whole and laid over its own lamp, so a press, a label, the form and the arrow keys are native. The lamp is the kit’s indicator lamp set in a round recess, and the lit lamps are found with CSS alone: a lamp is lit if its own radio is checked or if a later radio is, which is the selector `:has(~ label input:checked)`. The hover preview is the same rule keyed on the pointer. The script only prints the words.

## Rules

Ask for a score on a row of lamps: set by a press or the arrow keys, read as “4 of 5” by everyone, and shown read-only where the score is not yours to change.

The full rules are in `rating.rules.md` in the brain, which ships with the Kit.

## Related parts

- [Radio](https://tactileui.dev/parts/radio): One choice from a short list in a form: small round keys in a fieldset, the chosen one pressed with a printed dot.
- [Lamp](https://tactileui.dev/parts/lamp): The only colour in the kit: a lamp that is on. Green is on, amber is waiting, red is recording or failing, blue is linked, white is standing by. Always next to words.
- [Segmented control](https://tactileui.dev/parts/segmented): A row of keys in a tray with one pressed down: pick a view, a range or a mode and it applies at once. It is the kit’s selector without the lamps, with sizes, a full-width row and icon segments.
- [Field](https://tactileui.dev/parts/field): Text entry in a recess, the label printed above it, and a hint that says how to fix an error.
