Dark mode shipped in #59, but the popup-layer primitives in src/components/ui/ (exempt from check:colors, so the guard never caught them) and one raw <select> in app code still hardcode light-theme colors. In dark mode these render as white boxes with light-gray text.
Findings
web/src/components/ui/tooltip.tsx:25 — TooltipPopup uses bg-white and inherits no foreground token:
web/src/components/ui/toast.tsx:17-19, 31, 37 — toast root uses bg-white, border-red-300 / border-green-300, description text-neutral-700, close button text-neutral-400 hover:text-neutral-700:
→ bg-popover text-popover-foreground, border-destructive / border-success, text-muted-foreground hover:text-foreground. While in there: the close button renders a literal × glyph — swap to the lucide <X className="size-4" aria-hidden /> icon used by detail-drawer.tsx for visual consistency (the aria-label is already correct).
web/src/objects/objects-table.tsx:290 — the page-size <select> in the table footer uses bg-white in app code. check:colors doesn't flag it because its regex only matches palette-shade pairs (white has no shade). → bg-background (or replace with the ui Select, cf. #51).
web/index.html — head has the theme preload script but no browser-chrome integration:
add <meta name="color-scheme" content="light dark"> so native form controls/scrollbars follow the theme,
add <meta name="theme-color"> with light + dark media variants.
Suggested follow-up guard
Consider extending scripts/check-no-raw-colors.mjs to also match bg-white/text-black-style literals outside src/components/ui/, so the objects-table case can't recur.
All tokens needed (--color-popover, --color-accent, --color-destructive, --color-success) already exist in src/index.css@theme inline — this is purely a class swap.
Dark mode shipped in #59, but the popup-layer primitives in `src/components/ui/` (exempt from `check:colors`, so the guard never caught them) and one raw `<select>` in app code still hardcode light-theme colors. In dark mode these render as white boxes with light-gray text.
## Findings
**`web/src/components/ui/tooltip.tsx:25`** — `TooltipPopup` uses `bg-white` and inherits no foreground token:
```
"rounded border bg-white px-2 py-1 text-sm shadow-md"
```
→ `bg-popover text-popover-foreground`.
**`web/src/components/ui/toast.tsx:17-19, 31, 37`** — toast root uses `bg-white`, `border-red-300` / `border-green-300`, description `text-neutral-700`, close button `text-neutral-400 hover:text-neutral-700`:
→ `bg-popover text-popover-foreground`, `border-destructive` / `border-success`, `text-muted-foreground hover:text-foreground`. While in there: the close button renders a literal `×` glyph — swap to the lucide `<X className="size-4" aria-hidden />` icon used by `detail-drawer.tsx` for visual consistency (the `aria-label` is already correct).
**`web/src/components/ui/combobox.tsx:34, 46, 59, 84, 106`** — `ComboboxClear` (`text-neutral-400 hover:text-neutral-700`), `ComboboxTrigger` (`text-neutral-500`), `ComboboxPopup` (`bg-white`), `ComboboxItem` highlight (`data-[highlighted]:bg-indigo-50`), `ComboboxEmpty` (`text-neutral-500`):
→ `text-muted-foreground hover:text-foreground`, `bg-popover`, `data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground`, `text-muted-foreground`.
**`web/src/objects/objects-table.tsx:290`** — the page-size `<select>` in the table footer uses `bg-white` in *app* code. `check:colors` doesn't flag it because its regex only matches `palette-shade` pairs (`white` has no shade). → `bg-background` (or replace with the ui `Select`, cf. #51).
**`web/index.html`** — head has the theme preload script but no browser-chrome integration:
- add `<meta name="color-scheme" content="light dark">` so native form controls/scrollbars follow the theme,
- add `<meta name="theme-color">` with light + dark `media` variants.
## Suggested follow-up guard
Consider extending `scripts/check-no-raw-colors.mjs` to also match `bg-white`/`text-black`-style literals outside `src/components/ui/`, so the objects-table case can't recur.
All tokens needed (`--color-popover`, `--color-accent`, `--color-destructive`, `--color-success`) already exist in `src/index.css` `@theme inline` — this is purely a class swap.
As specified: tooltip/toast/combobox swapped to popover/accent/muted/destructive/success tokens, page-size select → bg-background, toast × → lucide X, and check-no-raw-colors now also flags shadeless white/black outside components/ui/.
One deviation: instead of static media-variant theme-color metas (which would desync from the in-app toggle), there's a singletheme-color meta kept in sync by the index.html preload script and applyTheme() (#ffffff/#0a0a0a, matching --background), with a unit test. color-scheme is set via CSS on :root/.dark — it takes precedence over the light dark meta, so native controls follow the resolved theme rather than the OS preference.
Fixed in 79a6567 (merged as 1d19ddf).
As specified: tooltip/toast/combobox swapped to `popover`/`accent`/`muted`/`destructive`/`success` tokens, page-size select → `bg-background`, toast `×` → lucide `X`, and `check-no-raw-colors` now also flags shadeless `white`/`black` outside `components/ui/`.
One deviation: instead of static `media`-variant `theme-color` metas (which would desync from the in-app toggle), there's a **single** `theme-color` meta kept in sync by the `index.html` preload script and `applyTheme()` (`#ffffff`/`#0a0a0a`, matching `--background`), with a unit test. `color-scheme` is set via CSS on `:root`/`.dark` — it takes precedence over the `light dark` meta, so native controls follow the resolved theme rather than the OS preference.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Dark mode shipped in #59, but the popup-layer primitives in
src/components/ui/(exempt fromcheck:colors, so the guard never caught them) and one raw<select>in app code still hardcode light-theme colors. In dark mode these render as white boxes with light-gray text.Findings
web/src/components/ui/tooltip.tsx:25—TooltipPopupusesbg-whiteand inherits no foreground token:→
bg-popover text-popover-foreground.web/src/components/ui/toast.tsx:17-19, 31, 37— toast root usesbg-white,border-red-300/border-green-300, descriptiontext-neutral-700, close buttontext-neutral-400 hover:text-neutral-700:→
bg-popover text-popover-foreground,border-destructive/border-success,text-muted-foreground hover:text-foreground. While in there: the close button renders a literal×glyph — swap to the lucide<X className="size-4" aria-hidden />icon used bydetail-drawer.tsxfor visual consistency (thearia-labelis already correct).web/src/components/ui/combobox.tsx:34, 46, 59, 84, 106—ComboboxClear(text-neutral-400 hover:text-neutral-700),ComboboxTrigger(text-neutral-500),ComboboxPopup(bg-white),ComboboxItemhighlight (data-[highlighted]:bg-indigo-50),ComboboxEmpty(text-neutral-500):→
text-muted-foreground hover:text-foreground,bg-popover,data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground,text-muted-foreground.web/src/objects/objects-table.tsx:290— the page-size<select>in the table footer usesbg-whitein app code.check:colorsdoesn't flag it because its regex only matchespalette-shadepairs (whitehas no shade). →bg-background(or replace with the uiSelect, cf. #51).web/index.html— head has the theme preload script but no browser-chrome integration:<meta name="color-scheme" content="light dark">so native form controls/scrollbars follow the theme,<meta name="theme-color">with light + darkmediavariants.Suggested follow-up guard
Consider extending
scripts/check-no-raw-colors.mjsto also matchbg-white/text-black-style literals outsidesrc/components/ui/, so the objects-table case can't recur.All tokens needed (
--color-popover,--color-accent,--color-destructive,--color-success) already exist insrc/index.css@theme inline— this is purely a class swap.Fixed in
79a6567(merged as1d19ddf).As specified: tooltip/toast/combobox swapped to
popover/accent/muted/destructive/successtokens, page-size select →bg-background, toast×→ lucideX, andcheck-no-raw-colorsnow also flags shadelesswhite/blackoutsidecomponents/ui/.One deviation: instead of static
media-varianttheme-colormetas (which would desync from the in-app toggle), there's a singletheme-colormeta kept in sync by theindex.htmlpreload script andapplyTheme()(#ffffff/#0a0a0a, matching--background), with a unit test.color-schemeis set via CSS on:root/.dark— it takes precedence over thelight darkmeta, so native controls follow the resolved theme rather than the OS preference.