mui / pigment-css

Pigment CSS is a zero-runtime CSS-in-JS library that extracts the colocated styles to their own CSS files at build time.
MIT License
396 stars 19 forks source link

Support props callback #82

Open oliviertassinari opened 1 month ago

oliviertassinari commented 1 month ago

Steps to reproduce

import { styled } from '@pigment-css/react';

// Write your styles in `styled` tag
const Title = styled.h1`
  font-family: 'Arial';
`;

const Container = styled.div`
  font-size: 10px;
  color: ${props => props.color};
  border: 1px solid red;

  &:hover {
    border-color: blue;
  }

  ${Title} {
    margin-bottom: 24px;
  }
`;

        <Container color="#333">
          <Title>Hello world</Title>
        </Container>

Current behavior

The color prop doesn't work.

Expected behavior

The color prop works in Linaria https://codesandbox.io/p/devbox/dreamy-danny-mqkftk?file=%2Fsrc%2FApp.tsx%3A1%2C1&workspaceId=836800c1-9711-491c-a89b-3ac24cbd8cd8

SCR-20240513-danc

Context

I'm trying to migrate code from styled-components.

I believe that it's also something @jantimon asked for.

Your environment

npx @mui/envinfo ``` Don't forget to mention which browser you used. Output from `npx @mui/envinfo` goes here. ```

Search keywords: -

jantimon commented 1 month ago

Here is how next-yak does it:

https://yak.js.org/how-does-it-work#transform-dynamic-styles

you can try it on the playground: https://yak.js.org/playground

we extract the function to set an inline style css variable

your example from above would be compiled to the following code:

import { styled } from "next-yak";

// Write your styles in `styled` tag
import __styleYak from "./file.yak.module.css!=!./file?./file.yak.module.css";
const Title =
/*YAK Extracted CSS:
.Title {
  font-family: 'Arial';
}*/
/*#__PURE__*/
styled.h1(__styleYak.Title);
const Container =
/*YAK Extracted CSS:
.Container {
  font-size: 10px;
  color: var(--1sstj5p);
  border: 1px solid red;
  &:hover {
    border-color: blue;
  }
  .Title {
    margin-bottom: 24px;
  }
}*/
/*#__PURE__*/
styled.div(__styleYak.Container, {
  "style": {
    "--1sstj5p": props => props.color
  }
});
oliviertassinari commented 1 month ago

Oh, there is a playground, great! I love using those with Prettier, Babel, esbuild, etc. I think it's a must have anytime there is code transformation. Issue created: https://github.com/mui/pigment-css/issues/84.

brijeshb42 commented 3 weeks ago

The only issue we had here while adding the current implementation was that how do you provide theme access here. Where you get props right now, in Linaria, we are passing theme in Pigment CSS.

RJWadley commented 2 weeks ago

preface: no clue how the template syntax works now, i've been trying to figure it out for a bit and have not been able to figure out how or even if template literal syntax works beyond very basic CSS

could we pass both? maybe theme could be a reserved prop:

const Sample = styled.div<{ isError: boolean }>`
    color: ${({ theme }) => theme.colors.primary};
    font-weight: ${({ isError }) => isError ? "bold" : "normal" };
`

or maybe we could merge them, only allowing prop names that aren't in the theme:

const Sample = styled.div<{ isError: boolean }>`
    color: ${({ colors }) => colors.primary};
    font-weight: ${({ isError }) => isError ? "bold" : "normal" };
`

Having used linaria in a few projects, I'll say the developer experience of being able to write and use props with a familiar syntax and have it transformed to CSS w/ variables is pretty amazing. (and fwiw, my team would have probably not agreed to using linaria instead of styled-components without it)