Role-based token contract #55
Notifications
Due Date
No due date set.
Depends on
#53 Palette candidates on a dense page
ShadowsOverWestgate/sow-nodebb-theme
Reference: ShadowsOverWestgate/sow-nodebb-theme#55
Reference in New Issue
Block a user
Part of #47
Question
What is the token contract, expressed as roles rather than colour names?
DESIGN.mdfrontmatter currently lists 26 named colours —tarnished-gold,bruised-plum,crypt-black,heart-wine— and_tokens.scssis 155 lines. Names like these describe pigment, not job, so every consumer has to know which pigment means "border" this week. That is exactly what makes a palette change expensive, and this map exists to make one.Resolve:
scss/westgate/, not invented.heart-*,sorrow-*), which are pigment-named state colours and the clearest case of the problem._tokens.scssstays one file.Output is the token contract as a list of roles with their values from the winning palette, plus the migration note for external consumers.
Handed over from #53 (resolved)
The palette this contract has to express is decided — candidate B, Two Metals. Full role
assignment in the #53 resolution.
Three things this ticket now owns:
scss/overrides.scssholds Sass variables(
$wg-ink,$gray-*,$black,$dropdown-bg) that must be real colours, notvar(), because Sass passes them torgba()and Bootstrap. They do not follow a CSScustom-property swap: in the prototype shots the topbar kept the old cold ground while the
page below it moved. The contract has to say how the two layers stay in agreement.
rgba(194, 163, 90, …)uses alone. Arole-based contract is unusable until they are tokenised. Branch
prototype/53-palette-candidateshas a working mechanical pass to crib from.now carries structure — so the live question is which of
velvet-panel/-deep/-raisedstill earns a slot. That is this ticket's to answer.Resolution
The token contract is ~30 roles, down from 50 declared tokens plus 26 frontmatter pigments.
Derived from real usage across
scss/westgate/(6118 lines) and the sibling plugin checkouts,not invented.
The contract
page,page-deep,panel,panel-quiet,accent#150E13,#0C0810,#21161C,#180F16, accent pendingaccent,accent-lift,accent-glow/-glow-raisedtext,text-soft,text-muted#E6E0D6,#B9B2A6,#9EA7B3pewterrule,rule-soft,rule-faint,edge-gold#A8893Fopaquegold,gold-lit,ink#C2A35A,#E0C878,#D8C28Afocus-ring#C2A35A,outline-offset: 2px(#50 finding b)status-online/away/dnd/offline,vote-on,danger,stamp#d47a87;#8E3438;#A84A4Eledger-line,page-width, 4 fontspage-widthis #56's, not this contract'sThe eight rules
value → name (
--wg-text-muted#9EA7B3pewter). No pigment name appears in code, infrontmatter, or in a consumer. The frontmatter
colors:block of 26 pigments goes away —it duplicated token values by hand, so a re-tune had to edit both and they could drift
silently. Name-aliasing tokens were rejected: a second public surface to keep AA-checked,
and renames cost double.
panelsurface. They differ by opacity and shadow,not by tone, and #54 already split them as components (Velvet panel vs Ledger, sheen on or
off). Material belongs to the component, not to a second surface token.
panel-quietsurvives for recessed things — card caps, inputs, #54's Well.
panel-3andplum-softaredropped, not renamed;
#4A2A38stays a documented accent value with #50's rule-2 limit(large text and non-text only) but earns no role until a component asks.
to the nearest of
.20/.11/.075; no bespoke alphas. Gold as an edge means value,not structure, so
edge-goldis opaque — because gold and pewter are luminance twins(1.006:1, #50), a pewter rule and a gold rule at the same alpha are the same lightness. The
ladder may never mean "more important".
accent(opaque surface — icon plates, plaques, bands),accent-lift(hover/active), andaccent-glowin two steps (rest/raised) for the inner bloom inside panels and behindornament. The glow role absorbs
#602044, an undeclared third plum found inside--wg-velvet-shadow.moss-string,dry-apricotanddeletion-redwere never UI states — they are highlight.js colours in
_posts.scss. They become scoped--wg-code-*vars next to that block. The fiveheart-*/sorrow-*names die: only#d47a87was ever used (the upvote arrow) and it becomes the singlevote-onrole.Downvote keeps plain gold and gets no colour of its own — a downvote is not a colour event.
stamp#A84A4Esurvives apart fromdangerbecause it is ornament (the wax seal, #54'sStamp), not an alert.
_palette.scssholds role → value;_tokens.scssemits:root { --wg-#{$role}: … }with an@each;overrides.scssreadsthe same map. This closes #53's two-layer seam — the Sass layer cannot follow a
var()swap, which is why the prototype's topbar stayed cold while the page moved. The Sass side is
derivation only (
rgba(),mix(), Bootstrap plumbing); it may never invent a colour.Bootstrap's
$gray-100…900stops being its own ramp and maps onto roles, as do$primaryand
$danger;$blue/$green/$cyanget roles or get pinned, because today Bootstrap canpaint a component in a colour nobody chose. NodeBB compiles the SCSS, so this needs no build
step in this repo.
_palette.scss(allowing#fffandtransparent). One morenode tests/<name>.test.jsfile. This is the only thing that stopsliteral #234 appearing next month — the theme currently has 233
rgba(194,163,90,…)uses,44
rgba(216,194,138,…), 40rgba(255,244,221,…)and 18 literal#fff4dd.subset — surfaces, text, accent, structure, gold, state, spacing, fonts. Ornament internals
(
etched-*, the shadow composites,control-bg) are private, carry a distinct prefix sothe boundary is visible in code, and #54's components may change them without it counting as
a break.
Which tokens are public, established by grep
--wg-border,-text-muted,-space-md,-gold,-font-display,-velvet-panel,-velvet-shadow,-font-text, …).Two of them —
velvet-panelandvelvet-shadow— this ticket abolishes.wiki styles against
--wiki-*, which this theme binds to--wg-*in_wiki-prose.scss.That indirection is the right shape and stays — do not flatten it.
sow-nodebb's
plugins.lock, so old theme and old pages keep working together until both arere-pinned. An alias layer would be permanent debt bought to protect one sibling checkout.
The migration table (old name → new role → who changes) is filed against pages when the
palette ships, not now.
Does
_tokens.scssstay one fileNo. It splits:
_palette.scss(the map — values, the one place a re-tune edits) and_tokens.scss(the emit, plus spacing, type scale and@font-face). The split is what makesrule 6 possible; it is not filing preference.
What this ticket does not close
The accent value is pending. During this grilling the human reversed a standing law of the
map: Bruised Plum is preferred over Plum Noir, as the accent pushed harder than today — not
as the ground. #53's four ground surfaces stay on the Plum Noir lineage. The new value needs a
contrast run (
#2a1222is darker than Plum Noir, which #53 already measured at the Dust 4.90ceiling) and a browser look. Raised as its own ticket rather than settled quietly here.
Riding along on that ticket:
#d47a87vote-onhas never been contrast-checked against thenew grounds, and it is the one saturated pink on a page that outlawed lavender.