astroturfcss / astroturf

Better Styling through Compiling: CSS-in-JS for those that want it all.
https://astroturfcss.github.io/astroturf/
MIT License
2.28k stars 60 forks source link

Possible limitation #748

Closed jpmaga closed 1 year ago

jpmaga commented 1 year ago

Hello all, I am currenlty evaluating astroturf and linaria to see which one fits our needs the best. So far astroturf is in the lead, but I think i found a possible limitation that would make it unusable for us. Or maybe I'm just missing some configuration flag or workaround.

I'm trying to assign different classes to an object, but I am greeted with the following error message:

There are multiple css tags with the same inferred identifier. Differentiate each tag by assigning the output to a unique identifier

and here is a sample code:

const styles = {
  App: css`text-align: center;`,
  header: css`background-color: #282c34;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: calc(10px + 2vmin);
    color: white;`,
  link: css`color: #b318f0;`,
  logo: css`
    animation: logo-spin infinite 20s linear;
    height: 40vmin;
    pointer-events: none;

    @keyframes logo-spin {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }
  `
}

Wouldn't it make sense to include the object key in the identifier in this case? Or what am I missing here?

Cheers.

jquense commented 1 year ago

does this not work already? I can totally make it work if it doesn't yeah

jquense commented 1 year ago

also you don't need to declare each class separately like this, stylesheet produces the same object with properties

jpmaga commented 1 year ago

Cool, thanks for the quick fix. Already tested and it is working just fine.

I hit another road block in the meantime. I feel this one might be by design, but just in case it isn't... It seems i can't interpolate strings (derived from functions). here is an example:

const interpolationFn = () => "tomato"
const color = interpolationFn()

const b_class = css`
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: ${color};
`

And this is the error message:

The following expression could not be evaluated during compilation. Dynamic expressions can only be used in the context of a component, in a `css` prop, or styled() component helper
  118 |   justify-content: center;
  119 |   font-size: calc(10px + 2vmin);
> 120 |   color: ${color};
      |            ^^^^^

Linaria handles this without issues, so it might have put my expectations a bit higher than they should. To our use case this is now the only thing failing our test suite. If you could let me know if this is by design or just an overlooked feature, that would be great. Many thanks! 🙏

jquense commented 1 year ago

yeah this isn't supported in astroturf, because the value of the interpolation isn't statically determinable. Linaria handles this by actually running your code to get the value of the fn, which has it's own downsides (its much slower and can create an uncanny valley around where code runs).

Astroturf supports dynamic values in the context of a component, where it can't replace the value with a CSS property, e.g.

function ({ color }) {
  return <div css={css`
       color: ${color}
    `} />
} 
jpmaga commented 1 year ago

yeah this isn't supported in astroturf, because the value of the interpolation isn't statically determinable. Linaria handles this by actually running your code to get the value of the fn, which has it's own downsides (its much slower and can create an uncanny valley around where code runs).

Astroturf supports dynamic values in the context of a component, where it can't replace the value with a CSS property, e.g.

function ({ color }) {
  return <div css={css`
       color: ${color}
    `} />
} 

Thanks for the quick reply. Yes, I saw that, it is and interesting approach, but for our use case doesn't work. We're not even using react and this is required to run a function kinda like vanilla extract's sprinkle. In any case, I understand the design decision, and thank you for your time. Cheers.

jpmaga commented 1 year ago

also you don't need to declare each class separately like this, stylesheet produces the same object with properties

Hello. I am still trying to use astroturf instead of Linaria. :) Using this approach works alright, but, i don't seem to get any type inference.

const styles = stylesheet`
.root {
  color: red;
}
`

console.log(styles.root) // no ts validation
console.log(styles.something) // no ts error

Don't really know how to handle this, if you could shed some light on the matter that would be great.

jquense commented 1 year ago

this is just a hard limitation of ts, you'd need a type plugin for this to work and TS doesn't allow that (if something else is doing this let me know i will see how they manage it).

The simplest way to avoid is like you tried originally with css to declare individual classes on an object, There are some differences between that and the stylesheet approach but should be the same feature-wise.

jpmaga commented 1 year ago

this is just a hard limitation of ts, you'd need a type plugin for this to work and TS doesn't allow that (if something else is doing this let me know i will see how they manage it).

The simplest way to avoid is like you tried originally with css to declare individual classes on an object, There are some differences between that and the stylesheet approach but should be the same feature-wise.

I've been using this with plain css modules: https://github.com/mrmckeb/typescript-plugin-css-modules and it works great. Even parses sass and postcss plugins. But have no idea if you can adapt to to the inner workings of astroturf.

jquense commented 1 year ago

you definitely could get that to work, astroturf is just css-modules, so all you'd need to do is tell it which template tags are actually css-modules. (the author might even add support if we ask) but that's not the same as TS errors, e.g. tsc -p . wouldn't give you type errors, but I agree the intellisense is nice...there is already an astroturf vscode extension we could add this too as well...

jpmaga commented 1 year ago

Well, I suggested it in here: https://github.com/mrmckeb/typescript-plugin-css-modules/issues/220 So... 🤞