Skip to content

Babel plugin to transpile class names to styles at build time #369

@namnm

Description

@namnm

First of all, thank you for your great package. Im happy to share I have made a babel plugin to transpile class names to styles at build time. It uses twrnc under the hood, with some other extra features:
https://github.com/nongdan-dev/react-native-tailwind-nextjs

Current the repo is like a boilerplate.
I hope if there are enough people interest in it and I could have time to move the plugin into a separated package.

// transpile class names directly to style object, with support for transition and animation
// on web they will be kept as string
const flex = tw`flex flex-col transition`
// will be transpiled to:
const flex = {
  display: 'flex',
  flexDirection: 'column',
  transition: ['..'],
  transitionDuration: 200,
  transitionTimingFunction: 'ease-in',
}

// jsx className prop will be transpiled to style on react native using babel-plugin-react-native-classname-to-style
// transpiled styles are moved to the root scope to avoid dynamic object creation on each render
const MyComponent = () => <View className={tw`flex flex-col transition`} />
// will be transpiled to:
const _style = {
  /* .. */
}
const MyComponent = () => <View style={_style} />

// support for selectors using hook
const MyComponent = () => {
  // on web the props simply contains className so it doesnt need to 'use client'
  // on native it will contains handlers if we have selectors such as active: focus:
  const [rootProps, childrenProps] = useTw({
    className: 'group flex flex-col transition active:bg-red-500',
    // with support for children
    children: {
      text: 'text-black transition group-active:text-white',
    },
    // props to compose or support selectors such as disabled: checked: on native
    props: {
      // ..
    },
    childrenProps: {
      text: {
        // ..
      },
    },
  })
  return (
    <Pressable {...rootProps}>
      <Text {...childrenProps.text}>Hello World</Text>
    </Pressable>
  )
}

// support cva style
const useClassNames = twCva({
  // similar to the above
  className: '..',
  children: {
    text: '..',
  },
  attributes: {
    // similar to cva variants
    attr1: {
      value1: '..',
    },
    // with support for children
    attr2: {
      value2: {
        className: '..',
        children: {
          text: '..',
        },
      },
    },
  },
  defaultVariant: {
    // similar to cva defaultVariants
  },
  compoundVariants: [
    // similar to cva compoundVariants
    {
      attr1: 'value1',
      attr2: 'value2',
      className: '..',
      // with support for children
      children: {
        text: '..',
      },
    },
  ],
})
const MyComponent = variant => {
  const [rootProps, childrenProps] = useClassNames({
    variant,
    // similar to the above
    props: {
      // ..
    },
    childrenProps: {
      text: {
        // ..
      },
    },
  })
  // ..
}

// support component style
const MyComponent = () => {
  return (
    <TwPressable className='group flex flex-col transition active:bg-red-500'>
      <TwText className='text-black transition group-active:text-white'>
        Hello World
      </TwText>
    </TwPressable>
  )
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions