Skip to content

πŸ¦Ήβ€β™‚οΈ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components and goober) at build time.

License

Notifications You must be signed in to change notification settings

pix2D/twin.macro

Β 
Β 

Repository files navigation

twin logo

Twin blends the magic of Tailwind with the flexibility of css-in-js

Total Downloads Latest Release Discord


Use Twin’s tw prop to add Tailwind classes onto jsx elements:

import 'twin.macro'

const Input = () => <input tw="border hover:border-black" />

Nest Twin’s tw import within a css prop to add conditional styles:

import tw from 'twin.macro'

const Input = ({ hasHover }) => (
  <input css={[tw`border`, hasHover && tw`hover:border-black`]} />
)

Or mix sass styles with the css import:

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

const hoverStyles = css`
  &:hover {
    border-color: black;
    ${tw`text-black`}
  }
`
const Input = ({ hasHover }) => (
  <input css={[tw`border`, hasHover && hoverStyles]} />
)

Styled Components

You can also use the tw import to create and style new components:

import tw from 'twin.macro'

const Input = tw.input`border hover:border-black`

And clone and style existing components:

const PurpleInput = tw(Input)`border-purple-500`

Switch to the styled import to add conditional styling:

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

const StyledInput = styled.input(({ hasBorder }) => [
  `color: black;`,
  hasBorder && tw`border-purple-500`,
])
const Input = () => <StyledInput hasBorder />

Or use backticks to mix with sass styles:

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

const StyledInput = styled.input`
  color: black;
  ${({ hasBorder }) => hasBorder && tw`border-purple-500`}
`
const Input = () => <StyledInput hasBorder />

How it works

When babel runs over your javascript or typescript files at compile time, twin grabs your classes and converts them into css objects. These css objects are then passed into your chosen css-in-js library without the need for an extra client-side bundle:

import tw from 'twin.macro'

tw`text-sm md:text-lg`

// ↓ ↓ ↓ ↓ ↓ ↓

{
  fontSize: '0.875rem',
  '@media (min-width: 768px)': {
    fontSize: '1.125rem',
  },
}

Twin also swaps its own css and styled imports with the real imports from your css-in-js library. This feature avoids having to add extra imports as you can import them all from twin.

Features

🎨 Style with all classes and variants available in Tailwind v2

🐹 Adds no size to your build - Twin converts classes you’ve used into css objects using Babel and then compiles away, leaving no runtime code

πŸ›Ž Helpful suggestions for mistypings - Twin chimes in with class and variant values from your Tailwind config:

βœ• ml-7 was not found

Try one of these classes:
ml-0 [0] / ml-1 [0.25rem] / ml-2 [0.5rem] / ml-3 [0.75rem] / ml-4 [1rem] / ml-5 [1.25rem] / ml-6 [1.5rem]
ml-8 [2rem] / ml-10 [2.5rem] / ml-12 [3rem] / ml-16 [4rem] / ml-20 [5rem] / ml-24 [6rem] / ml-32 [8rem]
ml-40 [10rem] / ml-48 [12rem] / ml-56 [14rem] / ml-64 [16rem] / ml-auto [auto] / ml-px [1px]

πŸ’‘ Works with the official tailwind vscode plugin - Avoid having to look up your classes with auto-completions straight from your Tailwind config - See setup instructions β†’

πŸš₯ Over 40 variants to prefix on your classes - Unlike Tailwind, the prefixes are always available to add to your classes

  • Prefix with before: and after: to style pseudo-elements
  • Prefix with hocus: to style hover + focus at the same time
  • Style with extra group states like group-hocus: and group-active:
  • Style form field states with checked:, invalid: and required:
  • Stack up variants whenever you need them sm:hover:first:bg-black

Check out the full list of variants β†’

🍱 Apply variants to multiple classes at once with variant groups

import 'twin.macro'

const interactionStyles = () => (
  <div tw="hover:(text-black underline) focus:(text-blue-500 underline)" />
)

const mediaStyles = () => <div tw="sm:(w-4 mt-3) lg:(w-8 mt-6)" />

const pseudoElementStyles = () => (
  <div tw="before:(content block w-10 h-10 bg-black)" />
)

const stackedVariants = () => <div tw="sm:hover:(bg-black text-white)" />

const groupsInGroups = () => <div tw="sm:(bg-black hover:(bg-white w-10))" />

πŸ‘‘ Add vanilla css that integrates with twins features

const alongsideTailwindClasses = () => (
  <div tw="after:(content['hello'] bg-black text-white)" />
)

const setCssVariables = () => <div tw="--base-color[#C0FFEE]" />

const useCssVariables = () => <div tw="background-color[var(--base-color)]" />

const customGridProperties = () => <div tw="grid-area[1 / 1 / 4 / 2]" />

const vendorPrefixes = () => <div tw="-webkit-mask-image[url(mask.png)]" />

πŸ–ŒοΈ Use the theme import to add values from your tailwind config

import { theme, css } from 'twin.macro'

const Input = () => <input css={css({ color: theme`colors.purple.500` })} />

See more examples using the theme import β†’

πŸ’₯ Add !important to any class with a trailing bang!

<div tw="hidden!" />
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
<div css={{ "display": "none !important" }} />

Add !important to multiple classes with bracket groups:

<div tw="(hidden ml-auto)!" />
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
<div css={{ "display": "none !important", "marginLeft": "auto !important" }} />

Get started

Take a look at these examples to get started:

React

πŸ’… styled-components Β  πŸ‘©β€πŸŽ€ emotion

Preact

πŸ’… styled-components Β  πŸ₯œ goober

Create React App

πŸ’… styled-components Β  πŸ‘©β€πŸŽ€ emotion

Gatsby

πŸ’… styled-components Β  πŸ‘©β€πŸŽ€ emotion

Next.js

πŸ’… styled-components Β  πŸ‘©β€πŸŽ€ emotion

Snowpack

πŸ’… styled-components Β  πŸ’… styled-components (TypeScript) Β  πŸ‘©β€πŸŽ€ emotion Β  πŸ‘©β€πŸŽ€ emotion (TypeScript)

Storybook

πŸ‘©β€πŸŽ€ emotion

Monorepo component library

πŸ’… styled-components (TypeScript)

Laravel

πŸ’… styled-components (TypeScript)

Plugins

You can use many Tailwind plugins with twin, like tailwindcss-typography and @tailwindcss/forms but there’s no compatibility with plugins that use the addVariant function.

See list of supported plugins β†’

TypeScript

Twin fully supports TypeScript projects and includes types for every import except the css and styled imports.

How to add the missing css and styled types β†’

Community

Drop into our Discord server for announcements, help and styling chat.

Discord

Resources

Special thanks

This project stemmed from babel-plugin-tailwind-components so a big shout out goes to Brad Cornes for the amazing work he produced. Styling with tailwind.macro has been such a pleasure.

About

πŸ¦Ήβ€β™‚οΈ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components and goober) at build time.

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 99.0%
  • TypeScript 1.0%