twin.macro: String interpolation inside tw macro doesn't work

Hi!

I have a problem with string interpolation in tw macro. For example I need to customize border color, so I’m trying to do it like this:

export const PrimaryButton = styled(Button)`
  ${({ color }) => tw`hover:border-${color ?? 'blue'}`};
`;

But I get the following error: ✕ Class “hover:border-” shouldn’t have a trailing dash.

It also doesn’t work without variables:

export const PrimaryButton = styled(Button)`
  ${({ color }) => tw`hover:border-${'blue'}`};
`;

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 14
  • Comments: 23 (11 by maintainers)

Most upvoted comments

Edit: Check out the discussion on this topic.

You could try a style map to reuse the styleMap object:

const styleMap = {
  primary: tw`bg-black text-white`,
  secondary: tw`bg-white text-black`,
  default: tw`bg-gray-500`
}

const getStyleName = ({ name }) => styleMap[name] || styleMap.default

const Button = styled.button(getStyleName)

const Buttons = () => (
  <>
    <Button name="primary">Primary</Button>
    <Button name="secondary">Secondary</Button>
    <Button>Default</Button>
  </>
)

You could also separate the styles and import them from another file:

// styles.js
const primary = tw`bg-black text-white`
const secondary = tw`bg-white text-black`
const other = tw`bg-gray-500`

const stylesCombined = { primary, secondary }
const getStyleName = ({ name }) => stylesCombined[name] || other

export default getStyleName
// Button.js
import getStyleName from './styles'

const Button = styled.button(getStyleName)

const Buttons = () => (
  <>
    <Button name="primary">Primary</Button>
    <Button name="secondary">Secondary</Button>
    <Button>Default</Button>
  </>
)

This is especially useful when using padding in the tailwind macro - eg: gap.

declare const gap: number

const styles = tw`px-${gap}`

I’m not sure whats the best workaround currently.

Unfortunately, I forgot that I had changed a few styles. The bug only seemed to have disappeared.

@ben-rogerson, I looked into the & issue a little closer. I decided to downgrade styled-components, and that definitely fixed it.

Thank you!

@kelvindecosta If you’re using styled-components you’re probably hitting the & issue with those dark classes. Great job with that workaround though, I think it’s working because you’re forcing styled-components to create separate styling objects.

@rattrayalex Twin doesn’t know how to work with TS interpolation like that, perhaps take a look at these guides I’m working on for all the ways you can use conditional styling

@alexhillel There are decent ways around interpolating classes, take a look at this codesandbox that shows different ways your styles could be assembled.