Skip to content

fix: import the dark counterparts of the admonition colour scales - #966

Merged
petyosi merged 2 commits into
mdx-editor:mainfrom
danielloader:fix/dark-theme-select-and-admonition-surfaces
Sep 9, 2026
Merged

petyosi merged 2 commits into
mdx-editor:mainfrom
danielloader:fix/dark-theme-select-and-admonition-surfaces

Conversation

@danielloader

@danielloader danielloader commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Narrows #921 to the missing admonition dark scales, per your review.

src/styles/globals.css imported blue and slate both ways, and grass, cyan, amber and red light-only. Those four feed the tip, info, caution and danger admonition tokens, so under dark-theme the scale had no dark steps to switch to and the four bands kept their light values. note derives from slate, imported both ways, which is why it was the one admonition that already looked right.

  @import url('@radix-ui/colors/grass.css');
+ @import url('@radix-ui/colors/grass-dark.css');
  @import url('@radix-ui/colors/cyan.css');
+ @import url('@radix-ui/colors/cyan-dark.css');
  @import url('@radix-ui/colors/amber.css');
+ @import url('@radix-ui/colors/amber-dark.css');
  @import url('@radix-ui/colors/red.css');
+ @import url('@radix-ui/colors/red-dark.css');

Screenshots

compare-light compare-dark

Measured

A band is decoration around the nested editor, not a text background — the admonition's text sits on --basePageBg and measures 15.60:1 either way. So the thing that breaks is the band's relationship to the surface it frames: a subtle tint in light mode, a bright block in dark.

admonition light mode (intended) dark, before dark, after
tip (cyan) 1.21:1 15.65:1 1.49:1
info (grass) 1.19:1 15.79:1 1.51:1
caution (amber) 1.17:1 16.13:1 1.35:1
danger (red) 1.28:1 14.75:1 1.28:1

Ratios are sRGB, band step 4 against the editor surface. Radix ships color(display-p3 …) overrides for every scale, including these four, so a wide-gamut display paints slightly different values — the same caveat that already applies to blue and slate.

Light mode is untouched: *-dark.css scopes every declaration to .dark, .dark-theme and declares nothing on :root.

Also corrected

src/examples/dark-editor.css used the pre-v3 unhyphenated names — --cyan4, --grass8 and so on — which Radix v3 spells --cyan-4, --grass-8. Renamed the eight of them. With the dark scales now imported, that example's admonition overrides resolve as intended.

Tests

src/test/theme-tokens.test.ts asserts one invariant: every Radix scale imported light is also imported dark. Reverting the four imports makes it fail and name them:

expected [ 'grass', 'cyan', 'amber', 'red' ] to deeply equal []

I dropped the second check from the earlier revision. You were right that requiring every semantic colour token to point at a scale step rejects the mutable-alias pattern — which is the pattern --basePageBg exists to support.

Demo

src/examples/bug-921.tsx, following the bug-NNN convention:

  • Bug 921 → Dark theme surfacesdark-theme, a toolbar with BlockTypeSelect and InsertAdmonition, and all five admonitions. The page supplies its background and maps --basePageBg; nothing else is overridden.
  • Bug 921 → Light theme surfaces — the same editor without the class. Both share the page inset so the two can be compared by flipping between them.

Checks

npm run typecheck, npm run lint, npm run test:once and npm run test:browser -- --project=chromium. Firefox and WebKit not run — not installed here.

@petyosi

petyosi commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for the detailed investigation. I looked deeper into the original theming intent and the earlier history around this behavior.

My verdict is that #921 combines two different cases:

  • The missing dark imports for cyan, grass, amber, and red are a valid bug. These are Radix scale variables used by the default admonition tokens, so their dark counterparts should be imported. I am in favor of keeping those four imports.
  • The --basePageBg behavior is intentional and should remain consumer-configurable. This is the same behavior addressed in Improper styles in dark theme: BlockTypeSelect and linkDialogPlugin #225: the dark-theme example explicitly maps --basePageBg to a dark value. That follows the Radix recommendation for cases where an app uses white in light mode and a gray scale value in dark mode: define a mutable semantic alias and map it per color mode. Changing the default to var(--slate-1) instead changes the existing contract and also changes the light-mode surface from white to slate step 1.

Please keep the dark-scale imports, but revert the --basePageBg default change. The new test should also not require every semantic color token to point directly to a Radix scale step, because that rejects the mutable-alias pattern recommended by Radix.

There are two closely related corrections worth making here:

  • The existing theming example and documentation use obsolete names such as --cyan4, --grass4, and --red8; Radix v3 uses --cyan-4, --grass-4, and --red-8.
  • An unresolved nested var() does not fall through to the lower .editorRoot custom-property declaration; it makes the consuming CSS property invalid. The PR description should not rely on that explanation.

Radix reference: https://www.radix-ui.com/colors/docs/palette-composition/understanding-the-scale
Earlier issue: #225

I suggest narrowing #921 to the missing admonition dark scales and treating the select/background portion as the documented configuration from #225.

@danielloader

danielloader commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

That's fair, thanks for the review, will action those suggestions shortly.

edit: all done for review.

`globals.css` imported `blue` and `slate` both ways and `grass`, `cyan`,
`amber` and `red` light-only. Radix defines a scale's dark steps in a separate
file scoped to `.dark, .dark-theme`, so those four had no dark steps to switch
to and the tip, info, caution and danger bands kept their light values under
`dark-theme`. `note` derives from `slate` and was therefore the one admonition
that already looked right.

A band is decoration rather than a text background, so what breaks is its
relationship to the surface it frames: a subtle tint in light mode (1.17-1.28:1
against white) became a bright block in dark (14.75-16.13:1 against the editor
surface), and is a tint again with the dark steps imported (1.28-1.51:1).

Light mode is untouched — `*-dark.css` declares nothing on `:root`.

Also renames the pre-v3 unhyphenated Radix variables in the dark-theme example
(`--cyan4` → `--cyan-4`, and the seven others). With the dark scales imported,
that example's admonition overrides now resolve as intended.

Adds `src/examples/bug-921.tsx`, which maps `--basePageBg` itself as a consumer
does — see mdx-editor#225 — so the story isolates the scales.
Importing a scale's light stylesheet without its dark one leaves the tokens
deriving from it unable to follow `dark-theme`, which is the defect behind the
four light admonition bands. Reverting the imports makes this fail and name
them.

It asserts nothing about what a semantic token points at: `--basePageBg` is a
mutable alias a consumer maps per colour mode, and a check requiring scale
steps would reject that pattern.
@danielloader
danielloader force-pushed the fix/dark-theme-select-and-admonition-surfaces branch from 0b1ab50 to d934c8d Compare September 8, 2026 08:13
@danielloader danielloader changed the title fix: make the select and admonition surfaces follow dark-theme fix: import the dark counterparts of the admonition colour scales Sep 8, 2026
@petyosi
petyosi merged commit eebafea into mdx-editor:main Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 4.2.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants