๐Ÿ’ซNested selectors (ex $ syntax)

tss-react unlike jss-react doesn't support the $ syntax but is a better alternative.

With the Modern API and makeStyles API

In JSS you can do:

//WARNING: This is legacy JSS code!
{
  "parent": {
      "padding": 30,
      "&:hover $child": {
          "backgroundColor": "red"
      },
  },
  "child": {
      "backgroundColor": "blue"
  }
}
//...
<div className={classes.parent}>
    <div className={classes.child}>
        Background turns red when the mouse is hovering over the parent
    </div>
</div>

This is how you would achieve the same result with tss-react

export function MyComponent() {
    const { classes } = useStyles();

    return (
        <div className={classes.parent}>
            <div className={classes.child}>
                Background turns red when the mouse is hovering over the parent.
            </div>
        </div>
    );
}

const useStyles = tss
    .withName("MyComponent") // It's important to set a name in SSR setups
    .withNestedSelectors<"child">()
    .create(({ classes }) => ({
        "parent": {
            "padding": 30,
            [`&:hover .${classes.child}`]: {
                "backgroundColor": "red"
            }
        },
        "child": {
            "backgroundColor": "blue"
        },
    }));

Another example:

export function MyComponent() {
    const { classes, cx } = useStyles({ "color": "primary" });

    return (
        <div className={classes.root}>
            <div className={classes.child}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent.
            </div>
            <div className={cx(classes.child, classes.small)}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent. I am smaller than the other child.
            </div>
        </div>
    );
}

const useStyles = tss
    .withName("MyComponent") 
    .withNestedSelectors<"child" | "small">()
    .withParams<{ color: "primary" | "secondary" }>()
    .create(({ theme, color, classes })=> ({
        root: {
            padding: 30,
            [`&:hover .${classes.child}`]: {
                backgroundColor: theme.palette[color].main
            }
        },
        small: {},
        child: {
            border: "1px solid black",
            height: 50,
            [`&.${classes.small}`]: {
                height: 30
            }
        }
    }));
The render of the above code

WARNING: Nested selectors requires ES6 Proxy support which IE doesn't support. It can't be polyfilled (this will not work) but don't worry, if Proxy is not available on a particular browser, no error will be thrown and TSS will still do its work. Only nested selectors won't work.

withStyles

SSR

NOTE: This does not apply to the Modern API

In SSR setups, on stylesheets using nested selectors, you could end up with warnings like:

Warning: Prop className did not match. Server: "tss-XXX-root-ref" Client: "tss-YYY-root-ref".

You can fix this error by providing a unique id when calling makeStyles or withStyles (It will set XXX and YYY).

Short unique identifiers can be generated with this website.

 const useStyles = makeStyles<
     { color: "primary" | "secondary" },
     "child" | "small"
 >({
     name: "MyComponent"
+    uniqId: "QnWmDL"
 })((theme, { color }, classes) => ({
     "root": {
         "padding": 30,
         [`&:hover .${classes.child}`]: {
             "backgroundColor": theme.palette[color].main
         }
     },
     "small": {},
     "child": {
         "border": "1px solid black",
         "height": 50,
         [`&.${classes.small}`]: {
             "height": 30
         }
     }
 }));
 
  const MyBreadcrumbs = withStyles(
     Breadcrumbs,
     (theme, _props, classes) => ({
         "ol": {
             [`& .${classes.separator}`]: {
                 "color": theme.palette.primary.main
             }
         }
     }), 
     {
          name: "MyBreadcrumbs",
+         uniqId: "vZHt3n" 
     }
 );

withStyles:

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

Last updated