Skip to content

feat(theme): make the neutral border tokens opaque surface steps - #889

Merged
isaque-bock-azion merged 5 commits into
mainfrom
feat/opaque-border-tokens
Aug 12, 2026
Merged

isaque-bock-azion merged 5 commits into
mainfrom
feat/opaque-border-tokens

Conversation

@gabriel-lisboa-azion

Copy link
Copy Markdown
Contributor

Summary

  • --border-default and --border-muted become opaque steps of the surface palette. As alpha they painted a different colour on every backdrop — rgb(26) on --bg-canvas, 35 on --bg-surface, 44 on --bg-surface-raised, 95 on --bg-surface-overlay — and two rules meeting composited into a fifth, brighter value, so any stacked or abutting border read as a double rule.
  • Adds four palette steps (gray 150 / 250 / 750 / 775) because the ramp had none in the range a border needs: it jumped 200 (229) → 300 (178) and 700 (77) → 800 (26), and those bracketing steps are already --bg-selected / --bg-disabled, so an opaque border landed on its own fill and disappeared. The dark background anchors (700 / 800 / 900) keep their values.
  • muted now sits closer to the background than default in both themes — lighter in light, darker in dark — instead of being identical to it in light.

How to test

  1. pnpm storybook:dev → Components/Inputs/Checkbox → Disabled, both themes: the control keeps a visible border. Before this change an opaque border here was exactly --bg-disabled and vanished.
  2. Any bordered component on a raised or selected surface (Components/Data/Table, Components/Overlay/Panel, Components/Actions/SegmentedButton): every hairline is visible, and a rule reads the same weight wherever it is drawn.
  3. pnpm --filter @aziontech/theme test → 12 pass.
  4. node packages/theme/src/scripts/build-tokens.mjs → dist/v4/globals.css regenerates with no diff, confirming the committed dist matches source.

Notes

  • Not an API change: no token is renamed or removed, only revalued, plus four additive palette steps. It is a visible change to every bordered component — borders read slightly stronger and no longer drift by backdrop — so it wants a design eye as much as a code one.
  • Measured contrast against every surface role, both themes: minimum delta 10, no zeros. Previously four combinations were delta 0 (invisible) once opaque.
  • Blocks feat(webkit): add frame-box, section-gap, section-title and hero-title #880, which needs these tokens for its frame rules and hatch to reach full strength.

`--border-default` and `--border-muted` were alpha (`#FFFFFF1A` / `#FFFFFF0D`
dark, `#14` light), so one token painted a different colour on every
backdrop — measured rgb(26) on `--bg-canvas`, 35 on `--bg-surface`, 44 on
`--bg-surface-raised` and 95 on `--bg-surface-overlay` — and two rules meeting
composited into a fifth, brighter value. A hairline had no fixed identity, and
any stacked or abutting border read as a double rule.

Both now point at opaque steps of the surface palette. The ramp had no step in
the range a border needs — it jumped 200 (229) to 300 (178) and 700 (77) to 800
(26), and the steps bracketing those gaps are already `--bg-selected` /
`--bg-disabled`, so an opaque border landed exactly on its own fill and
vanished. Four steps fill the gaps: gray 150, 250, 750 and 775. The dark
background anchors (700 / 800 / 900) keep their values.

Every border-on-surface pairing now clears zero contrast, minimum delta 10.
`muted` sits closer to the background than `default` in both themes — lighter
in light, darker in dark — so it reads as a subtler rule rather than a
duplicate.
@isaque-bock-azion
isaque-bock-azion merged commit 5595436 into main Aug 12, 2026
23 checks passed
@isaque-bock-azion
isaque-bock-azion deleted the feat/opaque-border-tokens branch August 12, 2026 17:37
isaque-bock-azion added a commit that referenced this pull request Aug 14, 2026
…lighter type scale

`Avatar › VariantGrid` failed the visual shard on `dark-desktop` only, at
1.0301% / 1354px against a 1% threshold — deterministically, byte-identical
across two runs.

