QuickBase / babel-plugin-styled-components-css-namespace

A babel plugin to add css namespaces (and increase specificity) of styled-component classes.
MIT License
118 stars 32 forks source link

Upgrading styled-components from 5.1.1 to 5.3.5 has broken the plugin #86

Open marmite22 opened 2 years ago

marmite22 commented 2 years ago

Environment

In the process of upgrading React to v18 we found that styled-components was throwing an error about breaking the rule of hooks. Upgrading styled-components to the latest version it appears that the babel-plugin-styled-components-css-namespace no longer works correctly.

Steps to reproduce

Given the babel config

['@quickbaseoss/babel-plugin-styled-components-css-namespace', { cssNamespace: '.ssa-app' }],

and the code

  const StyledIcon = styled(IcomoonReact)`
    transform: ${(props) => (props.$flipx ? `scaleX(-1)` : 'none')};`
  `

  <StyledIcon $flipx={true}   />
  <StyledIcon $flipx={false}   />

Expected Behavior

On version 5.1.1 the above would produce 2 styles and correctly assign the classnames to the elements in the DOM. (.ssa-app is the css prefix defined in babel-plugin-styled-components-css-namespace)

.ssa-app .lnugha {
    transform: none;
}

.ssa-app .hHOYwd {
    transform: scaleX(-1);
}

Actual Behavior

Since updating to 5.3.5 the CSS is as follows and both elements have the same class of sc-bczRLJ and thus both look the same (flipped).

.ssa-app .sc-bczRLJ {
    transform: scaleX(-1);
}

.ssa-app .sc-bczRLJ {
    transform: none;
}
.ssa-app .sc-bczRLJ {
    transform: none;
}

I'm completely stuck as to how to achieve the global css namespace in 5.3.5.

marmite22 commented 2 years ago

More specifically it looks like this issue was introduced in 5.2.0 of Styled Components

francois-codes commented 1 year ago

We've been struggling with this for a little while now, and we came across a solution which is working fine for us Using latest Styled Components v5, we removed this plugin, and instead used a stylis plugin and the StyleSheetManager form Styled Components


import { StyleSheetManager } from "styled-components";

export function MyApp() {
  return (
    <StyleSheetManager stylisPlugins={[stylisCssNamespace({ namespace: "#root-id" })]}>
       { /* rest of the app */}
    </StyleSheetManager>
  )
}

function stylisCssNamespace({ namespace }) {
  return (context, _, selectors) => {
    if (context !== -1) return;
    const [selector] = selectors;
    if (selector.includes(namespace)) return; // avoiding adding it multiple times
    selectors[0] = `${namespace} ${selector}`
  }
}

This is doing what this plugin was doing for us and solves our problem for specificity