Skip to content

Corrupted class names including string "null" generated from dynamic style with media query conditions #1702

Description

@joonaojapalo

Describe the issue

When using stylex.create() with dynamic style functions having a media query condition evaluating to null, StyleX generates class names that incorrectly include the raw string "null" in them leading to corrputed name, like "nullxafpxz5". This corrupted class name results respective style getting completely ignored. According to the StyleX documentation, null values should be ignored and not included in the generated class names.

Expected behavior

Conditional media query styles that return null should be ignored.

Steps to reproduce

Following component should have background-color: tomato when viewport is wider than 600px:

import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  highlightAt: (small, large) => ({
    backgroundColor: {
      default: null,
      "@media (max-width: 599px)": small ? "red" : null,
      "@media (min-width: 600px)": large ? "red" : null,
    },
  }),
});

const MyComponent = () => (
  <div {...stylex.props(styles.highlightAt(false, true))}>
    I should be red when viewport width is more than 600px
  </div>
);
  • StyleX version: 0.18.3
  • Plugins: @stylexjs/babel-plugin, @stylexjs/postcss-plugin
  • Environments tested: Astro.js dev server and production builds, Storybook

Test case

Reproduction steps work as deterministic test case.

Additional comments

Behavior is likely due to transpilation issue that can be reduced to very minimal Node.js program when standard stylex dependencies (@babel/core @babel/preset-react @stylexjs/babel-plugin) are in place. Self-contained reproduction repository: https://github.com/joonaojapalo/stylex-dynamic-mediaquery-repro

// repro.js
const babel = require("@babel/core");

const input = `
  import * as stylex from '@stylexjs/stylex';

  const styles = stylex.create({
    highlightAt: (small, large) => ({
      backgroundColor: {
        "@media (max-width: 599px)": small ? "red" : null,
        "@media (min-width: 600px)": large ? "red" : null,
      },
    }),
  });

  <div {...stylex.props(styles.highlightAt(false, true))} />
`;

const output = babel.transformSync(input, {
  presets: [["@babel/preset-react"]],
  plugins: [["@stylexjs/babel-plugin"]],
});

console.log(output.code);

This outputs transpiled code with following essential part:

 // ... redacted ..
  highlightAt: (small, large) => [{
    kWkggS: (
            (small ? "red" : null) != null
              ? "xkcfsz0 "
              : small
                ? "red"
                : null
        ) +  // <!-- string concatenation leads to invalid css, eg. highlightAt(false, true) -> {"kWkggS": "nullxafpxz5" }
        (
            (large ? "red" : null) != null 
                ? "xafpxz5"
                : large
                    ? "red"
                    : null
        ),
 // ... redacted ..

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions