tqwewe/emotion-solid

Question: How can SolidJS components use the Emotion css prop?

thedanchez opened this issue · 2 comments

Hello, I'm looking to use emotion-solid and I'm coming as a user of @emotion/react. I know in SolidJS we are working with actual HTML elements and not VDOM-variants as in React. If I'm porting a React component that was using the css prop, how should the SolidJS component port that prop over?

I think @emotion/css is framework agnostic and this can be closed: https://emotion.sh/docs/introduction

The css prop does three things,

  • Takes your styles, applies a class name on those styles
  • Inject those styles, in the head element with that class name applied
  • Return that class name.

You use that class name in the element's class, This is cool, However SolidJS supports server side rendering with a switch, When server side rendering there's no head / document / window, so you can't magically find head of the document using the JS API's, To do this Solid JS has a useAssets hook that allows you to insert assets / tags into the head element when server side rendering.

useAssets is actually used by suid

Assets injected using useAssets are taken by getAssets (forgot the name) and put into the head element in a root.tsx file in SolidStart (done automatically mostly, this behavior has changed in SolidStart beta 2 but kinda similar)

This library however I haven't created a pull request to inject the css into the head element so it might not support server side rendering. This is because I kept it experimental, It had bugs (mostly fixed), I used it in my library @qinetik/emotion I will be making a pull request after shifting to beta 2, You can visit its documentation at Anique CSS

Notice that the Anique css prop returns a function to class name () => string This is because it cannot cache the styles, when you call it outside the solid component. like this

const myclass = css`
    color : red;
`
function MyComponent() {
   return <span class={myclass()}>Text</span>
}

it returns a hook, When you call myclass() Its similar to calling createEffect or onMount, So you must call the hook in element's class name, This allows us to

  • Take out styles out of the component
  • Use cached styles (no need to parse / combine or inject args)

This is because useAssets hook is only available inside the component, To support server side rendering.