简体   繁体   中英

How to format tailwind classes in a cleaner way for re-usable styles dynamically?

I am making this reusable badge using Tailwind CSS where the colour of the badge is supposed to change depending on the status. The result is very unclean and I am looking for a way to optimise this.

I have tried using string literals to try make the styles cleaner as following;

bg-${color}-100 and same fo other classNames. Apparently this does not work because tailwind expects you to pass a full class name like this bg-green-100 . This means I have to conditionally check for each colour as this color === "green"? "bg-green-100": "bg-red-100" color === "green"? "bg-green-100": "bg-red-100" this forces you to write so many classes if you have a lot of colour props that you are checking.

This is how to whole component looks like

import ctl from "@netlify/classnames-template-literals";
interface BadgeProps {
  color: string;
  status: string | boolean;
}

function Badge({ color, status }: BadgeProps) {
  return <span className={badgeStyle(color)}>{status}</span>;
}


const badgeStyle = (color: string) =>
  ctl(
   `
    ${
      color === "green"
        ? `bg-green-100 text-green-800  ${containerStyle} dark:bg-green-900 dark:text-green-300`
        : color === "red"
        ? `bg-red-100 text-red-800  ${containerStyle} dark:bg-red-900 dark:text-red-300`
        : color === "yellow"
        ? `bg-yellow-100 text-yellow-800  ${containerStyle} dark:bg-yellow-900 dark:text-yellow-300`
        : color === "blue"
        ? "bg-blue-100 text-blue-800  ${containerStyle} dark:bg-blue-900 dark:text-blue-300"
        : color === "indigo"
        ? `bg-indigo-100 text-indigo-800  ${containerStyle} dark:bg-indigo-900 dark:text-indigo-300`
        : color === "purple"
        ? `bg-purple-100 text-purple-800  ${containerStyle} dark:bg-purple-900 dark:text-purple-300`
        : color === "pink"
        ? `bg-pink-100 text-pink-800  ${containerStyle} dark:bg-pink-900 dark:text-pink-300`
        : color === "orange"
        ? `bg-orange-100 text-orange-800  ${containerStyle} dark:bg-orange-900 dark:text-orange-300`
        : color === "gray"
        ? `bg-gray-100 text-gray-800  ${containerStyle} dark:bg-gray-900 dark:text-gray-300`
        : color === "gray"
        ? `bg-gray-100 text-gray-800  ${containerStyle} dark:bg-gray-900 dark:text-gray-300`
        : ""
    }
   
    `
  );

const containerStyle = ctl(`
 font-medium mr-2 px-2.5 py-0.5 rounded  text-sm text-sm
  `);

export default Badge;

The only option would be to reformat these ternary statements into a dictionary as per their documentation. Source

function Button({ color, children }) {
  const colorVariants = {
    blue: 'bg-blue-600 hover:bg-blue-500',
    red: 'bg-red-600 hover:bg-red-500',
  }

  return (
    <button className={`${colorVariants[color]} ...`}>
      {children}
    </button>
  )
}

You could create a separate file that maps the different color props to the corresponding Tailwind classes .

Create file called colorClasses.js that exports an object with the different color props as keys , and the corresponding Tailwind classes as values .

colorClasses.js

export default {
  green: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
  red: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
  yellow: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
  blue: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
  indigo: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300',
  purple: 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300',
  pink: 'bg-pink-100 text-pink-800 dark:bg-pink-900 dark:text-pink-300',
  orange: 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300',
  gray: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
}

Then in your component file, you can import the colorClasses object and use it to dynamically set the class names based on the color prop.

import colorClasses from './colorClasses';

const Badge = ({ color }) => {
  const containerStyle = 'font-medium mr-2 px-2.5 py-0.5 rounded text-sm';
  const colorClass = colorClasses[color];
  return (
    <div className={`${colorClass} ${containerStyle}`}>
      {/* Your content here */}
    </div>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM