Skip to content

feat(tailwind,design-tokens): Untitled UI Tailwind 4 adoption path - #6849

Draft
Kitty-Al wants to merge 4 commits into
AI-week-semanticfrom
AI-week-untitled-ui-tw4
Draft

feat(tailwind,design-tokens): Untitled UI Tailwind 4 adoption path#6849
Kitty-Al wants to merge 4 commits into
AI-week-semanticfrom
AI-week-untitled-ui-tw4

Conversation

@Kitty-Al

@Kitty-Al Kitty-Al commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What

Adds an Untitled UI (UUI) adoption path for Tailwind 4, layered on top of the semantic colour tokens from the base branch. Nothing current consumers use changes — TW3, TW4-via-@config, SCSS, CSS and JS all keep working. UUI is a side path today and the eventual primary path as @kaizen/components migrates to UUI and consumers standardise on TW4.

Background

UUI declares its semantic tokens as --color-bg-primary, --color-text-primary, --color-fg-primary, --color-border-primary inside a TW4 @theme block, so TW4 generates a doubled class form (bg-bg-primary, text-fg-primary, border-border-secondary) with no fg-* utility. Kaizen deliberately ships the clean form (bg-primary, fg-primary, …). This PR bridges the two without adopting the doubled names.

Changes

  • @kaizen/tailwind — UUI class transform (scripts/transform-untitled-ui-classes.mjs, pnpm transform:untitled-ui): rewrites UUI's doubled classes to Kaizen's clean form on adoption — bg-bg-*bg-*, text-text-*text-*, border-border-*border-*, text-fg-*fg-* — preserving variants, !important and any Tailwind prefix. Unit-tested (30 cases).
  • @kaizen/design-tokenscss/untitled-ui-vars.css: aliases UUI's --color-* var names to Kaizen semantic vars (--color-bg-primary: var(--bg-primary);) so UUI code referencing vars directly resolves to Kaizen values.
  • @kaizen/design-tokenscss/tailwind-v4.css: TW4-native (>=4.1) @utility entrypoint so pure CSS-first consumers get Kaizen's clean semantic utilities with no @config bridge.
  • Docs: packages/tailwind/docs/untitled-ui-tw4.md — consumer guide covering all paths.

All three generated files derive from a single token source (semanticColorTokens.ts), so they never drift. tailwind-v4.css verified compiling on Tailwind 4.2.4 (clean names, underscore names like bg-secondary_hover, and variants like hover:bg-primary all emit).

Toward dark mode — why the utilities point at the semantic var

Each @utility intentionally points at its semantic var, not the underlying primitive:

@utility border-brand_alt { border-color: var(--border-brand_alt); }   /* stable — never changes */

That indirection is a deliberate seam. The class name and the var name stay fixed; only what the var resolves to flips per context:

:root                    { --border-brand_alt: var(--color-blue-500); }
[data-color-mode="dark"] { --border-brand_alt: var(--color-blue-300); }  /* same var, different primitive */

So when dark mode (and the RFC's palette flip) land, they override the semantic var and every utility repaints with no change to consumer markup. Baking the primitive into the utility (border-color: var(--color-blue-500)) would remove that override point — dark mode overrides the semantic layer, not primitives (you don't want the primitive blue-500 itself to change). This PR keeps that door open.

Verification

  • pnpm --filter @kaizen/tailwind test — 30/30 transform tests pass.
  • pnpm --filter @kaizen/design-tokens build:semantic — regenerates all three CSS files (51 tokens, nulls skipped).
  • tailwind-v4.css compiled against Tailwind 4.2.4 via the PostCSS/compile() path — utilities emit correctly.

Not included (deliberate)

  • rem↔px spacing normalisation (separate concern; the transform is colour-only).
  • Dark mode / palette-flip overrides themselves (this PR only preserves the seam for them).

🤖 Generated with Claude Code

Layer a UUI-on-TW4 adoption path on top of the existing semantic colour
tokens. Current consumers (TW3, TW4-via-@config, SCSS, CSS, JS) are unchanged.

- @kaizen/tailwind: transform-untitled-ui-classes.mjs codemod strips UUI's
  doubled class form to Kaizen's clean form (bg-bg-*->bg-*, text-fg-*->fg-*,
  border-border-*->border-*, text-text-*->text-*), preserving variants,
  important and any TW prefix. Unit-tested (30 cases).
- @kaizen/design-tokens: generate css/untitled-ui-vars.css (aliases UUI's
  --color-* var names to Kaizen semantic vars) and css/tailwind-v4.css
  (TW4.1+ @Utility entrypoint for pure CSS-first consumers).

All generated from semanticColorTokens.ts, so no drift. tailwind-v4.css
verified compiling on Tailwind 4.2.4. Utilities point at the semantic var,
not the primitive, to keep the override seam for dark mode / palette flip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pip-the-concierge

Copy link
Copy Markdown
Contributor

🤖 Agent Workflows

  • PR Review — AI-powered code review

@changeset-bot

changeset-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6ee78bd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@kaizen/design-tokens Minor
@kaizen/tailwind Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Kitty-Al and others added 3 commits July 1, 2026 16:22
Storybook MDX guide (Guides/Untitled UI on Tailwind 4) covering the UUI
adoption path: the class transform, the var-compat file, the pure-TW4
@Utility entrypoint, and why utilities point at the semantic var (dark-mode
override seam). Replaces the earlier standalone markdown draft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… drop codemod

Replace the one-time class codemod with build-time aliasing so raw Untitled
UI components resolve against Kaizen colours with no consumer action.

- tailwind-presets.ts: each semantic theme map now emits both the clean class
  (bg-primary) and the UUI doubled class (bg-bg-primary) via a fullKeyMap
  helper; foreground keys exposed under textColor so text-fg-* resolves.
- buildSemanticTokens.ts: tailwind-v4.css emits both clean and doubled
  @Utility blocks (fg via text-*).
- Remove transform-untitled-ui-classes.mjs + spec and its package.json wiring.
- Docs + changeset updated to the no-codemod approach.

Both forms point at the same var(--token), preserving the semantic-var seam
for dark mode / palette flip. Verified on Tailwind 4.2.4 (clean + doubled,
incl. hover). Preset typechecks; package tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant