Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support for linaria for static CSS interop #248

Closed
wants to merge 3 commits into from

Conversation

NateRadebaugh
Copy link

@ben-rogerson
Copy link
Owner

thanks for the PR's, you got a good base ready this feature - 🤞 it can be done!

@ben-rogerson
Copy link
Owner

I have given this a quick initial test with the styled import (and by including the fix from #256).

This is working:

import tw from 'twin.macro'
import { styled } from 'linaria/react'

const Button = styled.button`
  ${tw`bg-black`}
`

But importing from twin doesn't work:

import tw, { styled } from 'twin.macro'

const Button = styled.button`
  ${tw`bg-black`}
`

Results in Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.

Array styling

There's also a common syntax twin uses/advertises which is adding the items to an array.
Either linaria needs some adjustments or twin (or a bit of both) to allow this:

import tw from "twin.macro";

const Button = tw.button`bg-black`;

// ↓ ↓ ↓ ↓ ↓ ↓

import { styled as _styled } from "linaria/react";

const Button = _styled.button({
  "--tw-bg-opacity": "1",
  "backgroundColor": "rgba(0, 0, 0, var(--tw-bg-opacity))"
});

and also this:

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

const Button = styled.button([tw`bg-black`]);

// ↓ ↓ ↓ ↓ ↓ ↓

import { styled as _styled } from "linaria/react";

const Button = _styled.button([{
  "--tw-bg-opacity": "1",
  "backgroundColor": "rgba(0, 0, 0, var(--tw-bg-opacity))"
}]);

@NateRadebaugh
Copy link
Author

Agreed, I haven't figured out the glue here but while I've got the example rendering linaria fully can't see any of the twin.macro ones working as expected. I don't understand the twin code well enough to determine the fix at the moment.

@ben-rogerson
Copy link
Owner

ben-rogerson commented Dec 16, 2020

I'm keen to explore this further, but I've got quite a bit on my plate at the moment so I'll have to circle back around and tackle it 👍

@vinverdy
Copy link

will it merged in near future?

@zaguiini
Copy link
Contributor

What is this PR missing? Can I help in any way?

@NateRadebaugh
Copy link
Author

This PR was never completed and is still just a draft. Was hoping @ben-rogerson would pick it up or give some pointers.

@ben-rogerson
Copy link
Owner

ben-rogerson commented Dec 30, 2021

I'm planning to wait for version 4 to come out of beta before pursuing an integration. Unless the API is similar enough?

@lukesmurray
Copy link

I'm planning to wait for version 3 to come out of beta before pursuing an integration. Unless the API is similar enough?

I would be so excited to see twin.macro add support for a zero-runtime CSS library. With linaria V4 recently being released, I would love to help twin.macro implement support for linaria. @ben-rogerson, would you be open to PRs adding linaria support? Or is that something you would prefer to tackle on your own?

@ben-rogerson
Copy link
Owner

ben-rogerson commented Aug 8, 2022

Hey Luke - yeah definitely open to a PR - how about a new "Linaria + Emotion + TypeScript" example?

As there's so many changes in the next twin.macro@rc I wouldn't advise working with any code in this repository at the moment but see how you go adding an example in the twin.examples repo - if you run into any issues either contact me on Discord or post up the unfinished PR and ask questions there - thanks!

As there's no preset="linaria" added yet, you can specify custom imports like this:

// In your twin config
styled: { import: 'default', from: '@emotion/styled' },
css: { import: 'css', from: '@emotion/react' },
global: { import: 'Global', from: '@emotion/react' },

@zaguiini
Copy link
Contributor

zaguiini commented Aug 8, 2022

Note to whoever implements this following @ben-rogerson's comment about custom imports: global styles in Linaria work a little bit differently: https://github.com/callstack/linaria/blob/v4.0.0/docs/BASICS.md#adding-global-styles.

EDIT: well, actually, it's kind of different: https://scottspence.com/posts/linaria-getting-started#global-style 🤷 the import for global is also css and you don't need to reference it at all as simply defining and exporting the css tagged-template makes Linaria append the style to the page.

@ben-rogerson
Copy link
Owner

ben-rogerson commented Aug 8, 2022

With global styles we should use the globalStyles (style object) import rather than GlobalStyles (for use in jsx) import.

Something like this:

import { globalStyles } from 'twin.macro'
import { css } from 'linaria'

export const globals = css(globalStyles)

@lukesmurray
Copy link

sounds good i'll put one together :)

@lukesmurray
Copy link

Started working on this but ran into an issue with vite and linaria.
I submitted an issue to linaria callstack/linaria#1044.

@lukesmurray
Copy link

lukesmurray commented Aug 9, 2022

Ok I gave this a first shot in a public repo (codesandbox demo). I can add that code to the examples repo but there were so many things that didn't work that the default example app used in all the other examples didn't seem like a reasonable place to start. Feel free to fork my code. I can add a license of your choosing to it if that is an issue. But I don't place any claims on it at all.

Note: The linaria -> vite integration only works with the beta version, not with the 4.0 release but the API between the last beta and the current release seems to be identical. This is due to this issue callstack/linaria#1044

Things that work

  • global styles
  • css import
  • Styled import
  • interpolating arrays in css and styled imports
// array interpolation works 👍 
css`${[tw`bg-red-500`, tw`text-sm`]}`

Things that don't work

  • css prop
  • tw prop
  • using tw import to create styled objects

Potential issues

Linaria styled tags allow for conditional styling via prop interpolation functions.
However, these functions only let you conditionally determine a css property value, not a css property name and property value.
This limitation is due to the fact that linaria compiles prop interpolations into css variables and you can't represent a property name and value with a css variable.

// this works
const Title = styled.h1`
  color: ${props => (props.primary ? 'tomato' : 'black')};
`;

// this will never work
const Title = styled.h1`
  ${props => (props.primary ? tw`text-red-500` :  tw`text-black`)};
`;

Linaria css interpolation is not linked to components and doesn't have access to state or props. If you want to condtionally apply styles you need to separate each potential style into a separate css call and conditionally apply the class names using cx.

// this works
const Title = ({primary, children}) => {
  return <h1 className={cx(primary ? css`${tw`text-red-500`}` :  css`${tw`text-black`}`)}>{children}</h1>
}

// this will never work
const Title = ({primary, children}) => {
  return <h1 className={css`${primary ? tw`text-red-500` :  tw`text-black`}`}>{children}</h1>
}

So in summary I'm optimistic that we can get this working but we probably need to do some leg work to get the css prop working. Most likely we want the css prop to accept any of tw, css or an array of either. tw should probably be compiled into css when used at the top level and can be left alone when used inside of css. Arrays passed to the css prop should be merged with cx.

@lukesmurray
Copy link

if it's possible to implement support for the tw and css props without modifying tw.macro itself i could try to do that but i would need a little hint.

@ben-rogerson
Copy link
Owner

There’s some great findings here Luke!
You're right, further updates would need to be made in the twin.macro repo.

Let's put this on hold for a little while until I'm through the v3 updates - both me and the repo will be better primed to pick this up again and complete the new linaria preset.

@NateRadebaugh NateRadebaugh deleted the linaria branch August 19, 2022 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants