twin.macro icon indicating copy to clipboard operation
twin.macro copied to clipboard

Add Solid.js support

Open ghost opened this issue 3 years ago • 4 comments

The solid-styled-component package for Solid is a thin wrapper around Goober.

This patch adds preset: solid, which loads the Goober wrappers and otherwise behaves as Goober would.

A small site has been written using this PR, as well as this recently merged Solid PR for createGlobalStyles support. If you edit pages/index/index.jsx and comment out lines 30 through 95, you can easily play with the client without any server errors in the console.

I'm not sure exactly how you'd like to see these changes implemented and there are currently caveats. At the moment, however, I'd say it's entirely usable as a feature. Whatever you advise is fine.

Here are the current caveats. The following pattern works:

import tw, { styled } from "twin.macro";

export default function App(props) {
  const Button = styled("button")`
    ${() => tw`text-white`}
  `;
  return <Button {...props} />;
}

The following will not:

import "twin.macro";

export default function App(props) {
  return <button {...props} tw="text-white" />;
}

However, the following also works:

export default function App(props) {
  const ToggleButton = styled("button")`
    ${() => (props.active ? tw`text-white` : tw`text-gray-700`)}
  `;
  return <ToggleButton {...props} />;
}

<ToggleButton active={state.volume > 0} onClick={click}>
  <Svg alt="speaker" />
</ToggleButton>

Where Svg also demonstrates the css escape hatch:

import tw, { css } from "twin.macro";

export default function App(props) {
  const svg = css`
    ${() => tw`
      h-8
      w-8
      fill-current
      stroke-current
      inline-block
      text-center 
      bg-cover
    `}
  `;
  return (
    <svg {...props} class={svg}>
      <use xlink:href={`#svg-${props.alt}`}></use>
    </svg>
  );
}

And most importantly GlobalStyles works:

import { createGlobalStyles } from "solid-styled-components";
import tw, { GlobalStyles as BaseStyles } from "twin.macro";

export default function App() {
  const CustomStyles = createGlobalStyles`   
    body { 
      ${() => tw`subpixel-antialiased`}
    }
    video {
      ${() => tw`h-screen w-full bg-black z-0`}
    }
    video::-webkit-media-controls {
      ${() => tw`hidden`}
    }
  `;

  return (
    <>
      <BaseStyles />
      <CustomStyles />
    </>
  );
}

The only setup needed is package.json:

{
  "babelMacros": {
    "twin": {
      "preset": "solid"
    }
  },
  "devDependencies": {
    "vite": "^2.2.1",
    "vite-plugin-babel-macros": "^1.0.5",
    "vite-plugin-solid": "^1.5.1"
  },
  "dependencies": {
    "solid-js": "^0.26.1",
    "solid-styled-components": "^0.26.1",
    "twin.macro": "^2.3.3"
  }
}

and vite.config.js:

import { defineConfig } from "vite";
import solid from "vite-plugin-solid";
import macros from "vite-plugin-babel-macros";

export default defineConfig({
  plugins: [ solid(), macros(), ],

  build: {
    target: "esnext",
    polyfillDynamicImport: false,
  },
});

ghost avatar Apr 19 '21 23:04 ghost

Thanks so much for this feature, I haven't heard of the solid-styled-components goober integration before. Looks like it adds SSR and a theme provider? We could probably get that tw prop working with a modified version of babel-plugin-goober-css-prop.

I'll take a closer look and get back to you.

ben-rogerson avatar Apr 21 '21 20:04 ben-rogerson

Yes, solid-styled-components is bundled with Solid.js and its extensions to Goober are roughly for SSR, themes and other bookkeeping related to making it work with Solid.

I had a go with babel-plugin-goober-css-prop earlier but didn't manage to get props going.

Sadly, I will be going back to working with Vite running PostCSS/Tailwind in JIT-mode for various reasons. However, the twin.macro+goober revision of Live.tv is still available as a reference.

If there's anything I can help with this issue, please let me know!

ghost avatar Apr 23 '21 00:04 ghost

Thank you so much for making this! I've created an issue before I was aware of this PR.

My issue https://github.com/ben-rogerson/twin.macro/issues/469 is regarding emotion, specifially with my emotion-solid port I made. Is this PR Specific to solid-styled-component?

tqwewe avatar Jul 01 '21 08:07 tqwewe

Is this PR Specific to solid-styled-component?

Absolutely. The PR is just adding an option to use solid-styled-component as if it was Goober, since it is a Solid-specific wrapper around it. What you would need to do is a similar option for Solid's Emotion wrapper, in which case maybe naming this PR's option solid-goober instead of solid would be a better idea, since then you could have a solid-emotion for your solution.

Good luck!

ghost avatar Jul 01 '21 17:07 ghost

Hey @ben-rogerson is there any reason why this wasn't merged? I'm happy to take this to the finish line as I want to use twin.macro with Solid :)

ddanielcruzz avatar Jun 29 '23 03:06 ddanielcruzz

I've made some strides in a solid + twin integration, thinking I'll test it some more and release shortly.

ben-rogerson avatar Jul 07 '23 22:07 ben-rogerson

@ben-rogerson Awesome! Let me know if I can be of any help.

ddanielcruzz avatar Jul 08 '23 04:07 ddanielcruzz