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"
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;
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>
);
};