Skip to content

fix(theme): add the widget-module layer, so Data Grid 2 follows the palette - #116

Merged
ako merged 1 commit into
mainfrom
claude/mendix-default-styling-1fgvpm
Aug 8, 2026
Merged

fix(theme): add the widget-module layer, so Data Grid 2 follows the palette#116
ako merged 1 commit into
mainfrom
claude/mendix-default-styling-1fgvpm

Conversation

@ako

@ako ako commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Reported from the Formula1 test build (FINDINGS §33).`` Follow-up to #102 and #104.

A themed app is on-palette everywhere, and then a few things are not: the Data Grid 2 pager caption — "1–15 of 77", the only thing telling a user where they are in the result set — measured 1.02:1 against a dark ground and was invisible. Row-select checkboxes stayed stock Mendix blue in a re-branded app, the loader flashed white on every page turn, popovers cast light-mode shadows.

One cause

_mxcli-atlas-map.scss re-points Atlas Core's custom properties, which covers the app. The theme source shipped by the widget modules under themesource/ styles some things with Sass variables and literals instead — datawidgets/web/variables.scss:18 is $pagination-caption-color: #0a1325. Sass resolves those at compile time, before any custom property exists, so the value is baked into theme.compiled.css and no --mxt-* can move it.

The parts that did work resolve var(--gray-darker, …) through Atlas. Same pager bar, two mechanisms, one of them reachable.

This adds _mxcli-widgets.scss, a third shared partial imported after the theme's own, correcting each baked declaration through a token so both palettes follow.

Why the obvious fix doesn't work

Each module's main.scss imports theme/web/custom-variables before its own !default variables, so setting $pagination-caption-color: var(--mxt-ink-muted) there would win — Sass substitutes the var() into every use site. Tempting, and wrong twice:

  1. The names collide with Atlas Core's, and Atlas Core feeds them to Sass colour functions. atlas_core/web/_variables.scss:20 computes mix($brand-primary, #e7e7e9, 10%). Handing mix() a var() is a compile error — the app stops building.
  2. The worst offenders aren't behind a variable at all. _three-state-checkbox.scss writes #264ae5 and rgba(#264ae5, 0.4) directly, so overriding $brand-primary would never reach them.

Read the compiled CSS, not the SCSS

Every selector here came out of a compiled theme.compiled.css. That halved the work: the sources are full of var(--token, #fallback) declarations that already resolve correctly. Of the 46 declarations mentioning the stock blue, 24 were harmless fallbacks. The report's list was assembled from the sources and is correspondingly longer — it includes rows that were never broken.

Verification

Browser-measured, both variants, on a light-first and a dark-first theme:

pager caption before after
console dark 1.02:1 6.99:1
console light 6.39:1
signal dark 6.78:1
signal light 5.93:1

The console figures resolve to rgb(154,166,180) / rgb(85,96,110) — the exact values the report measured for its own fix, arrived at independently. Checked-checkbox fill and loader background resolve to --mxt-brand and --mxt-surface in the compiled output, with mxcli's declaration last in each case.

A test asserts the layer reintroduces no literal colour, and the shared-partial drift guard now covers both shared files rather than only the Atlas map. Full suite, check-mdl, gofmt and vet pass.

Not addressed

The report also notes that theme apply cannot help with Atlas_Core.Layout.logo — a raster with a white tile, out of CSS's reach because it is an <img>. Their mask-based workaround is neat but needs an asset per app, so it isn't something a generated theme can ship. Worth a separate discussion.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JEZmExJUvn2nWTWE9mrd4i


Generated by Claude Code

…alette

Reported from the Formula1 test build (FINDINGS §33): a themed app is
on-palette everywhere, and then a few things are not. The Data Grid 2 pager
caption — "1-15 of 77", the only thing telling a user where they are in the
result set — measured 1.02:1 against a dark ground and was invisible. Row-select
checkboxes stayed stock Mendix blue in a re-branded app, the loader flashed
white on every page turn, and popovers cast light-mode shadows.

One cause. _mxcli-atlas-map.scss re-points Atlas Core's custom properties, which
covers the app. The theme source shipped by the *widget modules* under
themesource/ styles some things with Sass variables and literals instead, and
Sass resolves those at compile time, before any custom property exists — so the
value is baked into theme.compiled.css and no --mxt-* can move it. The parts
that did work resolve var(--gray-darker, …) through Atlas: same pager bar, two
mechanisms, one of them reachable.

Adds _mxcli-widgets.scss, a third shared partial imported after the theme's own,
correcting each baked declaration through a token so both palettes follow.

The obvious fix does not work, and it is worth writing down why. Each module's
main.scss imports theme/web/custom-variables *before* its own `!default`
variables, so setting `$pagination-caption-color: var(--mxt-ink-muted)` there
would win and Sass would substitute the var() into every use site. But the names
collide with Atlas Core's, and Atlas Core feeds them to Sass colour functions —
atlas_core/web/_variables.scss:20 computes mix($brand-primary, #e7e7e9, 10%),
and handing mix() a var() is a compile error, so the app stops building. And the
worst offenders are not behind a variable at all: _three-state-checkbox.scss
writes #264ae5 and rgba(#264ae5, 0.4) directly.

Every selector was read out of a compiled theme.compiled.css rather than from
the SCSS sources. That distinction halved the work: the sources are full of
`var(--token, #fallback)` declarations that already resolve correctly, and of
the 46 declarations mentioning the stock blue, 24 were harmless fallbacks. The
report's own list was assembled from the sources and is correspondingly longer.

Verified in a browser, both variants, both light-first and dark-first themes:
pager caption 1.02:1 -> 6.99:1 on console dark and 6.39:1 light (the exact
rgb(154,166,180) / rgb(85,96,110) the report measured for its own fix), 6.78 /
5.93 on signal. Checked-checkbox fill and loader background resolve to
--mxt-brand and --mxt-surface in the compiled output, with mxcli's declaration
last.

A test asserts the layer reintroduces no literal colour, and the shared-partial
drift guard now covers both shared files rather than only the Atlas map.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEZmExJUvn2nWTWE9mrd4i
@ako
ako merged commit d10c878 into main Aug 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants