garronej / tss-react

✨ Dynamic CSS-in-TS solution, based on Emotion
https://tss-react.dev
MIT License
608 stars 37 forks source link

Marged styles using with `cx` is defferent from using `styled` #56

Closed kazukinagata closed 2 years ago

kazukinagata commented 2 years ago

First of all, thanks for creating a great library!

I'm migrating a project from using jss towards tss-react but I'm struggling with the different style order when using cx.

Codesandbox is here.

I have two components (Parent and Child), and I want to override the objectFit property of img tag from Parent.

const useStyles = makeStyles()(() => ({
  logo: {
    width: "100%",
    height: "53px",
    objectFit: "contain"
  }
}));

export const Parent = () => {
  const { classes } = useStyles();
  const src =
    "https://ichef.bbci.co.uk/news/640/cpsprodpb/17A21/production/_85310869_85310700.jpg";
  return (
    <>
      <Box width="200px" height="106px">
        <Child src={src} className={classes.logo} />
      </Box>
    </>
  );
};
import { makeStyles } from "tss-react/mui";

const useStyles = makeStyles()(() => ({
  img: {
    objectFit: "cover"
  }
}));

type Props = {
  className?: string;
  src: string;
};
export const Child = ({ className, src }: Props) => {
  const { classes, cx } = useStyles();
  return <img src={src} className={cx(className, classes.img)} />;
};

The style generated by cx is as follows.

.tss-5qt1p9-logo-img {
    width: 100%;
    height: 53px;
    object-fit: contain;
    object-fit: cover; // The style declared in the child component wins.
}

// Expected result
.tss-5qt1p9-logo-img {
    width: 100%;
    height: 53px;
    object-fit: cover;
    object-fit: contain;
}

Using styled instead of makeStyles get the expected result.

garronej commented 2 years ago

Hi @kazukinagata,

First of all, thanks for creating a great library!

Thank you for showing your apreciation!

Sorry, I dont have time to actually deal with this issue right now but reading through it I noticed:

- return <img src={src} className={cx(className, classes.img)} />;
+ return <img src={src} className={cx(classes.img, classeName)} />;

The className passed as prop should always have a higher priority from the internal state to allow the user of the component to overwrite whatever he see fit. Thus, props.className shoud always be the last cx argument.

kazukinagata commented 2 years ago

@garronej You were right! I'm a newbie to emotion, so it was very helpful to learn from you.