Classes Helper

Published 5-12-2022 @ 07:45:00

Last updated 8-12-2023 @ 17:13:30

As a developer I tend to lean more towards standards over implementation. I am really not that bothered if something takes 2ms longer to compile or execute if it means that most developers will be better able to read and understand the code in the future. For this same reason I prefer tools like LitElement over React. While React is definitely the industry standard at this point, a lot of the logic is "cleverly" hidden and structured instead of being transparent and more aligned with standards.

One thing that Lit and React have in common is that they both require you to pass a string for CSS classes. There are a million packages on npm that will help you with this specific issue, but why install, update and maintain dependencies for something you can write yourself in 10 minutes? In most projects, I find myself crossing a point where the .join(' ')s become cumbersome and I whip up a variation on the following:

typescript
export const classes = (input: string | string[] | Record<string, boolean>): string => {
if (Array.isArray(input)) {
return input.join(' ');
}
if (typeof input === 'object') {
return Object.entries(input)
.filter(([_key, value]) => !!value)
.map(([key]) => key)
.join(' ');
}
return input;
};

This allows you to do the following in your components:

jsx
<div
className={classes({
[styles.example]: true,
[styles.active]: active,
globalStyle: someCheck && theOtherCheck > 5 && !thisCheck,
})}
>
Hello World!
</div>

The implementation in LitElement could look something like:

javascript
get wrapperClasses() {
return classes({
example: true,
active: this.active,
globalStyle: this.someCheck && this.theOtherCheck > 5 && !this.thisCheck,
});
}
render() {
return `<div class="${this.wrapperClasses()}">Hello World!</div>`;
}

I regularly update this function when we think of a smart addition to it.

React
JS
Utility