The cause is not this branch. That baseline was last regenerated on
2026-07-22 by #768 and has missed two theme changes since: #889 (opaque
neutral border tokens) and #876 (headings and body steps to font-weight 300,
body leading 1.5 → 1.375). #876 regenerated 548 baselines across three
rounds and updated this story's `--dark-tablet` file, but never the
dark-desktop one — which alone keeps the bare story id instead of a `--mode`
suffix (see .storybook/visual-modes.js), so it is the easy file to miss in a
partial regeneration. Aligning baseline to render needs a zero shift
(dx=0, dy=0); what differs is ink — text -9%, icons -7% — the lighter
weight. This branch only adds tokens, and is simply the first PR to run the
suite with #876 merged in.

Regenerated via the app-storybook-generate-baseline workflow on linux. The
`-u` path could not rewrite it on its own: stale-baseline vs clean render is
0.9875%, under the threshold, so the snapshot passed and was left alone. The
file had to be deleted so it was written as a missing snapshot. Against the
render CI actually produced, the new baseline is 0.0426% (56px).

Still stale and left alone, since both currently pass: this story's
`--dark-mobile` baseline (also 2026-07-22). Worth noting separately that the
Avatar stories source their photo from a live Unsplash URL, which
contributed the residual noise here and is what kept this story on the 1%
boundary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
isaque-bock-azion added a commit that referenced this pull request Aug 15, 2026
* feat(theme): add semantic/layouts — the container system

Ten tokens and nine `@utility` classes: how far content sits from the app
chrome (BOUNDARY), how far things sit from each other (RHYTHM), and how wide
a reading column may get (MEASURE).

A DERIVED group: every token is a var() reference to --spacing-* /
--container-*, never a literal length. That is why none carries a breakpoint
map — the spacing scale is already fluid and var() is substituted at use time
on the element, so a layout token follows the override for free. Duplicating
the scale into layout would only let the two drift.

Emitting them as `@utility` rather than `@layer components` is what gives
them variants (`md:layout-column`), the same reason the typography utilities
are emitted that way.

Generalizes the utility emitter into emitUtilities(map) with a thin
emitLayoutUtilities caller, so the shape is reusable.

Regenerating dist also picks up one line main was stale on: an emitted
comment that still read `bg-[var(--x)]` where the source has said `bg-(--x)`
since ENG-47001.

* chore(webkit): regenerate the catalog for the layout tokens

The catalog's token allowlists are scraped from the built theme, so adding
semantic/layouts adds ten --layout-* entries. Regenerated rather than
hand-edited, which is what catalog:check verifies.

* test(storybook): regenerate the avatar dark-desktop baseline for the lighter type scale

`Avatar › VariantGrid` failed the visual shard on `dark-desktop` only, at
1.0301% / 1354px against a 1% threshold — deterministically, byte-identical
across two runs.

The cause is not this branch. That baseline was last regenerated on
2026-07-22 by #768 and has missed two theme changes since: #889 (opaque
neutral border tokens) and #876 (headings and body steps to font-weight 300,
body leading 1.5 → 1.375). #876 regenerated 548 baselines across three
rounds and updated this story's `--dark-tablet` file, but never the
dark-desktop one — which alone keeps the bare story id instead of a `--mode`
suffix (see .storybook/visual-modes.js), so it is the easy file to miss in a
partial regeneration. Aligning baseline to render needs a zero shift
(dx=0, dy=0); what differs is ink — text -9%, icons -7% — the lighter
weight. This branch only adds tokens, and is simply the first PR to run the
suite with #876 merged in.

Regenerated via the app-storybook-generate-baseline workflow on linux. The
`-u` path could not rewrite it on its own: stale-baseline vs clean render is
0.9875%, under the threshold, so the snapshot passed and was left alone. The
file had to be deleted so it was written as a missing snapshot. Against the
render CI actually produced, the new baseline is 0.0426% (56px).

Still stale and left alone, since both currently pass: this story's
`--dark-mobile` baseline (also 2026-07-22). Worth noting separately that the
Avatar stories source their photo from a live Unsplash URL, which
contributed the residual noise here and is what kept this story on the 1%
boundary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com>
Co-authored-by: Isaque Böck <isaque.santos@azion.com>
Co-authored-by: robson-junior-azion <robson.junior@azion.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants