master-co / master-co/css

Stacked mode + breakpoint variants (e.g. `@dark@sm`) emit invalid media query: missing `and` between media features

Open Beginner friendly
#444 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.9k
Forks
44
PR merge metrics
No merged PRs in 30d

Description

Description

When a utility class combines a color-mode variant with a breakpoint variant (e.g. bg:black@dark@sm) and modeTrigger is media, the engine emits a malformed media query — the two media features are joined by a space instead of and:

@media (width>=52.125rem) (prefers-color-scheme:dark){.bg\:black\@dark\@sm{background-color:oklch(0% 0 none)}}

This is invalid CSS, so browsers drop the whole rule (the style silently never applies), and downstream CSS minifiers complain — e.g. esbuild during a Vite build:

▲ [WARNING] Expected "{" but found "(" [css-syntax-error]

The cause appears to be in packages/engine/src/utils/generate-condition.ts: when the mode's prefers-color-scheme component is pushed into an existing conditions.media array, generateCondition joins the media feature nodes with ' ' and no and combinator is inserted.

Note that @master/css-validator (same version) returns false for bg:black@dark@sm, so stacked variants may no longer be intended syntax in 2.0 — but then the expected behavior would be for the engine to reject the class rather than emit invalid CSS. Either outcome (emit ... and (prefers-color-scheme:dark), or treat the class as invalid) would be fine; silently generating a rule that browsers discard is the worst of both.

Expected: @media (width>=52.125rem) and (prefers-color-scheme:dark){...} — or the class is rejected as invalid.

Reproduction
  1. bun add @master/css@rc @master/css-compiler@rc @master/css-engine@rc (all resolve to 2.0.0-rc.88)
  2. master.css:
    @import '@master/css';
    
  3. repro.mjs:
    import { compileCSSManifestFile } from '@master/css-compiler'
    import { MasterCSS } from '@master/css-engine'
    
    const { manifest } = await compileCSSManifestFile('./master.css')
    const css = new MasterCSS(manifest)
    for (const name of ['bg:black@sm', 'bg:black@dark', 'bg:black@dark@sm']) {
        console.log(name, '=>', css.generate(name).map(r => r.text).join(''))
    }
    
  4. bun repro.mjs prints:
    bg:black@sm      => @media (width>=52.125rem){.bg\:black\@sm{background-color:oklch(0% 0 none)}}
    bg:black@dark    => @media (prefers-color-scheme:dark){.bg\:black\@dark{background-color:oklch(0% 0 none)}}
    bg:black@dark@sm => @media (width>=52.125rem) (prefers-color-scheme:dark){.bg\:black\@dark\@sm{background-color:oklch(0% 0 none)}}
    

The single-variant classes are correct; the stacked one is missing and between the two media features. The same output is produced through @master/css.vite in a real build.

System Informations
OS: macOS (arm64)
Node.js / runtime: Bun 1.3.0
Package Manager: bun
@master/css: 2.0.0-rc.88 (also present in earlier 2.0 rc versions; source on the `rc` branch still joins media condition nodes with a space)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/engine/src/utils/generate-condition.ts and reproduce the issue with the provided repro.mjs script using Bun. Trace how breakpoint and color-mode conditions are combined, then verify that the stacked class produces a valid media query or is rejected instead of emitting malformed CSS.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, typescript
Domain
frontend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.