Skip to content

Take the MD3 colour layer from pmndrs/design-system - #567

Closed
abernier wants to merge 2 commits into
mainfrom
md3-tier1
Closed

Take the MD3 colour layer from pmndrs/design-system#567
abernier wants to merge 2 commits into
mainfrom
md3-tier1

Conversation

@abernier

@abernier abernier commented Aug 16, 2026

Copy link
Copy Markdown
Member

PR 2 of pmndrs/design-system#1. Installs pmndrs/design-system/md3#v0.2.0.

docs stops maintaining its own copy of the colour system.

The migration

The ~60-line hand-written @theme mapping and the 33-line shadcn remap in globals.css are replaced by one registry item, pmndrs/design-system/md3. The item carries both, plus the config they map, so the mapping and the colours it names can no longer drift apart. react-mcu gives way to material-theme-builder, which is what the item installs.

Mostly a rename: --mcu-* becomes --md-sys-color-*. The --color-* names on top are identical either way, so every bg-surface, bg-primary-container and text-on-surface-variant in the codebase keeps working untouched.

The plan said "no component changes". Not quite — two components reference the raw variables rather than a Tailwind utility, Code (the prism fixed colour) and Sandpack (its three surface levels). Those four lines are the only component edits.

What Tier 1 owns, and what stays here

The first pass took the five alert colours from the design system too. It shouldn't have — note, tip, important, warning and caution are GitHub's palette, and this generator is the only thing rendering markdown alerts. pmndrs/design-system#3 pulled them back out; Tier 1 now ships the seed alone.

So they live in src/lib/mtb.ts, which spreads pmndrsMtb and adds them. Spreading rather than editing keeps src/lib/md3.ts a verbatim copy of the installed item, so updating it stays a clean overwrite. blend: true still harmonizes them against the pmndrs seed, and THEME_NOTE and its four siblings still override them.

Their twenty @theme lines moved out of the shadcn-managed block into one of ours, commented. The config and the mapping have to be read together: a name declared in one and missing from the other makes Tailwind emit no rule at all, with no error — so they should not be a block apart with shadcn free to rewrite one of them.

The seed

It moves to poimandres mint, #5de4c7. This is the one visible change — everything else is meant to render identically.

It also stops being restated. The seed lived in layout.tsx, again in build.yml's input defaults, and hard-coded a third time in ci.yml — three copies free to disagree, which is exactly what the plan flagged. Now src/lib/md3.ts holds it, installed from Tier 1, and the workflow inputs default to empty. A site overrides the seed by setting one; a site that leaves it alone inherits the pmndrs default. THEME_PRIMARY, THEME_SCHEME, THEME_CONTRAST and the five alert colours behave as before.

Worth a second look, since build.yml is reusable and other repos call it: the defaults it used to hand out are now the design system's rather than its own.

The preset

apply b5cR4Y50S --only theme. Close to a no-op here, by design — radius already matched at 0.625rem, the colour half is overridden by the remap on the next line, and the font half is deliberately left out because docs self-hosts Inter and Inconsolata. What it does land is the identity in components.json and a --sidebar* block in oklch instead of hsl.

Two things to know if you re-run the CLI here. apply writes the palette into the first :root it finds, which here is the layout block holding --rgrid-m and scroll-behavior, not the shadcn one further down — which then wins, being later. I moved the values into the shadcn block and restored the layout one. And add matches its :root, .dark block on the exact selector string, which prettier reformats to :root,\n.dark on commit — so re-installing the item appends a second, identical copy. Worth a glance at the diff after either command.

Verification

  • No token lost. All 67 --color-* names the old mapping defined are among the 191 the new one defines.
  • The five alert colours resolve end-to-end after the move: bg-note-container and bg-tip-container emit rules, and --md-sys-color-{note,tip,important,warning,caution}-container are all server-rendered.
  • Full build green, and the rendered output is mint: --md-ref-palette-primary-40: #086b5a, with 69 sys-colour and 308 palette variables server-rendered.
  • bg-surface-dim, bg-note-container, bg-tip-container and text-primary-fixed all emit rules. The custom colours were the fragile part — the package's tailwind.css covers standard M3 roles only, and Tailwind drops an unknown utility with no error — so they were checked by name rather than assumed.
  • tsc clean. lint reports two react/no-unescaped-entities in src/stories/Page.tsx; both pre-date this branch, verified against main.

The preview deploy is the real check: this should be a visual no-op apart from the seed, and the five alert colours deserve a specific look.

Known, not fixed here

material-theme-builder's shipped dist/tailwind.css contains its own README's example custom colours (--color-myCustomColor1 / 2), so docs now carries 24 dead variables. Harmless, upstream, worth an issue there.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EDvnsrory1aJsoNALn5aLB

docs stops maintaining its own copy of the colour system. The ~60-line
hand-written @theme mapping and the 33-line shadcn remap in globals.css
are replaced by one registry item, pmndrs/design-system/md3, which
carries both plus the config they map — so they can no longer drift from
each other. react-mcu gives way to material-theme-builder, which is what
that item installs.

Mostly a rename: --mcu-* becomes --md-sys-color-*. The --color-* names in
the @theme mapping are identical either way, so every bg-surface,
bg-primary-container and text-on-surface-variant keeps working untouched.
Two components referenced the raw variables rather than a utility — Code
and Sandpack — and those are the only component edits.

The seed moves to poimandres mint. It also stops being restated: it lived
in the layout, in build.yml's input defaults and hard-coded again in
ci.yml, three copies free to disagree. Now src/lib/md3.ts holds it and
the workflow inputs default to empty, so a site overrides the seed by
setting one and inherits the pmndrs default by leaving it alone.

Also applies the poimandres preset. It is close to a no-op here by
design: radius already matched, the colour half is overridden by the
remap, and the font half is deliberately not applied because docs
self-hosts Inter and Inconsolata. What it does land is the identity in
components.json and a --sidebar* block in oklch rather than hsl.

Verified: no token lost — all 67 --color-* names the old mapping defined
are in the 191 the new one does — and a full build renders mint, with
bg-surface-dim, bg-note-container and text-primary-fixed all emitting.

Refs pmndrs/design-system#1

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EDvnsrory1aJsoNALn5aLB
Follows pmndrs/design-system#3. note, tip, important, warning and
caution are GitHub's palette, and this generator is the only thing
rendering markdown alerts — they were never the design system's to
carry. Tier 1 now ships the seed alone, at v0.2.0.

src/lib/mtb.ts spreads pmndrsMtb and adds the five, so src/lib/md3.ts
stays a verbatim copy of the installed item and updating it remains a
clean overwrite. blend: true still harmonizes them against the seed, and
THEME_NOTE and its four siblings still override them.

Their twenty @theme lines move out of the shadcn-managed block into one
of our own, commented, next to nothing else — the config and the mapping
have to be read together, since a name declared in one and missing from
the other makes Tailwind emit no rule at all, without an error.

Refs pmndrs/design-system#1

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EDvnsrory1aJsoNALn5aLB
@abernier

Copy link
Copy Markdown
Member Author

Collapsed into #570, which now targets main and carries all five commits of this stack. Nothing dropped — the whole narrative moved there.

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