desktop-new: the palette's step labels describe Buzz, not the scale it came from

Both label sets came with the transcribed values and described a generic scale's
intentions: step 4 as "component hover", step 6 as "subtle border", step 7 as
"border". The product then decided otherwise and nobody updated the comments, so
the file said step 4 was a hover step while it held `border-primary`, the one
border weight, and said steps 6 and 7 were for borders while they had no readers
at all. A designer opening `tokens.css` or `/design/color` was told the wrong
thing by the only documentation to hand.

The neutral ramp's comments now name the roles that actually point at each step,
including the two steps that have no reader — an empty step is worth seeing,
because it is either a gap or a deletion nobody made yet.

`STEP_JOBS` keeps generic wording, because it is shared by all eight hues and a
hue's step 3 is a tinted surface whatever the product does with it. But it now
matches DESIGN.md's step-to-role table exactly, which it did not, and it says so
about itself: general intention here, real use in the neutral ramp's comments.

The reason it drifted is that it was never rendered. Every palette step carried
this text and no page displayed it, so it could only be checked by reading the
source. The colour page now shows each step's job under its swatch, which makes
the next divergence visible by looking rather than by audit.

Signed-off-by: Morgan Martin <morganmartin@squareup.com>
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
This commit is contained in:
morgmart
2026-09-07 16:14:27 -07:00
parent d9a0223804
commit 1dee19d8a1
3 changed files with 65 additions and 29 deletions

View File

@@ -97,6 +97,12 @@ export function ColourPage() {
{hue.usedBy ? `drawn from by ${hue.usedBy}` : "unassigned"}
</span>
</div>
{/* Each step carries what it is for, not just its number. The
registry has always held this text and no page rendered it,
which is how it drifted: it still described the generic scale
the values came from — step 4 as "component hover" — long after
this product had made step 4 its one border weight. Unrendered
documentation cannot be checked by looking. */}
<div className="flex gap-1">
{hue.steps.map((step) => (
<div
@@ -110,6 +116,9 @@ export function ColourPage() {
<span className="text-center text-body-sm text-tertiary">
{step.step}
</span>
<span className="text-center text-body-sm text-tertiary">
{step.job}
</span>
</div>
))}
</div>

View File

@@ -263,23 +263,37 @@
============================================================ */
:root {
/* --- Neutral. Twelve steps, each step a fixed job. --------
/* --- Neutral. Twelve steps. --------------------------------
Keeps its numbering: unlike the coloured families these steps
really are a scale, and every step is in use. Step 1 stays
pure white rather than the palette's off-white, because the
app background is a deliberate choice, not a grey. */
--neutral-1: #ffffff; /* app background */
--neutral-2: #f9f9f9; /* subtle background */
--neutral-3: #f0f0f0; /* component background */
--neutral-4: #e8e8e8; /* component hover */
--neutral-5: #e0e0e0; /* component selected */
--neutral-6: #d9d9d9; /* subtle border */
--neutral-7: #cecece; /* border */
--neutral-8: #bbbbbb; /* border hover */
--neutral-9: #8d8d8d; /* solid fill, tertiary text */
--neutral-10: #646464; /* secondary text */
--neutral-11: #262626; /* dark fill */
--neutral-12: #0a0a0a; /* high-contrast text */
really are a scale. Step 1 stays pure white rather than the
palette's off-white, because the app background is a
deliberate choice, not a grey.
**The comments record what Buzz uses each step for, not what
Radix intended it for.** They said "component hover",
"subtle border", "border" — a generic scale's intentions,
transcribed with the values and then left alone while the
product decided otherwise. That is how the one border weight
came to sit on the step labelled "component hover" while the
two steps labelled for borders had no readers at all, and how
a designer reading this file would have been told the wrong
thing by the only documentation at hand.
Keep these current. A step whose comment disagrees with its
use is worse than no comment, because it reads as a decision
someone made. `pnpm census` lists the real readers. */
--neutral-1: #ffffff; /* bg-panel, bg-float, bg-chrome-selected */
--neutral-2: #f9f9f9; /* unused in light; bg-inset in dark */
--neutral-3: #f0f0f0; /* bg-inset; bg-panel in dark */
--neutral-4: #e8e8e8; /* border-primary — the one border weight */
--neutral-5: #e0e0e0; /* unused in light; float + selected, dark */
--neutral-6: #d9d9d9; /* the /design specimen frame edge only */
--neutral-7: #cecece; /* no readers */
--neutral-8: #bbbbbb; /* text-disabled */
--neutral-9: #8d8d8d; /* text-tertiary */
--neutral-10: #646464; /* text-secondary */
--neutral-11: #262626; /* inverse fill, paired with neutral-1 */
--neutral-12: #0a0a0a; /* text-primary */
/* --- Glass. A translucency ramp of fills. ---------------- */
--glass-1: #ffffff5c; /* barely there */

View File

@@ -63,23 +63,36 @@ export interface RoleGroup {
============================================================ */
/**
* What each of the twelve steps is *for*. The same twelve jobs in every hue —
* which is the whole point of a twelve-step scale, and what makes the
* step-to-role mapping deterministic: a role picks a step number, not a colour.
* Named from the neutral ramp because that is where every step is in use.
* What each of the twelve steps is *for*, as a starting point.
*
* The same twelve jobs in every hue is what makes a twelve-step scale useful and
* the step-to-role mapping deterministic: a role picks a step number, not a
* colour.
*
* **These are the scale's general intentions, not a record of Buzz's decisions,
* and the two have already diverged.** The list came with the values and said
* step 4 was "component hover" and step 6 "subtle border" — while in this product
* step 4 is the one border weight and step 6 has one reader on a documentation
* page. A generic label that contradicts the product is worse than none, because
* a designer reading `/design` takes it for a decision someone made.
*
* So: **the label answers "what is this step generally for", and the neutral
* ramp's own comments in `tokens.css` answer "what does Buzz actually do with
* it".** When a step's real use settles into something durable, move it here.
* `pnpm census` lists the real readers of every role.
*/
const STEP_JOBS = [
"app background",
"subtle background",
"component background",
"component hover",
"component selected",
"subtle border",
"lightest surface",
"subtle surface",
"tinted surface",
"tinted surface, hovered",
"quiet border, or a selected surface",
"border",
"border hover",
"stronger border",
"border hover, focus ring",
"solid fill",
"secondary text",
"dark fill",
"solid fill, hovered",
"text on a tint, or an inverse fill",
"high-contrast text",
];