I cannot find a way to get both a local rule reference (named '& $value' in the code below) to fully work in conjunction with using functions for CSS definitions. Any CSS properties that are defined using a function accepting a StyleProperties object and returning a CSS value are simply ignored when defined for rules that reference other local rules; please see code and comments:
import * as React from "react";
import { Theme, makeStyles, createStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import clsx from "clsx";
type StyleProperties = {
scale: number;
};
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: (props: StyleProperties) => {
const size = `${2.0 * props.scale}rem`;
return {
position: "relative",
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.palette.divider}`,
width: size,
height: size,
"& > div": {
position: "absolute"
}
};
},
value: {
color: theme.palette.text.primary,
width: "100%",
height: "100%",
textAlign: "center",
lineHeight: (props: StyleProperties) => `${2.0 * props.scale}rem`
},
static: {
"& $value": {
// Following are OK
color: theme.palette.action.disabled,
backgroundColor: theme.palette.action.disabledBackground,
// Ignored
border: (props: StyleProperties) =>
`${0.0625 * props.scale}rem solid red`
// Comment out above line and uncomment the following to see expected output
// if the value 2.0 was passed in through props.
//border: `${ 0.0625 * 2.0 }rem solid red`,
}
}
})
);
type ValueProperties = {
value: string;
scale: number;
};
function Value(props: ValueProperties) {
const classes = useStyles(props);
return <div className={clsx(classes.value)}>{props.value}</div>;
}
type CellProperties = {
static: boolean;
scale: number;
};
function Cell(props: CellProperties) {
const classes = useStyles(props);
return (
<div className={clsx(classes.root, { [classes.static]: props.static })}>
<Value value="value" scale={props.scale} />
</div>
);
}
export default function App() {
return (
<div className="App">
<CssBaseline />
<Cell static={false} scale={2.0} />
<Cell static={true} scale={2.0} />
</div>
);
}
I have also tried using a function accepting my StyleProperties object at both static and '& $value' rule levels rather than at the CSS Property levels, but both approaches fully ignored all CSS definitions found within '& $value'.
There are no error messages or warnings output when using the code above. After searching around through the documentation of both Material-UI and JSS I did not find any mention of known limitations relating to this scenario.
Ultimately, defining the CSS based on values provided by StyleProperties and the Material-UI Theme is a strict requirement for the interface of my application. So if you would like to suggest an alternate approach to declaring hierarchy based style rules, please keep that in mind.
EDIT: As requested I am providing a code sandbox to demonstrate the issue: https://codesandbox.io/s/relaxed-bird-sklgr -- see border definition on line 43 and the fact it is not being applied.
The issue is that you are calling
useStylesfrom bothCellandValue. This causes two different classes to be generated for thevaluerule and two different classes to be generated for thestaticrule. Thevalueclass generated forCellis being referenced by"& $value"in thestaticclass applied toCell, but it is thevalueclass generated forValuethat is applied to theValueelement, so it isn't matched by the descendant selector in thestaticclass.You can fix this by only calling
useStylesin one place and passing thevalueclass name down to theValueelement as in the example below: