๐Ÿ”งSetup

Start using TSS, with or without MUI

tss-react has over 170 000 monthly NPM download and fewer than 220 โญ๏ธ on GitHub.

If you use TSS in production, please consider giving the project a star.

yarn add tss-react @emotion/react @mui/material @emotion/styled

If you are migrating from @material-ui/core (v4) to @mui/material (v5) checkout the migration guide from MUI's documentation website here.

import { render } from "react-dom";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import { ThemeProvider } from "@mui/material/styles";

export const muiCache = createCache({
    "key": "mui",
    "prepend": true
});

//NOTE: Don't use <StyledEngineProvider injectFirst/>
render(
    <CacheProvider value={muiCache}>
        <ThemeProvider theme={myTheme}>
            <Root />
        </ThemeProvider>
    </CacheProvider>,
    document.getElementById("root")
);

As a MUI user (if you are using TypeScript >= v4.4), you can simply:

import { makeStyles, withStyles } from "tss-react/mui";

The theme object that will be passed to your callbacks functions will be the one you get with import { useTheme } from "@mui/material/styles".

If you want to take controls over what the theme object should be, you can re-export makeStyles and withStyles from a file called, for example, makesStyles.ts:

import { useTheme } from "@mui/material/styles";
//WARNING: tss-react require TypeScript v4.4 or newer. If you can't update use:
//import { createMakeAndWithStyles } from "tss-react/compat";
import { createMakeAndWithStyles } from "tss-react";

export const { makeStyles, withStyles } = createMakeAndWithStyles({
    useTheme
    // OR, if you have extended the default mui theme adding your own custom properties: 
    // Let's assume the myTheme object that you provide to the <ThemeProvider /> is of 
    // type MyTheme then you'll write:
    //"useTheme": useTheme as (()=> MyTheme)
});

./MyComponent.tsx

import { makeStyles } from "tss-react/mui";
//OR:
//import { makeStyles } from "./makeStyles";

export function MyComponent(props: Props) {
    const { className } = props;

    const [color, setColor] = useState<"red" | "blue">("red");

    const { classes, cx } = useStyles({ color });

    //Thanks to cx, className will take priority over classes.root ๐Ÿคฉ
    //With TSS you must stop using clsx and use cx instead.
    //More info here: https://github.com/mui/material-ui/pull/31802#issuecomment-1093478971
    return <span className={cx(classes.root, className)}>hello world</span>;
}

const useStyles = makeStyles<{ color: "red" | "blue" }>()(
    (theme, { color }) => ({
        "root": {
            color,
            "&:hover": {
                "backgroundColor": theme.primaryColor
            }
        }
    })
);

Keep @emotion/styled as a dependency of your project.

Even if you never use it explicitly, it's a peer dependency of @mui/material.

Storybook: As of writing this lines storybook still uses by default emotion 10. Material-ui and TSS runs emotion 11 so there is some changes to be made to your .storybook/main.js to make it uses emotion 11.

You can detect unused classes with this ESLint plugin.

If you don't want to end up writing things like:

import { makeStyles } from "../../../../../../makeStyles";

You can put "baseUrl": "src" in your tsconfig.json and import things relative to your src/ directory.

Last updated