LogoLogo
HomeGitHubPlayground
v4
v4
  • πŸ”§Setup
  • πŸ”API References
    • tss - the Modern API
    • keyframes
    • <GlobalStyles />
    • makeStyles -> useStyles
    • withStyles
  • ⚑SSR
    • Next.js
    • Gatsby
    • Other backends
  • 🎯Increase specificity
  • 🦱classes overrides
  • 🧹Detecting unused classes
  • πŸ’½Emotion Cache
  • πŸ’«Nested selectors (ex $ syntax)
  • 🍭MUI Global styleOverrides
  • πŸ“¦Publish a module that uses TSS
  • 🩳MUI sx syntax
  • πŸ“²React Native
  • πŸ†˜Fix broken styles after upgrading to MUI v5 with TSS
  • ⬆️Migration v3 -> v4
Powered by GitBook
On this page
  • With no classes props
  • With a MUI component
  • With an base HTML component
  • Naming the stylesheets (useful for debugging and theme style overrides)
  • Use in place of styled

Was this helpful?

Edit on GitHub
  1. API References

withStyles

PreviousmakeStyles -> useStylesNextSSR

Last updated 17 days ago

Was this helpful?

It's like but type safe by design.

can often helps when you get red squiggly lines.

MyComponent.tsx
import { withStyles } from "tss-react/mui";

type Props = {
    className?: string;
    classes?: Partial<Record<"root" | "text", string>>;
    colorSmall: string;
};

function MyComponent(props: Props) {

    const classes = withStyles.getClasses(props);

    return (
      // props.classeName and props.classes.root are merged, props.className get higher specificity
      <div className={classes.root}>
        <span className={classes.text}>The background color should be different when the screen is small.</span>
      </div>
    );
}

const MyComponentStyled = withStyles(
    MyComponent, 
    (theme, props) => ({
        root: {
            backgroundColor: theme.palette.primary.main,
            height: 100
        },
        text: {
            border: "1px solid red"
        },
        "@media (max-width: 960px)": {
            root: {
                backgroundColor: props.colorSmall
            }
        }
    })
);

export default MyComponentStyled;
import MyComponent from "./MyComponent";

render(
    <MyComponent 
       className="foo bar"
       classes={{ text: "baz baz" }} 
       colorSmall="cyan" 
    />
);

If you have your styles defined as a separate function:

MyComponent.tsx
import { withStyles } from "tss-react/mui";
import type { Theme } from '@mui/material';

type Props = {
    className?: string;
    classes?: Partial<Record<keyof ReturnType<typeof styles>, string>>;
    colorSmall: string;
};

function MyComponent(props: Props) {

    const classes = withStyles.getClasses(props);

    return (
      // props.classeName and props.classes.root are merged, props.className get higher specificity
      <div className={classes.root}>
        <span className={classes.text}>The background color should be different when the screen is small.</span>
      </div>
    );
}

const styles = (theme: Theme, props: Props) => ({
    root: {
        backgroundColor: theme.palette.primary.main,
        height: 100
    },
    text: {
        border: "1px solid red"
    },
    "@media (max-width: 960px)": {
        root: {
            backgroundColor: props.colorSmall
        }
    }
});

const MyComponentStyled = withStyles(MyComponent, styles);

export default MyComponentStyled;

The main reason you would use withStyles over makeStyles is to support class based components.

MyComponent.tsx
import * as React from "react";
import { withStyles }Β from "tss-react/mui";

export type Props ={
  className?: string;
  classes?: Partial<Record<"root" | "span", string>>;
  isBig: boolean;
};

class MyComponent extends React.Component<Props> {
  render() {
    const classes = withStyles.getClasses(this.props);

    return (
      {/* props.classeName and props.classes.root are merged, props.className get higher specificity */}
      <div className={classes.root}>
        <span className={classes.span}>The background color should be different when the screen is small.</span>
      </div>
    );
  }
}

const MyComponentStyled = withStyles(
  MyComponent, 
  (theme, props) => ({
      root: {
          backgroundColor: theme.palette.primary.main,
          height: props.isBig ? 100 : 50
      },
      span: {
        border: "1px solid red"
      },
      "@media (max-width: 960px)": {
          root: {
              backgroundColor: "red"
          }
      }
  })
);

export default MyComponentStyled;
import MyComponent from "./MyComponent";

render(
    <MyComponent 
       className="foo bar" 
       classes={{ text: "baz baz" }} 
       colorSmall="cyan" 
    />
);

Or, if you have your styles defined as a separate function:

