Skip to content

Add @octopusdeploy/design-system-tokens as CSS custom properties - #3257

Closed
enf0rc3 wants to merge 1 commit into
mainfrom
wl/design-system-tokens
Closed

Add @octopusdeploy/design-system-tokens as CSS custom properties#3257
enf0rc3 wants to merge 1 commit into
mainfrom
wl/design-system-tokens

Conversation

@enf0rc3

@enf0rc3 enf0rc3 commented Jul 27, 2026

Copy link
Copy Markdown

Adds @octopusdeploy/design-system-tokens to the docs site so colour, spacing, and typography values can come from the design system instead of being hand-picked.

Why not just import the tokens

The package ships no CSS. Its entry point is CommonJS, and the ergonomic exports resolve to CSS variable references, not values:

themeTokens.color.text.primary  // => "var(--colorTextPrimary)"
text.body.regular.medium        // => "var(--textBodyRegularMedium)"

The actual values live in lightTheme / darkTheme / textTheme as flat name → value maps that a consumer is expected to paint into a :root block. In the Octopus app that job belongs to the Theme component in @octopusdeploy/design-system-componentsnot a dependency here, and adding it would pull in a React + Emotion runtime this docs site has no other use for.

Without something emitting that block, importing a theme token yields var(--colorTextPrimary) against an undefined variable and silently falls back to inherited/initial.

Approach

A build-time generator emits the same custom properties as a static stylesheet. This matches how CSS already works in this repo — hand-written files in public/docs/css linked from HtmlHead.astro, no Tailwind, no SCSS, no CSS-in-JS — rather than introducing a new pattern.

  • src/themes/octopus/utilities/design-tokens.mjs → generates public/docs/css/design-tokens.css
  • 564 properties: 489 light colours/shadows, 24 typography composites, 51 theme-invariant scales
  • 413 dark overrides under html[data-theme='dark'] — the selector vars.css already uses, so both stylesheets switch off the existing toggle
  • 48KB raw / 7KB gzipped
  • Loaded before vars.css, so existing site variables stay authoritative

Names match the package's TS API exactly, so themeTokens.color.text.primaryvar(--colorTextPrimary). App-side code and the package's own guidance translate directly.

Usage

Plain CSS in any .astro file or <style> block, no imports:

color: var(--colorTextPrimary);
background: var(--colorBackgroundPrimaryDefault);
padding: var(--space-16);
border-radius: var(--borderRadius-medium);
font: var(--textBodyRegularMedium);

Verification

  • Full astro build passes — 2,696 pages, exit 0
  • design-tokens.css copied to dist/docs/css/; <link> renders in the correct position in built HTML
  • 977 declarations, balanced blocks, all terminated
  • Zero name collisions with the 154 existing vars.css variables (generated names are camelCase, existing ones kebab-case)
  • vars.css untouched — this change is visually a no-op

Notes for reviewers

  • .prettierignore is load-bearing. dev:watch and format both glob public/docs/css/**/*.css; without the exclusion prettier and the generator rewrite each other on every dev run.
  • The invariant scale names are ours. The package exposes space, borderRadius, etc. as plain literals rather than var() references, so it defines no custom property names for them. --space-16 / --borderRadius-medium follow the package's camelCase style for consistency.
  • colorScales and dialog are intentionally omitted. The package's own skill doc says raw scales are not theme-aware and should not be used in feature code; the theme tokens already resolve to those hex values.
  • ~401 of the 489 colour tokens are component-specific (--colorButtonTextPrimary, --colorBadgeBackgroundInfo, …). The package scopes those to design-system components, which this repo does not have, so they are present but inert. Cheap at 7KB gzipped. The sanctioned set for use here is --colorText* / --colorBackground* / --colorBorder* / --shadow*.
  • test runs astro build directly and so bypasses prebuild. Harmless because the generated file is committed.

Follow-up (not in this PR)

The /* TODO - update with design system */ markers at vars.css:133 and vars.css:137 are now actionable — those variables can be repointed at generated tokens.

🤖 Generated with Claude Code

The tokens package ships no CSS of its own: its ergonomic exports
(themeTokens, text, fontFamily) resolve to `var(--name)` strings, and
lightTheme/darkTheme/textTheme are the matching name -> value maps a
consumer is expected to paint into a :root block. In the Octopus app that
job belongs to the Theme component in @octopusdeploy/design-system-components,
which is not a dependency here and would pull in a React + Emotion runtime
this docs site has no other use for.

Instead, a build-time generator emits the same custom properties as a
static stylesheet, matching how this repo already does CSS (hand-written
files in public/docs/css linked from HtmlHead, no Tailwind or SCSS):

- src/themes/octopus/utilities/design-tokens.mjs generates
  public/docs/css/design-tokens.css (48KB raw, 7KB gzipped)
- 564 properties: 489 light colors/shadows, 24 typography composites,
  51 theme-invariant scales, plus 413 dark overrides
- Dark overrides use html[data-theme='dark'], the selector vars.css
  already uses, so both stylesheets switch off the existing toggle
- Loaded before vars.css, so existing site variables stay authoritative
  and this change is visually a no-op
- Names match the package's TS API, so themeTokens.color.text.primary
  translates directly to var(--colorTextPrimary)

Wired into `dev` and a `prebuild` step so the file cannot drift from the
installed package version. Excluded from prettier via .prettierignore,
since dev:watch globs public/docs/css and would otherwise fight the
generator on every dev run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@team-marketing-branch-protections

Copy link
Copy Markdown

Pull request environment is available at https://stoctodocspr3257.z22.web.core.windows.net.

You can view the ephemeral environment status in Octopus Deploy.

This environment will be automatically deprovisioned when the pull request is closed, or after 7 days of inactivity.

@enf0rc3 enf0rc3 closed this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants