Repository navigation
feat(ui): put Eval on the Redrob brand tokens - #20
Merged
Merged
Conversation
The palette was this app's own: Tailwind greys for the page and the lines, a
navy titlebar, a teal accent left over from when the primary button was teal,
and a second copy of every colour in the dark block. None of it was a brand
value, so the same screen in Eval and in Console were two shades of the same
idea.
The stylesheet now carries the same three bands Console does. The brand
primitives are transcribed verbatim from Console's `globals.css`, all sixty-eight
of them. On top of that sit Console's eighty semantic roles at Console's exact
values in both themes, plus the handful of roles Console has no equivalent of:
the titlebar and its inks, the terminal, the two ends of the run bar, a status
strip's edge, and a control boundary under the cursor. Each of those is built
from primitives only and commented where it is declared.
The four thousand three hundred lines of rules below are not rewritten. The
names they already spell are rebound as aliases onto the roles, one line each,
which is how the Office and Work ports did it: `--panel` is `var(--card)` and
`--line` is `var(--border)`, and the dark twins those names used to carry are
deleted, because the role each one points at is already re-pointed for dark.
Four names went instead of moving:
--muted was secondary text here and a surface in Console, and the two
cannot both hold the name. Renamed to `--muted-foreground`,
which is what it always was.
--brand-solid was `--brand` with the theme lifted off it, so that a white
label stayed readable. On dark the ink is Redrob Black now, so
the fill does not need to stay saturated and the two collapse.
--brand-ink was a third step of brand text between `--brand-deep` and the
fill. Under the brand scale it is `--brand-deep`.
--accent-* four teal tokens, every caller a selected state. A selected
state is brand blue.
Two smaller things fall out of it. The four literal copies of the Pretendard
stack and the eight of the monospace stack are gone: both are declared once, in
`@theme inline`, and named through `var()`. And the titlebar is one colour in
both themes rather than two navies, because the dark theme's requirement fixes
it: a bar darker than a Gray 9 page measures 1.19:1 against it, which is to say
it is not visible.
Not taken: the type size, leading and tracking scale. Its steps differ from the
ones in use at every level, so adopting it re-flows every screen at once, which
wants reviewing against the live layouts rather than arriving with a colour
change. Console and Office made the same call. Radius and spacing are unchanged.
`--line` on `--panel` is 1.18:1 in dark, under the 1.25:1 this repo asks of a
surface join. That is Console's value: the brand grayscale has three steps at
the dark end, the raised panel is a mix of two of them, and a Gray 8 border
drawn on it lands there. Recorded per pairing in `CONSOLE_FLOOR` rather than by
lowering the floor, so the exemption cannot quietly grow.
Co-authored-by: janghoonlee <janghoonlee@mckinleyrice.co>
Same CDN and same pin as before, but the full variable file rather than the dynamic subset. The subset carries the whole weight axis and splits the face into slices the browser fetches only when a page renders glyphs from them, which for an English screen is Latin and some punctuation where the full file is mostly Hangul it will never draw. Console, Office and Code all load the subset; this was the one product on the full file. The URL moves to a named constant, so the version is written in exactly one place and `--font-sans` in `globals.css` names only the family it registers. The `preconnect` matters more than usual here: the stylesheet and the slices it names are two round trips to a third party before any text is in its real face. Co-authored-by: janghoonlee <janghoonlee@mckinleyrice.co>
Two repositories cannot import from each other, so the palettes agree only for
as long as somebody checks. This file is the joint: every primitive and every
semantic role Console declares is transcribed here, and each test compares Eval's
copy against it. If either side changes a colour alone, it fails and names the
token.
Fourteen assertions, and the ones that earn their place:
- every primitive at Console's value, and no primitive this app invented
- no primitive re-pointed for a theme, because Blue 6 is Blue 6 in both
- every role where Console points it, in light and in dark
- the dark block re-points exactly the seventy-two roles Console re-points,
plus the four roles Console does not have. A role missing from it would fall
through to a light value on a dark page
- no literal colour outside the primitive band, so a role is decided once
- every local name a plain alias with no dark twin, which is the property that
makes the band safe to keep
- no rule and no component naming a primitive, so nothing reaches past the
roles for a colour that cannot follow the theme
- no hardcoded colour under `apps/web/src`, with one exception that has to
prove itself: xterm paints to a canvas and cannot resolve `var()`, so
`DeployTerminal` needs literals for the case where `getComputedStyle` returns
nothing, and both are asserted equal to the primitives their tokens hold
- Pretendard first in the stack, the stack written once, the version pinned once
- the monospace stack named only by the eight code surfaces, listed, so adding
a ninth is a decision somebody writes down
- the reason the type scale was not taken, so a later change cannot take half
of it without noticing
Checked by mutation: drifting a primitive, hardcoding a colour in a component and
reintroducing a dark twin each fail, and each fails in the test that should catch
it rather than somewhere downstream.
Co-authored-by: janghoonlee <janghoonlee@mckinleyrice.co>
its-janghoon
marked this pull request as ready for review
August 30, 2026 17:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eval now uses Console’s
--rr-*primitives and semantic roles instead of a local palette.What changed
apps/web/src/app/globals.cssis three bands: 68--rr-*primitives, Console semantic roles at Console’s exact light/dark values, then Eval’s existing names as aliases.--mutedbecame--muted-foreground(name clash with Console’s surface). Teal--accent-*selected states map to brand blue.scripts/test/design-tokens.test.mtsfails if a primitive drifts from Console, a colour is hardcoded, or a dark twin comes back.Labs is not in this PR. No Labs files were changed.
Proof (Kiro)
yarn typecheckexit 0yarn lintexit 0yarn testexit 0 (1000/1000)yarn verify:themeexit 0yarn buildexit 0Commits:
f74fba5,9811927,841e414oncursor/eval-design-tokens-8171.Remaining risks
--lineon--panelis Console’s 1.18:1 join; recorded inCONSOLE_FLOORrather than a lowered floor.DeployTerminalgetComputedStyleofvar()inside a custom property was not exercised here.