How can I consistently overwrite JSS styles which have indeterminate suffixes?

1.2k views Asked by At

I’m looking for advice around @material-ui/core in react,

TLDR;

I would appreciate a consistent approach for handling CSS-in-js generated classNames which have indeterminate numeric suffixes, while still using @material-ui/core's styled() function if possible.

Specifically

“the class names generated by @material-ui/core/styles are non-deterministic” (https://material-ui.com/styles/advanced/#class-names), but so far at my company the projects I’ve been on have used the styled() function for wrapping components to apply styles.

It works great, until I want to overwrite how one of the pseudo-classes applies to the root element that I’m styling. At which point, if I try to use a regular old class-selector to take control of the styling in ta specific state, it’ll work if there’s no suffix on the class, but as soon as the JSS generated className has a numeric suffix, it breaks.

When I say "suffix" I'm referring to how a component's root className might be .makeStyles-root but when the className is generated for that specific instance, it likely has a numeric suffix appended: .makeStyles-root-123

For example:

Component: InputLabel https://material-ui.com/api/input-label/#inputlabel-api I want to fiddle with the transform that happens, which comes from .MuiInputLabel-formControl, but then that transform is overwritten by .MuiInputLabel-shrink.

If I try using a regular class selector:

export const InputLabel = styled(MuiInputLabel)({
  `&.MuiInputLabel-formControl`: {
    transform: 'translate(2px, 8px) scale(1)',
  },
  `&.MuiInputLabel-shrink`: {
    transform: 'translate(0) scale(0.6)',
  },
});

It works only if the JSS class doesn’t have a suffix,

and if I try using the rule names (I don’t think it’s actually supported with styled())

export const InputLabel = styled(MuiInputLabel)({
  formControl: {
    transform: 'translate(2px, 8px) scale(1)',
  },
  shrink: {
    transform: 'translate(0) scale(0.6)',
  },
});

It just applies invalid rules to the element:

    formControl: [object Object]
    shrink: [object Object];

I've also tried passing classes (but that didn't seem to work at all)

export const InputLabel = styled((props) => (
  <MuiInputLabel
    classes={{
      formControl: {
        transform: 'translate(2px, 8px) scale(1)',
      },
      shrink: {
        transform: 'translate(0) scale(0.6)',
      },
    }}
    {...props}
  />
))({});

Further Notes

  • I don’t want to use a theme override (which I imagine would enable the use of those rules here) because I don’t want this styling to apply to all instances of a InputLabel

  • so that leaves me leaning towards using the hook api / makeStyles() : https://material-ui.com/styles/basics/#hook-api

    • But that doesn’t lend itself well to current patterns with style files.

Related

1

There are 1 answers

0
jnotelddim On

As far as I can tell, it isn't possible to do this with styled(),

so I've just gone with what other posts have suggested and used makeStyles().

However I have used a bit of a mash-up of the two, so that I can still keep my styling in a separate file.

const useLabelStyles = makeStyles((theme) => ({
  root: {
    color: theme.text.primary,
  },
  formControl: {
    transform: 'translate(2px, 8px) scale(1)',
  },
  shrink: {
    transform: 'translate(0) scale(0.6)',
  },
}));

export const InputLabel = styled((props) => {
  const theme = useTheme();
  const classes = useLabelStyles(theme);
  return (
    <MuiInputLabel
      classes={classes}
      {...props}
    />
  );
})({});