Skip to content

feat(tokens): add saturated surface tokens for danger/success/warning/info#7439

Closed
talissoncosta wants to merge 1 commit intomainfrom
refactor/add-saturated-surface-tokens
Closed

feat(tokens): add saturated surface tokens for danger/success/warning/info#7439
talissoncosta wants to merge 1 commit intomainfrom
refactor/add-saturated-surface-tokens

Conversation

@talissoncosta
Copy link
Copy Markdown
Contributor

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to `docs/` if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

TL;DR. Adds 12 saturated surface tokens (4 intents × 3 states) so danger/success/warning/info buttons can use semantic tokens instead of hardcoded hex. Pure additive — no consumers wired up yet.

Why

The token system had asymmetric intent coverage:

Intent Surface tokens Gap
action subtle, muted, base, hover, active ✓ complete
danger subtle (0.08 α) only no saturated
success subtle (0.08 α) only no saturated
warning subtle (0.08 α) only no saturated
info subtle (0.08 α) only no saturated

That forced `_variables.scss` to fill the gap with hardcoded hex (`$btn-danger-hover: #cd384d;`) and primitive references (`$btn-success-hover: $success;`), silently bypassing the token system for every saturated intent button.

What's new

12 new tokens using the `Strong` qualifier already in use by `colorBorderStrong`:

```
--color-surface-{intent}-strong # saturated bg
--color-surface-{intent}-strong-hover # hover state
--color-surface-{intent}-strong-active # active state
```

For each of `danger`, `success`, `warning`, `info`. Light theme uses the `{intent}-500/600/700` primitive scale; dark theme shifts one step lighter (`-400/500/600`) for contrast — same pattern `action` already follows.

Why `Strong` instead of other naming

  • `colorBorderStrong` already uses this convention in the project — no new word to learn.
  • Maps cleanly to mature design systems: GitHub Primer's `emphasis`, Material 3's `error` (vs `errorContainer`), Carbon's `bg` (vs `background`). They all distinguish foreground-saturated from backdrop-subtle.
  • Read aloud: "the danger surface, but stronger" — natural.

Why `action` stays without a `Strong` qualifier

The `action` intent's saturated colour is its default `colorSurfaceAction` (no qualifier). Adding a `Strong` qualifier there would be a breaking rename for zero semantic gain. The asymmetry is honest — `action` is the brand's primary surface and the default; other intents are secondary and need explicit qualification.

How did you test this code?

  • `npm run generate:tokens` regenerated the four downstream files cleanly (tokens.ts, _tokens.scss, _token-utilities.scss, TokenReference.generated.stories.tsx).
  • `git diff --stat` confirms changes are isolated to the 5 token files.
  • Pure additive — no existing tokens renamed or removed, no consumer code touched. Visual diff on Chromatic should be zero.
  • Phase 1 of a three-PR sequence: this adds the tokens, [Phase 2] migrates _buttons.scss to use them, [Phase 3] extracts a DocsLink component. See investigation document for the full design rationale.

…/info

The action intent has a complete surface family (subtle, muted, base,
hover, active) — every other intent only had the subtle 0.08-alpha
tint. That asymmetry forced the design system to fill the gap with
hardcoded hex colours and primitive references in _variables.scss
($btn-danger-hover, $btn-success-active, etc.) — silently bypassing
the token system for every saturated intent button.

Adds 12 new surface tokens (4 intents × 3 states) using the `Strong`
qualifier already in use by colorBorderStrong:

  --color-surface-{intent}-strong          # saturated bg
  --color-surface-{intent}-strong-hover    # hover state
  --color-surface-{intent}-strong-active   # active state

Light theme uses the {intent}-500/600/700 primitive scale; dark
theme shifts one step lighter (-400/500/600) for contrast — same
pattern action follows.

Pure additive change. Auto-generated tokens.ts, _tokens.scss,
_token-utilities.scss, and TokenReference.generated.stories.tsx
follow from `npm run generate:tokens`.

Action intent stays asymmetric (no Strong qualifier) — its base is
already the saturated brand surface, no rename needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment May 6, 2026 1:05pm
flagsmith-frontend-staging Ready Ready Preview, Comment May 6, 2026 1:05pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview May 6, 2026 1:05pm

Request Review

@talissoncosta
Copy link
Copy Markdown
Contributor Author

Closing in favour of a documented design plan for Button + Link before further code changes. The implementation here was outpacing the architectural decisions — pausing the code, will reopen replacements once the plan is agreed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant