malcolm-kee / codemod-example-twin-macro

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Twin + Vite + Emotion + TypeScript

TwinTwinViteEmotionTypeScript

Download this example using degit

npx degit https://github.com/ben-rogerson/twin.examples/vite-emotion-typescript folder-name

From within the new folder, run yarn, then yarn start to start the dev server.

Table of contents

Getting started

Installation

Install Vite

yarn create vite my-vite-app --template react-ts

Install the dependencies

yarn add @emotion/react @emotion/styled
yarn add twin.macro @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx babel-plugin-macros tailwindcss --dev
Install with npm

Install Vite

npm create vite@latest my-vite-app -- --template react-ts

Install the dependencies

npm install @emotion/react @emotion/styled
npm install --save-dev twin.macro @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx babel-plugin-macros tailwindcss

Add the global styles

Twin uses the same preflight base styles as Tailwind to smooth over cross-browser inconsistencies.

The GlobalStyles import adds these base styles along with some @keyframes for the animation classes and some global css that makes the ring classes and box-shadows work.

You can import GlobalStyles within a new file placed in src/styles/GlobalStyles.tsx:

// src/styles/GlobalStyles.tsx
import React from 'react'
import { Global } from '@emotion/react'
import tw, { css, theme, GlobalStyles as BaseStyles } from 'twin.macro'

const customStyles = css({
  body: {
    WebkitTapHighlightColor: theme`colors.purple.500`,
    ...tw`antialiased`,
  },
})

const GlobalStyles = () => (
  <>
    <BaseStyles />
    <Global styles={customStyles} />
  </>
)

export default GlobalStyles

Then import the GlobalStyles file in src/main.tsx:

// src/main.tsx
import React from 'react'
import { createRoot } from 'react-dom/client'
import GlobalStyles from './styles/GlobalStyles'
import App from './App'

const container = document.getElementById('root')
const root = createRoot(container!)
root.render(
  <React.StrictMode>
    <GlobalStyles />
    <App />
  </React.StrictMode>,
)

Add the twin config (optional)

Twin’s config can be added in a couple of different files.

a) Either in babel-plugin-macros.config.js:

// babel-plugin-macros.config.js
module.exports = {
  twin: {
    preset: 'emotion',
  },
}

b) Or in package.json:

// package.json
"babelMacros": {
  "twin": {
    "preset": "emotion"
  }
},

Note: The preset gets set to 'emotion' by default, so adding the config is only useful if you want to adjust Twin’s other options.

Add the vite config

Add the following to your vite config:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  optimizeDeps: {
    esbuildOptions: {
      target: 'es2020',
    },
  },
  esbuild: {
    // https://github.com/vitejs/vite/issues/8644#issuecomment-1159308803
    logOverride: { 'this-is-undefined-in-esm': 'silent' },
  },
  plugins: [
    react({
      babel: {
        plugins: [
          'babel-plugin-macros',
          [
            '@emotion/babel-plugin-jsx-pragmatic',
            {
              export: 'jsx',
              import: '__cssprop',
              module: '@emotion/react',
            },
          ],
          [
            '@babel/plugin-transform-react-jsx',
            { pragma: '__cssprop' },
            'twin.macro',
          ],
        ],
      },
    }),
  ],
})

Complete the TypeScript setup

To avoid red squiggly underlines, you’ll need to add the remaining types for your chosen css-in-js framework.

First up, you’ll need to install some types for React:

npm install -D @types/react
// or
yarn add @types/react -D

Then create a file in types/twin.d.ts and add these declarations:

// types/twin.d.ts
import 'twin.macro'
import { css as cssImport } from '@emotion/react'
import styledImport from '@emotion/styled'
import { CSSInterpolation } from '@emotion/serialize'

declare module 'twin.macro' {
  // The styled and css imports
  const styled: typeof styledImport
  const css: typeof cssImport
}

declare module 'react' {
  // The tw and css prop
  interface DOMAttributes<T> {
    tw?: string
    css?: CSSInterpolation
  }
}

Then add the following to your tsconfig.json:

{
  "compilerOptions": {
    "skipLibCheck": true,
    "jsxImportSource": "@emotion/react"
  },
  "include": ["src", "types"]
}

Customization

Next steps

Learn how to work with twin

Learn more about emotion

About


Languages

Language:TypeScript 73.5%Language:JavaScript 21.6%Language:HTML 4.9%