Skip to content

Commit cb21525

Browse files
committed
fix(react): keep native select options readable in dark mode
The native <select> option popup follows the control's opaque background and color-scheme, not option-level styles. bg-transparent left the popup white, so dark-mode options rendered near-white text on a white surface. The dark:bg-input/30 fallback never applied: the dark: variant is gated on a .dark ancestor class this app never sets (theming is prefers-color-scheme driven). Give the select a solid themed surface (bg-popover/text-popover-foreground), add a hover:bg-accent state, and pin color-scheme via useIsDark so the native popup follows the active theme. Fixes the Resume approvals dropdown in setup-mcp and mcp-install-card, and every other NativeSelect. Closes #1227
1 parent 1c1051c commit cb21525

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@executor-js/react": patch
3+
---
4+
5+
Keep native `<select>` dropdown options readable in dark mode. The console themes through `prefers-color-scheme` and never sets a `.dark` class, so Tailwind `dark:` utilities never matched and the native option popup rendered with a light color scheme over dark text. `NativeSelect` now uses a solid themed surface (`bg-popover`) and pins `color-scheme` to the active theme, so the browser draws a matching, readable popup.

packages/react/src/components/native-select.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
import * as React from "react";
22
import { ChevronDownIcon } from "lucide-react";
33

4+
import { useIsDark } from "../hooks/use-is-dark";
45
import { cn } from "../lib/utils";
56

67
function NativeSelect({
78
className,
89
size = "default",
10+
style,
911
...props
1012
}: Omit<React.ComponentProps<"select">, "size"> & { size?: "sm" | "default" }) {
13+
const isDark = useIsDark();
1114
return (
1215
<div
1316
className="group/native-select relative w-fit has-[select:disabled]:opacity-50"
1417
data-slot="native-select-wrapper"
1518
>
19+
{/* The native option popup follows the select's opaque background and
20+
color-scheme, not option-level styles. Give it a solid themed surface
21+
and pin color-scheme so options stay readable in dark mode, which is
22+
driven by prefers-color-scheme (no .dark class in this app). */}
1623
{/* oxlint-disable-next-line react/forbid-elements */}
1724
<select
1825
data-slot="native-select"
1926
data-size={size}
27+
style={{ colorScheme: isDark ? "dark" : "light", ...style }}
2028
className={cn(
21-
"h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1 dark:bg-input/30 dark:hover:bg-input/50",
29+
"h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-popover text-popover-foreground px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground hover:bg-accent disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1",
2230
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
2331
"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
2432
className,

0 commit comments

Comments
 (0)