Building class-glue: A Journey into Modern Package Development
Rahul Shetty
Posted on October 27, 2024
The Journey Begins 🚀
I recently decided to dive into open-source contribution by building something I needed in my day-to-day development: a utility for handling CSS class names that works seamlessly with CSS Modules and React Native styles.
The Problem 🤔
If you've worked with CSS Modules or React Native, you've probably written code like this:
// CSS Modules
className={`${styles.container} ${isActive ? styles.active : ''}`}
// React Native
style={[styles.container, isActive && styles.active]}
While libraries like clsx help with class name construction, they don't directly support style objects. This is where class-glue comes in.
The Solution 💡
class-glue provides a unified API for handling both class names and style objects:
// CSS Modules
import createModuleGlue from 'class-glue/merge-module-strings';
import styles from './Card.module.css';
const clgl = createModuleGlue(styles);
function Card({ isHighlighted }) {
return (
<div className={clgl('card', { cardHighlighted: isHighlighted })}>
{/* Resolves to actual CSS Module classes */}
</div>
);
}
// React Native
import createStyleGlue from 'class-glue/merge-styles';
const styles = {
container: { padding: 16, borderRadius: 8 },
active: { backgroundColor: 'blue' }
};
const clgl = createStyleGlue(styles);
function Card({ isActive }) {
return (
<View style={clgl('container', { active: isActive })}>
{/* Merges styles based on conditions */}
</View>
);
}
Technical Deep Dive 🔍
Installation
You can install using your favourite javascript package manager but for the sake of this post -
npm add class-glue
NPM Link: https://www.npmjs.com/package/class-glue
GitHub Link: https://github.com/shettayyy/class-glue
Modular Architecture
The library is split into focused utilities:
-
class-glue
: Core functionality -
join-strings
: String-only operations -
keys-to-strings
: Object-based class generation -
merge-module-strings
: CSS Modules support -
merge-styles
: Style object handling
Each utility is independent and tree-shakeable, ensuring you only bundle what you use.
Bundle Size Optimization
One interesting learning was that for such a small utility, a bundler wasn't necessary. The raw, minified code was already optimal. The entire package is just 425B gzipped!
Type Safety
TypeScript support was a priority. Here's how we handle type inference:
import type { ClassValue } from 'class-glue';
function Button<T extends string>({ className, variant }: {
className?: ClassValue;
variant?: T;
}) {
// Full type safety and inference
}
Learnings & Insights 📚
Building this package taught me several valuable lessons:
- Less is More: For small utilities, avoiding bundlers can actually lead to smaller package size
- Module Systems: Supporting both CommonJS and ESM requires careful consideration
- NPM Workflow: Understanding pre/post scripts and entry points
- GitHub Features: Branch rulesets, discussions, sponsorship setup
- Documentation: The importance of clear, example-driven docs
Get Involved 🤝
The project is open source and welcomes contributions! You can:
- Star the repository
- Try it out:
npm install class-glue
- Provide feedback
- Contribute code or documentation
GitHub Link: https://github.com/shettayyy/class-glue
Conclusion
What started as a simple utility grew into a learning journey about modern package development. The biggest takeaway? No contribution to open source is too small - you often gain more knowledge than you give.
Posted on October 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.