Skip to content

fix(cli): correctly nest @media rules inside parent selectors (#10375) - #10384

Open
mrlexcoder wants to merge 1 commit into
shadcn-ui:mainfrom
mrlexcoder:fix/nested-media-postcss-10375
Open

fix(cli): correctly nest @media rules inside parent selectors (#10375)#10384
mrlexcoder wants to merge 1 commit into
shadcn-ui:mainfrom
mrlexcoder:fix/nested-media-postcss-10375

Conversation

@mrlexcoder

Copy link
Copy Markdown

Problem

When a registry item (e.g., registry:style) defines nested at-rules like @media inside a selector object (e.g., body inside @layer base), the PostCSS merger in the CLI incorrectly appends those @media blocks as siblings to the parent at-rule instead of nesting them inside the current rule.

Example registry item:

{
  "name": "repro-nested-media",
  "type": "registry:style",
  "css": {
    "@layer base": {
      "body": {
        "--foo": "1rem",
        "@media (width >= 40rem)": {
          "--foo": "2rem"
        }
      }
    }
  }
}

Current (broken) output:

@layer base {
  body {
    --foo: 1rem;
  }
  @media (width >= 40rem) {
     --foo: 2rem;
  }
}

This causes "Unexpected end of input" errors in Next.js because the @media rule is orphaned outside the body selector.

Expected output:

@layer base {
  body {
    --foo: 1rem;
    @media (width >= 40rem) {
      --foo: 2rem;
    }
  }
}

Root Cause

In packages/shadcn/src/utils/updaters/update-css.ts, the processRule function handles nested objects (line 597-602). When it encounters a nested object property, it assumes it's a nested selector and calls processRule(parent, ...), which appends to the parent at-rule instead of the current rule.

The code didn't check if the nested property is an at-rule (starts with @) with a body.

Solution

Added logic to detect nested at-rules with bodies:

  1. Check if prop.startsWith("@") and has a non-empty object value
  2. Create the at-rule inside the current rule (not parent)
  3. Recursively process the nested content inside the at-rule

Changes

  • packages/shadcn/src/utils/updaters/update-css.ts - Updated processRule function (lines 597-624)

Testing

With this fix:

  • Nested @media rules are correctly placed inside their parent selectors
  • No more "Unexpected end of input" errors
  • Works with any nested at-rule (@media, @supports, @container, etc.)

Related

Fixes #10375


Submitted by: @mrlexcoder

…-ui#10375)

When a registry item defines nested at-rules like @media inside a
selector (e.g., body), the PostCSS merger was incorrectly appending
them as siblings to the parent at-rule instead of nesting them inside
the current rule.

This caused syntax errors like 'Unexpected end of input' in Next.js.

Fixed by detecting nested at-rules with bodies and creating them
inside the current rule, then recursively processing their content.

Fixes shadcn-ui#10375
@vercel

vercel Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

@mrlexcoder is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

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.

[bug]: CLI: nested @media in registry css merges under wrong parent

1 participant