How to combine TailwindCSS, Material-UI and Twin Macro for React Application.

Sandy Goodnews
4 min readOct 1, 2022

--

Problem: How do you combine TailwindCSS theme with Material-UI Theme in an Application? In other words, how do I make MUI theme work with TailwindCSS utility classes?

Solution: Twin Macro

Table of Contents

Introduction

In large project, you may need to maintain styling themes and ensure that patterns are reusable across the codebase. This is very crucial if you are using different styling libraries.
In this article , i will illustrate how to use Twin Macro to combine styling themes from TailwindCSS and Material-UI libraries for a Vite React TypeScript Application .

Definitions

Twin Macro is a library that makes TailwindCSS able to work with other CSS-in-JS libraries such as styled-component, and Emotion. With this library, you have a wider range of styling capabilities.

TailwindCSS: is a styling library that uses utility first styling this means styling is done as class names. It’s a direct styling and handles mobile and web views. With TailwindCSS, there is no need for external CSS classes and Ids, you can build a complete custom design without ever leaving your HTML.

Material-UI: is a popular React UI library that offers different design components to create a user interface in applications. These components already exist and developers do not have to build them from scratch.

Vite: It’s just blazingly fast for Front-end development. See the article for the Vite setup. You can find Vite starter packages in Docs

Prerequisites

  • Knowlege of React application
  • Knowlege of Javascript and;
  • Basic command line

Installation and Set-up

1. Setup a Vite-React application with TailwindCSS for styling

You can follow the docs for installation.

  • Install the Vite-React-typescript application package.
    npm create vite@latest my-project — — template react-ts
  • Install TailwindCSS and generate your Tailwind and PostCSS config files.
    npm install -D tailwindcss postcss autoprefixer
    npx tailwindcss init -p
  • If your file is in commonjs(.cjs), you can rename it to .js and remove the type: “module” on the package.json file.
  • Add the paths to files and configure your styling settings in the tailwind.config.js file. As shown below,
/** @type {import(‘tailwindcss’).config} */
module.exports = {
mode: “jit”,
content: [“./src/**/*.{ts,tsx}”, “./components/**/*.{ts,tsx}”],
theme: {
extend: {
colors: {
primary: “hsla(120, 100% ,25%,1)”,
secondary: “hsla(330, 100% ,71%,1)”,
},
},
},
plugins: [],
};
  • Add the Tailwind directives to the app global css file. You could add this to your App.css file
//App.css
@tailwind base;
@tailwind components;
@tailwind utilities;

2. Setup Material-UI

  • Install Material-UI packages. See docs
    yarn add @mui/material @emotion/react @emotion/styled
    or
    npm install @mui/material @emotion/react @emotion/styled
  • Create a theme.tsx file in the src folder and add the following,
// theme.tsx file
import { createTheme } from “@mui/material/styles”;
const theme = createTheme({});
export default theme;
  • Add MUI Theme Provider to the App global file(main.tsx) as follow:
// main.tsx
import React from “react”;
import ReactDOM from “react-dom/client”;
import App from “./App”;
import { ThemeProvider } from “@mui/material”;
import theme from “./theme”;

ReactDOM.createRoot(document.getElementById("root")
as HTMLElement).render(<React.StrictMode>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</React.StrictMode>
);

3. Setup Twin Macro

  • To Install the Twin Macro package, you can follow the docs here.
    yarn add twin.macroor npm install twin.macro
  • Install babel-plugins to support styling.
yarn add babel-plugin-macros @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx -D
or
npm install babel-plugin-macros @emotion/babel-plugin-jsx-pragmatic @babel/plugin-transform-react-jsx -D
  • Add the following codes to the vite config.js file,
// vite config.js

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',
],
],
},
}),
],
  • And since we are using Typescript, we install a package to handle types in React.
    yarn add @types/react -D or npm install @types/react -D
  • Create a file types/twin.d.ts in the root directory and add the following code:
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
}
}

Combining styling themes

  • Using TailwindCSS utilty styling in MUI Theme
    To extend the TailwindCSS theme to the MUI theme configuration file(theme.tsx), we import the tw and tailwindTheme modules from Twin Macro.
/// theme.tsx

import { createTheme } from "@mui/material/styles";
import tw, { theme as tailwindTheme } from "twin.macro";const theme = createTheme({
palette: {
primary: {
main: tailwindTheme`colors.primary`,
},
secondary: {
main: tailwindTheme`colors.secondary`,
},
},
components: {
MuiButton: {
styleOverrides: {
containedPrimary: {
...tw`bg-primary text-lg font-bold`,
color: tailwindTheme`colors.black`,
},
outlinedSecondary: {
backgroundColor: tailwindTheme`colors.secondary`,
color: tailwindTheme`colors.white`,
},
sizeLarge: {
height: "3.5rem",
...tw`px-8 text-base`,
},
},
},
},
});export default theme;
  • Let’s update the App.tsx file as follows:
import "./App.css";
import { Button } from "@mui/material";
import "twin.macro";

function App() {
return (
<div>
{/* customizing MUI Buttons */}
<div className="flex flex-col w-64 gap-y-6">
<Button variant="contained" color="primary">
Contained
</Button>
<Button variant="outlined" color="secondary">
Outlined
</Button>
<Button variant="outlined">Outlined</Button>
</div>
{/* using tw directly */}
<div className="my-6">
<input
placeholder="text here"
tw="border border-primary hover:border-secondary"
/>
</div>
</div>
);
}
export default App;

Result

Conclusion

With that, the MUI theme is in sync with the TailwindCSS styling theme. You can go ahead to add more theme to your TailwindCSS and use it in your MUI Theme. Twin macro can also be used for direct styling on HTML elements too.

Resources

Repository link: https://github.com/sandygudie/vite-material-ui-ts

--

--

Sandy Goodnews

Software developer. Imaginative. I love to try, I write to relearn and reinforce while sharing the knowledge.