Meters and scores

Meters and scores

One meter: six bands

The house meter is GradeMeter (js/src/components/commonComponent/seoTools/GradeMeter.jsx). It draws six bands: F, D, C, B, A, A+, with the current band highlighted.

Six, not five, and that is the whole point of it existing. The scale gained an F, and the meter that preceded it did not. A meter that disagrees with the grade chip beside it is the bug this replaces.

Use it for anything on the 0-100 score scale. It is already in the dashboard, the channel audit, the title workshop, the SEO workshop, and the extension.

The legacy meter, and how to recognise it

ProgressIconic (js/src/components/svgcomponents/ProgressIconic.jsx) is the one being retired. It draws five frames on 20-point bands (0-20, 20-40 and so on), with a sparkle at 71 and a particle burst at 86.

Because the two disagree about how many bands the scale has, any screen showing both is showing the same score on two scales. That is not a subtle mismatch: a score can sit in the fourth of five frames and the fourth of six bands and mean different things.

Still on it, and not yet reviewed: the video report top section. That is TS-5173.

Opting a block in

SeoBlock takes a meter prop. It is opt-in rather than a straight swap so that consumers get converted deliberately rather than silently restyled.

<SeoBlock meter progressScore={score} />

Absence is not zero

A score we do not have is not a score of zero. GradeMeter renders null as no band current, not as an F, because stamping an F on something we simply have not measured is a different claim entirely.

Two consequences worth knowing:

score || default defeats this. A genuine score of 0 is falsy, so it falls through to the placeholder and the distinction is lost. This pattern is still present in the SEO workshop sidebar and is worth fixing wherever it appears.

Whether an empty meter belongs is a judgement call. The channel audit passes progressScore={null} with meter, so an unmeasured category shows an empty meter and says so, because there absence is a result. The SEO workshop’s Title Keyword and Learning Skills cards pass null without meter, because they are list cards showing keywords with their own score tags, not categories left unmeasured. Same prop, opposite intent. Ask whether absence is itself information before deciding.

Context changes the words, not the bands

getScoreGrade(score, context) takes "title" or "channel". This is easy to get wrong in both directions, so:

  • getScoreGrade defaults to "title".
  • GradeMeter defaults to "channel".
  • SeoBlock forwards no context at all.

None of that affects the band. Context swaps only the blurb wording, so the copy reads correctly for a title or for a channel. The thresholds are shared. A block and the sidebar beside it will always agree on the letter even if they disagree on the context.

Colour

Bands take the --ts-score-* tokens. Do not reach for the colours getScoreGrade returns: that scale is the older generation (#96DC46, #5AB43C, #FAC833) and does not carry on a white page, let alone on glass. The helper owns the boundaries, the design tokens own the palette.