Found while reviewing #348. The reporter's complaint was about their own dark: classes; the library has the same defect in its own stylesheet.
The defect
Dark mode is switched by adding .dark to <html> — theme-init.js and theme.js both do root.classList.add('dark').
But the library's Tailwind build defines no dark variant, so Tailwind v4 falls back to its default, which is the media query. Every bb:dark: utility in blazorblueprint.css compiles like this:
@media (prefers-color-scheme:dark){
.bb\:dark\:bg-blue-950{background-color:var(--bb-color-blue-950)}
...
}
So those utilities follow the operating system, not the toggle. Turn the app to dark on a machine set to light and they stay light; turn the app to light on a machine set to dark and they stay dark.
Most components are unaffected because they use CSS custom properties (--background, --foreground) that theme.js rewrites when the theme changes. Only the hard-coded dark: utilities are wrong.
Blast radius
9 distinct utilities, 14 usages, 4 components:
BbBadge — bb:dark:bg-*-950 / bb:dark:text-*-300 on the semantic variants
BbTextarea — bb:dark:bg-input
BbBubble
BbTreeView (TreeItemNode)
Reproduction
- Set the OS to light mode.
- Load the demo and toggle the app to dark with
BbDarkModeToggle.
- Look at a semantic
BbBadge, or a BbTextarea background.
- They keep their light-mode colour while everything around them is dark.
Fix
Declare the variant in blazorblueprint-input.css so it matches how the class is actually set:
@custom-variant dark (&:where(.dark, .dark *));
That makes bb:dark:* compile against .dark rather than the media query. Worth checking the 14 usages afterwards — some may have been authored against the OS behaviour by accident and will change appearance once this is correct.
The consumer half
The same trap catches anyone running their own Tailwind v4 build alongside the library, which is what #348 actually hit. Their dark:bg-none applies in light mode too, because their build has no custom variant either and the library sets a class rather than relying on the OS.
Nothing documents this. It belongs in THEMING.md and the migration guide next to the border-colour rule from #527, because it is the same shape of problem: a thing a consumer must add to their own stylesheet to make their build agree with the library's.
@layer base {
@custom-variant dark (&:where(.dark, .dark *));
}
Not a bug: the persistence half of #348
The other half of that discussion — dark mode resetting on reload or navigation — is theme-init.js missing from <head>. It is documented in README and THEMING.md and every demo host uses it. Answering that in the discussion rather than here.
Found while reviewing #348. The reporter's complaint was about their own
dark:classes; the library has the same defect in its own stylesheet.The defect
Dark mode is switched by adding
.darkto<html>—theme-init.jsandtheme.jsboth doroot.classList.add('dark').But the library's Tailwind build defines no dark variant, so Tailwind v4 falls back to its default, which is the media query. Every
bb:dark:utility inblazorblueprint.csscompiles like this:So those utilities follow the operating system, not the toggle. Turn the app to dark on a machine set to light and they stay light; turn the app to light on a machine set to dark and they stay dark.
Most components are unaffected because they use CSS custom properties (
--background,--foreground) thattheme.jsrewrites when the theme changes. Only the hard-codeddark:utilities are wrong.Blast radius
9 distinct utilities, 14 usages, 4 components:
BbBadge—bb:dark:bg-*-950/bb:dark:text-*-300on the semantic variantsBbTextarea—bb:dark:bg-inputBbBubbleBbTreeView(TreeItemNode)Reproduction
BbDarkModeToggle.BbBadge, or aBbTextareabackground.Fix
Declare the variant in
blazorblueprint-input.cssso it matches how the class is actually set:That makes
bb:dark:*compile against.darkrather than the media query. Worth checking the 14 usages afterwards — some may have been authored against the OS behaviour by accident and will change appearance once this is correct.The consumer half
The same trap catches anyone running their own Tailwind v4 build alongside the library, which is what #348 actually hit. Their
dark:bg-noneapplies in light mode too, because their build has no custom variant either and the library sets a class rather than relying on the OS.Nothing documents this. It belongs in THEMING.md and the migration guide next to the border-colour rule from #527, because it is the same shape of problem: a thing a consumer must add to their own stylesheet to make their build agree with the library's.
Not a bug: the persistence half of #348
The other half of that discussion — dark mode resetting on reload or navigation — is
theme-init.jsmissing from<head>. It is documented in README and THEMING.md and every demo host uses it. Answering that in the discussion rather than here.