npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

tailwind-dx

v1.0.7

Published

DX utility for organizing Tailwind classNames semantically

Readme

🌀 tailwind-dx

npm build coverage license bundle size

Better classNames. Less eye-bleed. DX that actually feels good.

tailwind-dx is a tiny utility that helps you write readable, maintainable Tailwind classNames by organizing them by intent — like layout, spacing, typography, and more.

No more 200-character className strings that look like a CSS ransom note.


🚀 Why tho?

Tailwind is awesome. But reading your class strings after 3 espressos and 5 months of tech debt?

'flex items-center justify-between px-4 py-2 text-gray-800 shadow rounded-md';

Now compare:

twDX({
	layout: 'flex items-center justify-between',
	spacing: 'px-4 py-2',
	typography: 'text-gray-800',
	effects: 'shadow',
	borders: 'rounded-md',
});

Boom. Readable. Maintainable. Your eyes and your team will thank you.


✨ Features

  • 🧠 Group Tailwind classes by purpose (layout, spacing, typography, etc.)
  • 🧱 Support for reusable class presets (like card, buttonPrimary, etc.)
  • 🧼 Cleaner className logic in React, Preact, Solid, whatever.
  • 🦾 Written in TypeScript. Minimal. Zero deps.
  • 🎯 ESLint validation for proper class categorization
  • 🌈 Support for responsive, state, and dark mode variants
  • 🤖 LLM-friendly structure for better AI assistance

🤖 LLM & IDE Friendly

tailwind-dx is designed to be extremely friendly for both LLM coding agents and IDE autocompletion:

  1. Structured Input: The layer-based organization makes it easy for LLMs to understand and generate code
  2. ESLint Validation: Automatic validation of class placement in correct layers
  3. Predictable Patterns: Consistent structure makes it easier for AI to generate correct code
  4. Self-Documenting: The layer names serve as natural documentation
  5. IDE Support: Get autocompletion for:
    • Layer names (layout, spacing, typography, etc.)
    • Class names within each layer
    • Variants (responsive, state, dark mode)

Example of LLM-friendly code generation:

// Easy for LLMs to understand and generate
twDX({
	layout: 'flex items-center justify-between',
	spacing: 'px-4 py-2',
	typography: 'text-gray-800 dark:text-white',
	effects: 'shadow hover:shadow-lg',
	borders: 'rounded-md focus:ring-2',
});

📦 Installation

npm install tailwind-dx

or

yarn add tailwind-dx

🛠️ Usage

Basic usage

import { twDX } from 'tailwind-dx';

const className = twDX({
	layout: 'flex items-center justify-between',
	spacing: 'px-4 py-2',
	typography: 'text-gray-800',
	borders: 'rounded-md',
	effects: 'shadow-md',
});

ESLint Integration

To enforce proper class placement in your project, add the ESLint plugin:

  1. Install the plugin:
npm install -D tailwind-dx
  1. Add to your ESLint config:

For traditional config (.eslintrc.js):

module.exports = {
	plugins: ['tailwind-dx'],
	extends: ['plugin:tailwind-dx/recommended'],
	// ... your other config
};

For flat config (eslint.config.js):

import tailwindDxPlugin from 'tailwind-dx/eslint-rules';

export default [
	{
		plugins: {
			'tailwind-dx': tailwindDxPlugin,
		},
		rules: {
			'tailwind-dx/layers': 'error',
		},
	},
];

Now ESLint will validate that your classes are in the correct layers:

// ❌ This will show an error
twDX({
	layout: 'text-lg', // Error: Class "text-lg" should be in the "typography" layer
	typography: 'flex', // Error: Class "flex" should be in the "layout" layer
});

// ✅ This is correct
twDX({
	layout: 'flex',
	typography: 'text-lg',
});

Use with variants

twDX({
	// Responsive variants
	layout: 'flex md:flex-col lg:flex-row',

	// Dark mode variant
	typography: 'text-gray-800 dark:text-white',

	// State variants
	effects: 'shadow hover:shadow-lg',
	borders: 'rounded-md focus:ring-2',
});

Use with presets

twDX({ preset: 'card' });

You can define your own presets in src/index.ts or extend it in your own wrapper.

const presets = {
	card: 'bg-white rounded-lg shadow-md p-4',
	buttonPrimary: 'bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700',
	centerFlex: 'flex justify-center items-center',
};

🧪 Real-world example

export function Card() {
	return (
		<div
			className={twDX({
				layout: 'flex flex-col gap-4',
				typography: 'text-gray-800 dark:text-white',
				spacing: 'p-6',
				borders: 'rounded-xl',
				effects: 'shadow-lg hover:shadow-xl',
			})}
		>
			<h2 className={twDX({ typography: 'text-xl font-bold' })}>
				Hello, TailwindDX
			</h2>
			<p
				className={twDX({
					typography: 'text-sm text-gray-500 dark:text-gray-400',
				})}
			>
				Clean classNames, clean mind.
			</p>
		</div>
	);
}

⚙️ Pro Tips

Want conditional classes? Use with clsx or classnames:

import { clsx } from 'clsx';

const className = clsx(
	twDX({ preset: 'card' }),
	isActive && 'ring-2 ring-blue-500',
);

🧙 Roadmap (aka Things I Might Do While Procrastinating)

  • 🧩 Plugin system for presets
  • 🧠 VSCode IntelliSense extension
  • 🧼 Linter plugin to auto-split long classNames into twDX
  • 🪄 Babel/TS transform that turns twDX into strings at build time

🧑‍💻 Contributing

Got ideas? Found bugs? Want to add a tailwind-dx theme song? Open a PR or issue. We're just getting started.


🪪 License

MIT — use it, abuse it, remix it.


✨ Final thought

Writing Tailwind should feel like composing UI, not like decoding The Matrix.
Let tailwind-dx clean up your className soup. 🍜