import * as React from "react";
import { withStyles } from "tss-react/mui";
import type { Theme } from '@mui/material';

type Props = {
    className?: string;
    classes?: Partial<Record<keyof ReturnType<typeof styles>, string>>;
    colorSmall: string;
};

class MyComponent extends React.Component<Props> {
  render() {
    const classes = withStyles.getClasses(this.props);

    return (
      {/* props.classeName and props.classes.root are merged, props.className get higher specificity */}
      <div className={classes.root}>
        <span className={classes.span}>The background color should be different when the screen is small.</span>
      </div>
    );
  }
}

const styles = (theme: Theme, props: Props) => ({
    root: {
        backgroundColor: theme.palette.primary.main,
        height: 100
    },
    text: {
        border: "1px solid red"
    },
    "@media (max-width: 960px)": {
        root: {
            backgroundColor: props.colorSmall
        }
    }
});

const MyComponentStyled = withStyles(MyComponent, styles);

export default MyComponentStyled;

With no classes props

Your component can also only have a className prop (and no classes).

MyComponent.tsx
import * as React from "react";
import { withStyles }Β from "tss-react/mui";

export type Props ={
  className?: string;
  isBig: boolean;
};

class MyComponent extends React.Component<Props> {
  render() {
  
    const classes = withStyles.getClasses(this.props);

    return (
      <div className={classes.root}>
        The background color should be different when the screen is small.
      </div>
    );
  }
}

const MyComponentStyled = withStyles(
  MyComponent, 
  (theme, props) => ({
      "root": {
          "backgroundColor": theme.palette.primary.main,
          "height": props.isBig ? 100 : 50
      },
      "@media (max-width: 960px)": {
          "root": {
              "backgroundColor": "red"
          }
      }
  })
);

export default MyComponentStyled;
import MyComponent from "./MyComponent";

render(
    <MyComponent 
       className="foo bar"
       colorSmall="cyan" 
    />
);

With a MUI component

import Button from "@mui/material/Button";
import { withStyles }Β from "tss-react/mui";

const MyStyledButton = withStyles(Button, {
    root: {
        backgroundColor: "grey"
    }
    text: {
        color: "red"
    },
    "@media (max-width: 960px)": {
        text: {
            color: "blue"
        }
    }
});

What's very powerfull about the withStyles API it it's capable to infer the type of the nested overwritable classes, example:

import Breadcrumbs from "@mui/material/Breadcrumbs";
import { withStyles } from "tss-react/mui";

const MyBreadcrumbs = withStyles(
    Breadcrumbs,
    (theme, props, classes) => {
        ol: {
            [`& .${classes.separator}`]: {
                color: theme.palette.primary.main
            }
        }
    }
);

With an base HTML component

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

const MyAnchorStyled = withStyles("a", (theme, { href }) => ({
    root: {
        border: "1px solid black",
        backgroundColor: href?.startsWith("https")
            ? theme.palette.primary.main
            : "red"
    }
}));
import { withStyles }Β from "tss-react/mui";

const MyDiv = withStyles("div", {
  root: {
    /* ... */
  }
}, { name: "MyDiv" });

//The class apllied to the div will be like: "css-xxxxxx-MyDiv-root"

Use in place of styled

If you want to use withStyles instead of styled for the extra type safety it provides:

Before:

import { styled } from '@mui/material/styles';
import Popper from '@mui/material/Popper';

const StyledPopper = styled(Popper)({
  border: '1px solid red',
  '& .Mui-autoComplete-listBox': {
    boxSizing: 'border-box',
    '& ul': {
      padding: 0,
      margin: 0
    }
  },
  "@media (max-width: 960px)": {
    color: "blue"
  }
});

After (just wrap everything into root):

import { withStyles } from 'tss-react/mui';
import Popper from '@mui/material/Popper';

const StyledPopper = withStyles(Popper, {
  root: {
    border: '1px solid red',
    '& .Mui-autoComplete-listBox': {
      boxSizing: 'border-box',
      '& ul': {
        padding: 0,
        margin: 0
      }
    },
    "@media (max-width: 960px)": {
      color: "blue"
    }
  }
});

You can also pass a mui component like for example <Button /> and you'll be able to overwrite (it uses the classes prop).

You can experiment with those examples live , you can also run it locally with .

Naming the stylesheets (useful for debugging and )

To ease debugging you can specify a name that will appear in every class names. It is like the .

It's also required to for .

πŸ”
every rule name of the component
here
here
yarn start_spa
theme style overrides
option.name in material-ui v4's makeStyles
theme style overrides
the material-ui v4 higher-order component API
Using as const