fix(ui): dark mode white dropdown on language and timezone selects (#255)

* fix(ui): use color-scheme dark for select dropdowns in dark mode

Language and timezone selects rendered with white native dropdown in
dark mode because browser ignores CSS bg-transparent on <option>.
Adding dark:scheme-dark tells the browser to render the native select
dropdown using dark color scheme in dark mode.

* fix(ui): replace native select with Radix UI Select for dark mode fix

Native <select> dropdown ignores CSS styling — browser always renders
the popup with its default (light) color scheme, causing white box in
dark mode. Replace language and timezone selectors with Radix UI Select
which renders custom HTML/CSS dropdowns that fully respect dark mode.

- Use bg-popover/text-popover-foreground from ui/select.tsx (dark-aware)
- Remove unused handleLanguageChange handler
- Use Tailwind v4 canonical **:data-radix-select-icon:hidden to hide chevron
This commit is contained in:
Nguyễn Hoàng Thức authored and GitHub committed 2026-03-18 16:38:33 +07:00
1 parent 2141852945
commit b7d8d52f5e
1 file changed
+23 -22
+23 -22
View File
@@ -6,6 +6,7 @@ import { useAuthStore } from "@/stores/use-auth-store";
import { useIsMobile } from "@/hooks/use-media-query";
import { usePendingPairingsCount } from "@/hooks/use-pending-pairings-count";
import { ROUTES, SUPPORTED_LANGUAGES, LANGUAGE_LABELS, TIMEZONE_OPTIONS, type Language } from "@/lib/constants";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
export function Topbar() {
const { t } = useTranslation("topbar");
@@ -29,10 +30,6 @@ export function Topbar() {
? () => setMobileSidebarOpen(true)
: toggleSidebar;
const handleLanguageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setLanguage(e.target.value as Language);
};
return (
<header className="flex h-14 items-center justify-between border-b bg-background px-4 landscape-compact">
<div className="flex items-center gap-2">
@@ -63,31 +60,35 @@ export function Topbar() {
)}
</button>
<div className="flex items-center gap-1 rounded-md px-2 py-1.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground" title={t("language")}>
<Globe className="h-4 w-4 shrink-0" />
<select
value={language}
onChange={handleLanguageChange}
className="cursor-pointer bg-transparent text-xs outline-none"
<Select value={language} onValueChange={(v) => setLanguage(v as Language)}>
<SelectTrigger
title={t("language")}
className="h-auto w-auto gap-1 border-0 bg-transparent px-2 py-1.5 text-xs text-muted-foreground shadow-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-0 dark:bg-transparent dark:hover:bg-accent **:data-radix-select-icon:hidden"
>
<Globe className="h-4 w-4 shrink-0" />
<SelectValue />
</SelectTrigger>
<SelectContent>
{SUPPORTED_LANGUAGES.map((lang) => (
<option key={lang} value={lang}>{LANGUAGE_LABELS[lang]}</option>
<SelectItem key={lang} value={lang}>{LANGUAGE_LABELS[lang]}</SelectItem>
))}
</select>
</div>
</SelectContent>
</Select>
<div className="flex items-center gap-1 rounded-md px-2 py-1.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground" title={t("timezone")}>
<Clock className="h-4 w-4 shrink-0" />
<select
value={timezone}
onChange={(e) => setTimezone(e.target.value)}
className="cursor-pointer bg-transparent text-xs outline-none"
<Select value={timezone} onValueChange={setTimezone}>
<SelectTrigger
title={t("timezone")}
className="h-auto w-auto gap-1 border-0 bg-transparent px-2 py-1.5 text-xs text-muted-foreground shadow-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-0 dark:bg-transparent dark:hover:bg-accent **:data-radix-select-icon:hidden"
>
<Clock className="h-4 w-4 shrink-0" />
<SelectValue />
</SelectTrigger>
<SelectContent>
{TIMEZONE_OPTIONS.map((tz) => (
<option key={tz.value} value={tz.value}>{tz.label}</option>
<SelectItem key={tz.value} value={tz.value}>{tz.label}</SelectItem>
))}
</select>
</div>
</SelectContent>
</Select>
<button
onClick={() => setTheme(isDark ? "light" : "dark")}