fix(ui): make dark-mode form controls visible (#37648)

* fix(ui): make dark-mode form controls visible

Two dark-mode defects left form controls without any visual boundary or fill.

`--input` and `--border` share one value in `.dark`, oklch(0.309), which resolves to
rgb(48,48,48). Against `--background` (33) that is a 15-step stroke, and against `--popover` (42)
it collapses to 6 steps out of 255, so a control inside any dialog is effectively undrawn. The
controls also use `bg-transparent`, so there is no fill cue either and only the placeholder text
renders. Measured 1.09:1 against the dialog surface where WCAG 1.4.11 asks for 3.0:1 on the
boundary of a user interface component. Splitting `--input` off at oklch(0.56) restores 3.07:1
without touching `--border`, which stays where it is because it draws decorative separators rather
than control boundaries. 91 controls across 19 routes were measured at the collapsed value, every
one with an identical stroke and surface, so a single token covers all of them.

Separately, `@tailwindcss/forms` paints a white fill on every bare control. The block above
already neutralises that for `combobox-chip-input`, but its audit covered `components/ui` only,
and hand-rolled controls elsewhere still render white on a dark page: typed text lands at 1.11:1
and native selects at 2.19:1 on `/model-hub-table`, `/playground`, `/guardrails`, `/mcp-servers`
and `/models-and-endpoints`. Tracking `--background` fixes those at 14.51:1 and 7.34:1.

Light mode is unchanged by both. The token edit is scoped to `.dark`, and `--background` in
`:root` is the same white the plugin was already painting, verified control-by-control on a dev
server: backgrounds stay rgb(255,255,255) and ratios stay 20.13:1 and 4.84:1.

* fix(ui): keep the combobox chip input transparent under the bare-control fill

The new base rule matched at (0,2,1) while the combobox chip-input override
sits at (0,1,0), so ComboboxChipsInput lost its transparent background and
painted an opaque page-colored rectangle inside the chips container, which
carries its own bg-transparent / dark:bg-input/30 fill.

Folding the exclusions into one :not() list adds the chip input and drops the
selector to (0,1,1). Every @tailwindcss/forms base selector is wrapped in
:where(), so it lands at (0,0,1); (0,1,1) still outweighs it and bare inputs,
textareas and selects keep the fill this PR gives them.
This commit is contained in:
yuneng-jiang 2026-08-20 10:58:27 -07:00 • committed by GitHub
parent d2d158f271
commit e12833e6b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -134,7 +134,7 @@
--warning: oklch(0.828 0.189 84.429);
--info: oklch(0.707 0.165 254.624);
--border: oklch(0.309 0 0);
--input: oklch(0.309 0 0);
--input: oklch(0.56 0 0);
--ring: oklch(0.569 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
@ -230,6 +230,13 @@
letter-spacing: inherit;
}
/* Same plugin's white fill, on the hand-rolled controls outside components/ui that the audit
above did not cover. Tracks --background so light mode keeps the white it already painted.
Delete along with the plugin. */
:is(input, textarea, select):not([type="checkbox"], [type="radio"], [data-slot="combobox-chip-input"]) {
background-color: var(--color-background);
}
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;