ReviewOS

stacks/stx

12 components use `blue-gray-*` (Tailwind v2) — no CSS is generated, so form inputs have no dark mode

#1976
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Summary

Twelve components style their dark mode with blue-gray-*, a palette name from Tailwind v2 that no longer exists. It generates no CSS, so those elements have no dark-mode background at all — they fall through to bg-white and render as white boxes on a dark page.

Every form control in the library is affected: Select, TextInput, PasswordInput, NumberInput, Textarea.

Evidence

packages/components/src/ui/select/Select.stx renders:

<select class="… dark:bg-blue-gray-700 dark:text-gray-100 … bg-white dark:bg-blue-gray-700 …">

In the generated stylesheet for a page containing that element:

$ grep -c 'blue-gray' css.<hash>.css
0

No rule, so bg-white wins in both modes. Screenshot: a <Select placeholder="Pick a sport" /> on a dark:bg-slate-950 page is a solid white bar.

Scope

51 uses across 12 files:

ui/select/Select.stx
ui/input/TextInput.stx
ui/input/PasswordInput.stx
ui/input/NumberInput.stx
ui/textarea/Textarea.stx
ui/drawer/Drawer.stx
ui/auth/Login.stx
ui/auth/Signup.stx
ui/auth/TwoFactorChallenge.stx
ui/payment/SubscriptionCheckout.stx
ui/payment/PaymentMethods.stx
ui/payment/DefaultPaymentMethod.stx

Suggested fix

blue-gray was renamed slate in Tailwind v3. A straight blue-gray-N → slate-N substitution restores the intended appearance.

Better, given packages/stx/src/theme-tokens.ts already ships role tokens that resolve through var(--stx-*): these are all surfaces and borders, so bg-surface-raised / border-line-strong would make them themeable by a host app at the same time. Drawer.stx already documents exactly this problem in its own header comment — "the panel painted itself bg-white dark:bg-blue-gray-800 and offered no way to say otherwise" — and solved it with a panelClass seam; the inputs have no equivalent.

Worth a CI guard afterwards: a test that greps the built CSS for every utility the components emit would have caught this and #1977 at the commit that introduced them.

Environment

  • @stacksjs/components 0.2.339, stacks 0.75.31, Crosswind
  • Found while migrating hq.training onto the component library.
9 days ago

Re-tested on 0.2.343 — still reproduces, and I can put a number on the outcome.

blue-gray-* generates zero rules in the compiled stylesheet:

(css.match(/blue-gray/g) || []).length   // → 0

So the dark-mode classes on TextInput, Select, Textarea and NumberInput resolve to nothing. Measured computed styles, .dark active, against the app's own input for comparison:

backgroundtext
<TextInput>rgb(255, 255, 255)oklab(0.966 …)
<Select>rgb(255, 255, 255)oklab(0.966 …)
<Textarea>rgb(255, 255, 255)oklab(0.966 …)
<NumberInput>rgb(255, 255, 255)oklab(0.966 …)
oursoklch(0.208 0.042 265.755)rgb(255, 255, 255)

That is near-white text on a white background — not "off-brand", unreadable. The text colour comes through from a role token while the background falls back to the light default, so the two disagree.

This is the single blocker that keeps the largest surface out of reach for us: 287 form controls, against 6 tables and a handful of menus. Everything else in our Phase 4 is smaller than this one item.

Worth noting the fix may be a one-line palette alias rather than 12 component edits — blue-gray was Tailwind v2's name for what v3 calls slate, so mapping the family would make all 12 render correctly and keep the components' own intent intact.

Sign in to comment on this issue.