Tokenise the remaining backend colours so dark mode can be a pure variable redefinition
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- css
- Domain
- frontend
Research direction
Start with modules/backend/assets/less/layout/fancylayout.less and modules/backend/models/brandsetting/custom.less, then inspect the listed variable files and IconPicker.vue. Run the dark-tokens harness from wn-tailwindui-plugin to verify each core token replacement and confirm the matching darkmode.css and fancy-layout.css overrides can be deleted without changing light mode.
Written by the indexing model from the issue text.
Description
#1541 routed core's colour literals through --wn-* tokens so that dark mode (and other themes) can redefine a variable instead of overriding every rule that paints something. The TailwindUI dark mode now does that (wintercms/wn-tailwindui-plugin#58): a .dark { --wn-…: … } block replaced 86 per-element declarations.
But some backend colours never became variables, and every dark-mode fix since has had to fall back to per-selector overrides, 31 of them with !important. Each gap below needs a core change so the corresponding plugin override can be deleted and dark mode becomes a pure variable redefinition.
Gaps
- Brand-derived fancy chrome. The fancy header band, tab bars, active/inactive tabs, their wings, and the breadcrumb bar, segments, arrow tips and separators are all LESS
mix()/saturate()expressions on@brand-secondary. They're compiled at build time inmodules/backend/assets/less/layout/fancylayout.less, and again at runtime inmodules/backend/models/brandsetting/custom.less(lines ~133–240). Novar()is involved, so dark mode has to override every selector with!importantto beat the runtime brand CSS.- Fix: have
custom.lessemit these as custom properties computed from the brand settings (e.g.--wn-fancy-header-bg,--wn-fancy-tab-bar,--wn-fancy-tab-active,--wn-fancy-tab-inactive,--wn-breadcrumb-bar,--wn-breadcrumb-segment,--wn-breadcrumb-current). Point the fancy-layout and breadcrumb rules at them. This is step 2b ofbrand-color-variable-architecture.md(on the plugin'swip/darkmode-auditbranch). - Retires: the tab, wing, breadcrumb and header-band overrides in the plugin's
darkmode.cssandcomponents/fancy-layout.css.
- Fix: have
- Named-colour literals the hex sweep missed.
fancylayout.lessuseswhitefor the secondary-content tab wings and titles (lines ~419, 450, 473, 477, 841). The tokenisation only matched hex values, so these stayed literal and draw white edges and lines in dark mode.- Fix: sweep core LESS for named colours (
white,black,silver, …) and tokenise them like the hex literals.
- Fix: sweep core LESS for named colours (
- Input-group addon.
@input-group-addon-bg: @gray-lighter(form.variables.less:26) is a compile-time literal, so the email/URL field icons stay a light box.- Fix: a surface token, if nothing derives from it at compile time.
- Active and hover rows reuse a text token.
@color-list-activeand@color-list-hoverarevar(--wn-text-faint, #ddd)(list.variables.less:15-16). They paint the tree, file list and asset list active/hover row backgrounds (treeview.less,filelist.less,assetlist.less). Redefining--wn-text-faintfor dark text turns those rows into grey blocks.- Fix: give them their own role tokens (e.g.
--wn-surface-row-active,--wn-surface-row-hover).
- Fix: give them their own role tokens (e.g.
- Date and time picker states.
@color-datepicker-today-text: @brand-primaryand@color-datepicker-selected-bg: @brand-accent(datepicker.variables.less:5-6) are compile-time brand colours. So is the clockpicker header's.text-primary. The clockpicker dial colours (.clockpicker-canvas-bg,-fg, the hand) are literals indatepicker.time.less:271+. In dark mode, today is navy on a dark cell, the selected date is white on green (~2:1), and the selected hour is a pale bubble behind light numerals.- Fix: tokens for the selected, today, dial and hand colours.
- Switch knob.
.slide-button(checkbox.less:246) is painted with--wn-surface-hover. The knob should stay light in both modes while hover surfaces go dark, so dark mode currently has to pin the knob back.- Fix: give the knob its own token.
- Icon picker modal.
modules/backend/formwidgets/iconpicker/assets/js/src/components/IconPicker.vuehard-codes its panel, tile, search and footer colours in scoped CSS. Scoped CSS is injected after the skin's stylesheet with equal specificity, so dark mode has to anchor its overrides on.aim-modal.aim-opento win.- Fix: point the component's colours at the existing surface, text and border tokens.
- Logos on dark surfaces.
.wn-logo/.oc-logoand the empty-editor watermark (*-logo-transparent) hard-codeurl(../images/logo-dark.svg)incontrols/common.less. Dark mode swaps inlogo-light.svgwith a root-absolute URL, which breaks on subdirectory installs.- Fix: a custom property for the logo image (e.g.
--wn-logo-image), so a theme can switch it without knowing the install path.
- Fix: a custom property for the logo image (e.g.
Done when
Each gap is a variable in core, and the matching overrides in wn-tailwindui-plugin's darkmode.css / fancy-layout.css are deleted. That deletion should be verified with the dark-tokens harness, which proves a removal changes nothing and that light mode is untouched.
- Dominant language
- PHP
- Stars
- 1.5k
- Forks
- 251
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 10
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from wintercms/winter
-
Difficulty 1/5 Under an hour Newbie friendliness 80/100
Maintainers usually reply within 1 day
-
needs review
Difficulty 1/5 Under an hour Newbie friendliness 90/100
wintercms/winter#1539 · 3 comments ·
Maintainers usually reply within 1 day
-
Snowboard's Url utility mangles protocol-relative asset URLs, hanging AJAX handlersPossibly taken @wakqasahmed claimed this 25 days ago. Openlow priority needs pr
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
wintercms/winter#1538 · 1 comment ·
Maintainers usually reply within 1 day
-
vite:watch writes an unreachable dev-server URL (http://[::]:5173) to the hot file on IPv6 hostsPossibly taken @LukeTowers claimed this 60 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
wintercms/winter#1537 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
All issues in wintercms/winter
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
kanboard/kanboard#5929 · 1 comment · 3 reactions ·
Maintainers usually reply within 5 days
-
Rebuild 6.2.3 images on PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 (CVE-2026-109618, CVE-2026-109619)Open
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
swoole/docker-swoole#65 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
PHP-CS-Fixer/PHP-CS-Fixer#9899 ·
Maintainers usually reply within 1 day
-
REST: Add missing text domain and fix typos in REST API controller stringsPossibly taken @devmuhib009 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100