Skip to content

refactor(sass): replace the deprecated if() function with @if and or - #670

Draft
desig9stein wants to merge 1 commit into
masterfrom
mpopov/fix-641-sass-if-function
Draft

desig9stein wants to merge 1 commit into
masterfrom
mpopov/fix-641-sass-if-function

Conversation

@desig9stein

@desig9stein desig9stein commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Closes #641.

Draft for review of the approach proposed in #641 (comment).

Problem

Sass 1.95+ deprecates the legacy if() function, so every consumer compile on a current Sass prints [if-function] warnings from sass/. Compiling the e2e theme with sass-embedded 1.107.1 on master prints 74 of them. The repo pins sass-embedded ~1.92.1, which predates the deprecation, so CI never saw them.

The new if(sass($c): $a; else: $b) syntax is not an option while Prettier formats sass/** in CI:

  • 3.8.1 (the lockfile pin) and 3.8.2 add trailing commas that break the compile (Undefined operation "(21,) < 1.07").
  • 3.8.3 to 3.8.5 insert a space before every ; that follows a ) or a string.
  • 3.9.x collapses one-element lists such as (background,) into (background) in 36 untouched files, which changes their Sass type.

Change

Sass

  • Every conditional in sass/ is an @if/@else block or an or/and expression. No if() call is left, including in the tile-manager theme from feat(tile-manager): add theme and MCP metadata #667.
  • _optional-shades(), _default-variant() and bem--not-selector() replace the nested if() calls that repeated the same branch.
  • $bem--sep-elem, $bem--sep-mod and $bem--sep-mod-val are !default. Before, they read meta.variable-exists(), which is always false inside a module, so @use ... with (...) could not set them. They keep the same values.
  • The supported Sass range does not change. The rewrite uses nothing newer than Sass 1.92.

Dependencies

  • sass-embedded is ~1.107.1 in packages/theming, packages/mcp and packages/preview. In theming and mcp it is a runtime dependency, because the MCP server compiles CSS with it, so consumers install 1.107.1 instead of 1.92.1.

Tests

  • tests/deprecations.test.ts compiles the e2e theme with a logger and fails on any deprecation warning.
  • tests/_themes.spec.scss uses an _fallback() helper instead of the 16 copies of the same if().

Tests

  • npm run lint: 0 errors. npm run build: passes with 0 deprecation warnings. npm test: 42 files, 1522 tests pass.

  • deprecations.test.ts fails on master's sass/ with 74 [if-function] warnings and passes on this branch.

  • The compiled output does not change. Each comparison is byte-identical:

    Compared Output
    Build output (dist/json, dist/tailwind, e2e theme.css), master vs branch on the same compiler identical
    All 69 component themes on all 8 schemas plus the 8 palettes (1.7 MB of CSS), master on 1.92.1 vs branch on 1.107.1 identical
    The same file, branch on 1.92.1 vs branch on 1.107.1 identical

Known limit

deprecations.test.ts compiles only the e2e theme, which covers one component theme. The all-themes compile above shows no deprecations today, but a future deprecation in a component theme outside the e2e theme would not fail CI. One option is to pass fatalDeprecations to the sass-true run in tests/sass.test.ts, so every spec fails on a deprecation. I left that out to keep this PR to the migration.

Notes

  • A stylelint autofix also limits the syntax: scss/at-if-no-parentheses --fix strips the outer parentheses of @if ($a and $b) or ($c and $d), which leaves invalid Sass. The one mixed condition in _generator.scss stays unparenthesized, which follows and binding tighter than or.

- Every conditional in sass/ and the themes spec is an @if/@else block or an
  `or`/`and` expression, so Sass 1.95+ prints no if-function warning and
  older Sass still compiles. The compiled CSS does not change.
- _optional-shades, _default-variant and bem--not-selector replace the
  repeated nested if() calls.
- The bem separators are `!default`, so `@use ... with (...)` can set them.
- sass-embedded is 1.107.1 in theming, mcp and preview, and
  tests/deprecations.test.ts fails the suite on any deprecation warning.

Closes #641.
@desig9stein desig9stein self-assigned this Nov 10, 2026
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.

Migrate off the deprecated Sass if() function

1 participant