Skip to content

Latest commit

 

History

History

next-emotion

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Twin + Next.js + Emotion

TwinTwinNext.jsNext.jsEmotion

Download this example using degit

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

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

Table of contents

Getting started

Installation

Install Next.js

Choose "Yes" for the src/ directory option when prompted.

npx create-next-app@latest --javascript

Install the dependencies

npm install @emotion/react @emotion/styled
npm install -D twin.macro tailwindcss @emotion/babel-plugin babel-plugin-macros @babel/preset-react babel-loader babel-plugin-macros
Install with Yarn

Choose "Yes" for the src/ directory option when prompted.

yarn create next-app

Install the dependencies

yarn add @emotion/react @emotion/styled
yarn add -D twin.macro tailwindcss @emotion/babel-plugin babel-plugin-macros

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, some @keyframes for animations, and some global css variables.

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

// src/styles/GlobalStyles.js
import { Global, css } from '@emotion/react'
import tw, { 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/pages/_app.js:

// src/pages/_app.js
import GlobalStyles from '../styles/GlobalStyles'

const App = ({ Component, pageProps }) => (
  <>
    <GlobalStyles />
    <Component {...pageProps} />
  </>
)

export default App

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 next babel config

Create a new file either in the root or in a config subfolder:

// withTwin.mjs
import babelPluginMacros from 'babel-plugin-macros'
import * as path from 'path'
import * as url from 'url'
// import babelPluginTwin from 'babel-plugin-twin'

const __dirname = url.fileURLToPath(new URL('.', import.meta.url))

// The folders containing files importing twin.macro
const includedDirs = [path.resolve(__dirname, 'src')]

/** @returns {import('next').NextConfig} */
export default function withTwin(
  /** @type {import('next').NextConfig} */
  nextConfig,
) {
  return {
    ...nextConfig,
    webpack(
      /** @type {import('webpack').Configuration} */
      config,
      options,
    ) {
      config.module = config.module || {}
      config.module.rules = config.module.rules || []

      config.module.rules.push({
        test: /\.(jsx|js)$/,
        include: includedDirs,
        use: [
          {
            loader: 'babel-loader',
            options: {
              sourceMaps: options.dev,
              presets: [
                [
                  '@babel/preset-react',
                  { runtime: 'automatic', importSource: '@emotion/react' },
                ],
              ],
              plugins: [
                // babelPluginTwin, // Optional
                babelPluginMacros,
              ],
            },
          },
        ],
      })

      if (typeof nextConfig.webpack === 'function')
        return nextConfig.webpack(config, options)

      return config
    },
  }
}

Then in your next.config.mjs, import and wrap the main export with withTwin(...):

// next.config.mjs
import withTwin from './withTwin.mjs'

/**
 * @type {import('next').NextConfig}
 */
export default withTwin({
  reactStrictMode: true,
})

Customization

Next steps

Learn how to work with twin

Learn more about emotion