💫
Nested selectors (ex $ syntax)
tss-react
unlike jss-react
doesn't support the $
syntax but a better alternative.In JSS you can do:
//WARNIG: 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 hover the parent
</div>
</div>

This is how you would achieve the same result with
tss-react
Modern API
makeStyles
export function MyComponent() {
const { classes } = useStyles();
return (
<div className={classes.parent}>
<div className={classes.child}>
Background turns red when mouse is hover 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"
},
}));
An other example:
export function MyComponent() {
const { classes, cx } = useStyles({ "color": "primary" });
return (
<div className={classes.root}>
<div className={classes.child}>
The Background take the primary theme color when the mouse is
hover the parent.
</div>
<div className={cx(classes.child, classes.small)}>
The Background take the primary theme color when the mouse is
hover 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
}
}
}));
export function App() {
const { classes } = useStyles();
return (
<div className={classes.parent}>
<div className={classes.child}>
Background turns red when mouse is hover the parent.
</div>
</div>
);
}
const useStyles = makeStyles<void, "child">()(
(_theme, _params, classes) => ({
"parent": {
"padding": 30,
[`&:hover .${classes.child}`]: {
"backgroundColor": "red"
}
},
"child": {
"backgroundColor": "blue"
},
})
);
An other example:
export function App() {
const { classes, cx } = useStyles({ "color": "primary" });
return (
<div className={classes.root}>
<div className={classes.child}>
The Background take the primary theme color when the mouse is
hover the parent.
</div>
<div className={cx(classes.child, classes.small)}>
The Background take the primary theme color when the mouse is
hover the parent. I am smaller than the other child.
</div>
</div>
);
}
const useStyles = makeStyles<
{ color: "primary" | "secondary" },
"child" | "small"
>()((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 avove 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, ifProxy
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.
NOTE: This do not apply for 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"
.
Example of error you may run against with Next.js
You can fix this error by providing an uniq id when calling
makeStyles
or withStyles
(It will set XXX and YYY). 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 modified 1mo ago