🔧
Setup
Start using TSS, with or without MUI
With MUI - makeStyles API
With MUI - Modern API
Standalone
Think of the
makeStyles
and withStyles
APIs as continuity solutions that replace the deprecated API of the same name, which was provided in Material-UI v4. Migration guide on the MUI website.Rest assured, these APIs are here to stay and are not on the path to deprecation. However, if you are willing to deviate slightly from the familiar Material-UI API, you are encouraged to explore and adopt the Modern API. It is designed to be more readable and user-friendly, offering a cleaner and more intuitive approach to styling your components.
After completing your migration, if elements do not display as they used to, do this and everything should work.
yarn add @mui/material @emotion/styled @emotion/react #Required for MUI
yarn add tss-react
src/MyButton.tsx
import { makeStyles, withStyles } from "tss-react/mui"; // "tss-react/mui-compat" if your project is using Typescript < 4.4
import Button from "@mui/material/Button";
import { useState } from "react";
type Props = {
className?: string;
};
export function MyButton(props: Props) {
const { className } = props;
const [isClicked, setIsClicked] = useState(false);
const { classes, cx } = useStyles({ "color": isClicked ? "blue": "red" });
//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 (
<Button
className={cx(classes.root, className)}
onClick={()=> setIsClicked(true)}
>
hello world
</Button>
);
}
const useStyles = makeStyles<{ color: "red" | "blue" }>()(
(theme, { color }) => ({
root: {
// The color of the text is either blue or red depending of
// the state fo the component.
color,
// When the curser is over the button has a black border
"&:hover": {
border: '4px solid black'
},
// On screens bigger than MD the button will have a big cyan border
[theme.breakpoints.up("md")]: {
border: '10px solid cyan'
}
}
})
);
Introduced in v4.9
yarn add @mui/material @emotion/styled @emotion/react #Required for MUI
yarn add tss-react
src/MyButton.tsx
import { tss } from "tss-react/mui";
import Button from "@mui/material/Button";
import { useState } from "react";
type Props = {
className?: string;
};
export function MyButton(props: Props) {
const { className } = props;
const [isClicked, setIsClicked] = useState(false);
const { classes, cx } = useStyles({ "color": isClicked ? "blue": "red" });
//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 (
<Button
className={cx(classes.root, className)}
onClick={()=> setIsClicked(true)}
>
hello world
</Button>
);
}
const useStyles = tss
.withParams<{ color: "red" | "blue"; }>()
.create(({ theme, color })=> ({
root: {
// The color of the text is either blue or red depending of
// the state fo the component.
color,
// When the curser is over the button has a black border
"&:hover": {
border: '4px solid black'
},
// On screens bigger than MD the button will have a big cyan border
[theme.breakpoints.up("md")]: {
border: '10px solid cyan'
}
}
}));
yarn add tss-react @emotion/react
src/tss.ts
import { createTss } from "tss-react";
function useContext() {
const myTheme = {
primaryColor: "#32CD32", // This is LimeGreen in hex
};
// You can return anything here, you decide what's the context.
return { myTheme };
}
export const { tss } = createTss({ useContext });
export const useStyles = tss.create({});
src/MyComponents.tsx
import { useState } from 'react';
import { tss } from './tss';
// NOTE: If you don't have a theme you can import { tss } from "tss-react";
export type Props = {
className?: string;
};
export function MyComponent(props: Props) {
const { className } = props;
const [color, setColor] = useState<'red' | 'blue'>('red');
const { classes, cx /*,myTheme*/ } = useStyles({ color });
//Thanks to cx, className will take priority over classes.root 🤩
return (
<span
className={cx(classes.root, className)}
onClick={() => setColor('blue')}
>
hello world
</span>
);
}
const useStyles = tss
.withParams<{ color: 'red' | 'blue'; }>()
.create(({ myTheme, color }) => ({
root: {
cursor: 'pointer',
// The color of the text is red or blue depending on the state of the component
color,
// When mouse is hover, green border
'&:hover': {
border: `4px solid ${myTheme.primaryColor}`,
},
// On big screen, a big black border
'@media (min-width:48em)': {
border: '10px solid black',
}
}
}));
If you don't want to end up writing things like:
import { makeStyles } from "../../../../../../tss";
In Vite, you can put
"baseUrl": "src"
in your tsconfig.json and import things relative to your src/
directory.In the above example it would be:
import { makeStyles } from "tss";
Last modified 1mo ago