javascriptreactjssassnext.jsstyled-jsx

How to render custom generated ruleset in styled-jsx


TL;DR

How does one insert a variable that contains one or more CSS rules into styled-jsx (using styled-jsx-plugin-sass under the hood)?


I have the following JSX style:

// src/pages/index.tsx
...
<style jsx>
  {`
    .test {
      height: 100vh;
      width: 100vw;
      background-color: green;
      ${contained}
     }
  `}
</style>

And contained is a variable that I'm trying to insert into it the mentioned rule:

// src/styles/break.ts

export const contained = `
margin: 0 auto;
${breakAt("sm")(`
  width: calc(100% - 10vw);
`)}
${breakAt("md")(`
  width: calc(100% - 15vw);
`)}
@media screen and (min-width: calc(960px + 10vw)) {
  width: 960px;
}`;
...

Notes:

breakAt is a function that generates a specific media query (breakpoint: string) => (content: string) => string

I have ensured that styled-jsx-plugin-sass is configured correctly - writing the generated CSS in raw acts as intended.

I've also looked into how I believe styled-jsx behaves - it seems to do some literal parsing of the code I put in as I wrote a generator ((content: string) => string acting on contained) and called it, and the parser recognised that I wrote a CallExpression, but failed to render anything because of that.

I understand that this could be solved using @mixin/@include but I'm picking and choosing features of Sass that I like at this point (mainly embedded rules), and was curious to see what was possible.

Your input and correction is greatly appreciated. Please read the full question before answering!


Solution

  • I'm not a fan of styled-components (yet!) but it seems to be the valid situation in this scenario:

    import styled from "styled-components"
    // ... other imports
    
    const Wrapper = styled.div`
      /* ... scoped styles */
      ${contained} /* mixin */
    `
    
    export default SomeComponent({ children }) {
      return <Wrapper>This component was mixed in<Wrapper/>
    }