Search code examples
reactjstailwind-cssreact-icons

React Icons affecting Tailwind styling


So I have the following styling:

function Button({
  children,
  primary,
  secondary,
  success,
  warning,
  danger,
  outline,
  rounded,
}) {
  const classes = className("flex items-center px-3 py-1.5 border", {
    "border-blue-500 bg-blue-500 text-white": primary,
    "border-gray-900 bg-gray-900 text-white": secondary,
    "border-green-500 bg-green-500 text-white": success,
    "border-yellow-400 bg-yellow-400 text-white": warning,
    "border-red-500 bg-red-500 text-white": danger,
    "rounded-full": rounded,
    "bg-white": outline,
    "text-blue-500": outline && primary,
    "text-gray-500": outline && secondary,
    "text-green-500": outline && success,
    "text-yellow-400": outline && warning,
    "text-red-500": outline && danger,
  });

  return <button className={classes}>{children}</button>;
}

In Tailwind the last styles listed override the text color and the purpose of that is so if a button is outline then we do not want a text color of white because the background is white in an outline button, so we want the color of the text to change if the button is designated as outline. That is the purpose of the last four lines of classes, but it no longer works ever since I installed react-icons.

By no longer working I mean the "text-white" remains where outline is applied.

Now, I am wondering if the Button.propTypes solution is what clobbering it:

Button.propTypes = {
  checkVariationValue: ({ primary, secondary, success, warning, danger }) => {
    const count =
      Number(!!primary) +
      Number(!!secondary) +
      Number(!!warning) +
      Number(!!success) +
      Number(!!danger);

    if (count > 1) {
      return new Error(
        "Only one of primary, success, warning, danger can be true"
      );
    }
  },
};

Solution

  • When outline is truthy, you will end up in a situation where you will have conflicting classes, like text-white text-blue-500 (for truthy primary). Consider only having a single class with the same variant that applies the same property:

    function Button({
      children,
      primary,
      secondary,
      success,
      warning,
      danger,
      outline,
      rounded,
    }) {
      const classes = classNames("flex items-center px-3 py-1.5 border", {
        "border-blue-500 bg-blue-500": primary,
        "border-gray-900 bg-gray-900": secondary,
        "border-green-500 bg-green-500": success,
        "border-yellow-400 bg-yellow-400": warning,
        "border-red-500 bg-red-500": danger,
        "rounded-full": rounded,
        "text-white": !outline && (primary || secondary || success || warning || danger),
        "bg-white": outline,
        "text-blue-500": outline && primary,
        "text-gray-500": outline && secondary,
        "text-green-500": outline && success,
        "text-yellow-400": outline && warning,
        "text-red-500": outline && danger,
      });
    
      return <button className={classes}>{children}</button>;
    }
    
    ReactDOM.createRoot(document.getElementById('app')).render(
      <React.Fragment>
        <Button primary>Foo</Button>
        <Button primary outline>Foo</Button>
        <Button secondary>Foo</Button>
        <Button secondary outline>Foo</Button>
        <Button success>Foo</Button>
        <Button success outline>Foo</Button>
        <Button warning>Foo</Button>
        <Button warning outline>Foo</Button>
        <Button danger>Foo</Button>
        <Button danger outline>Foo</Button>
      </React.Fragment>
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.3.2/index.min.js" integrity="sha512-GqhSAi+WYQlHmNWiE4TQsVa7HVKctQMdgUMA+1RogjxOPdv9Kj59/no5BEvJgpvuMTYw2JRQu/szumfVXdowag==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdn.tailwindcss.com"></script>
    
    <div id="app"></div>