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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@batthewz/response-ui-tw-merge

v0.1.3

Published

tailwind-merge configured for the response-ui design system's custom utilities (r1..r6 spacing, semantic colors, h1..h6 and body-1..body-3 text scales). Pairs with @batthewz/response-ui-css.

Downloads

297

Readme

@batthewz/response-ui-tw-merge

tailwind-merge pre-configured for the response-ui design system's custom utilities, plus an extensible cn() className helper. Tiny, zero-runtime-dependencies-beyond-peers.

What it knows about

  • Responsive spacing scale: r1..r6 (e.g. p-r3, gap-r4)
  • Semantic colors: canvas, primary, surface-0..3, fg-primary, status-error, etc.
  • Heading + body text scales: h1..h6, body-1..body-3

Without this configuration, tailwind-merge doesn't know that p-r3 and p-r5 conflict, or that text-fg-primary and text-fg-muted are alternatives — cn() would happily emit both and let the cascade decide.

Pairing with @batthewz/response-ui-css

This package is the JS-side companion to @batthewz/response-ui-css. It does not import the CSS package at runtime, but the token list it ships mirrors the tokens defined in response-ui-css. They are intentionally separate npm packages so that:

  • response-ui-css stays pure CSS — pure-CSS consumers (Vue, Svelte, vanilla, plain HTML) pay zero JS cost.
  • This package can be used independently by anyone who wants cn() with the same conventions in a non-React, non-CSS-consuming context.

Important: if you add a new token (color, spacing step, text scale) to response-ui-css, you must update the corresponding array in this package's src/index.js too, or tailwind-merge won't know about it. This is the trade-off for keeping the packages decoupled.

In practice you almost always want both installed together.

Install

npm install @batthewz/response-ui-tw-merge clsx tailwind-merge
# and the styles:
npm install @batthewz/response-ui-css

clsx and tailwind-merge are peer dependencies — bring your own to avoid duplicate copies in the bundle.

Usage

No custom tokens — just import cn

import { cn } from "@batthewz/response-ui-tw-merge";

function Button({ className, ...props }) {
  return (
    <button
      className={cn(
        "px-r4 py-r3 text-body-2 text-fg-on-primary bg-primary",
        "hover:bg-primary-hover",
        className,
      )}
      {...props}
    />
  );
}

cn() runs your inputs through clsx (conditional class merging) and then through a tailwind-merge instance that's been taught the design system's tokens, so the last-spec-wins rule works correctly for the custom utilities.

Your app adds custom tokens — use createCn

When your app extends the design system with its own colors, spacing, etc., create a project-local cn that knows about both the response-ui tokens and yours:

// app/cn.ts
import { createCn } from "@batthewz/response-ui-tw-merge";

export const cn = createCn({
  theme: {
    color: ["brand-primary", "brand-accent"],
    spacing: ["xtra-tight", "xtra-wide"],
  },
});

Then import cn from app/cn everywhere instead of from the package directly.

Why a factory rather than spread? The factory concatenates your arrays onto the built-ins. With the older spread pattern, customising one theme key (e.g. color) while forgetting to spread the others (spacing, text) silently wiped the built-in awareness for those. With createCn that footgun is impossible — every built-in stays known no matter which keys you customise.

You can also pass through tailwind-merge's other config keys (classGroups, conflictingClassGroups, cacheSize, etc.):

export const cn = createCn({
  theme: { color: ["brand-x"] },
  classGroups: {
    "custom-prose": ["prose-tight", "prose-loose"],
  },
  cacheSize: 1000,
});

Low-level escape hatches

For power users who want to drive extendTailwindMerge themselves:

import { mergeExtension, tailwindMergeExtension } from "@batthewz/response-ui-tw-merge";
import { extendTailwindMerge } from "tailwind-merge";

// `mergeExtension` does the safe concat for you:
const config = mergeExtension({
  theme: { color: ["brand-x"] },
});
const twMerge = extendTailwindMerge({ extend: config });

// Or use the raw built-in extension config (frozen, immutable):
const twMergeStrict = extendTailwindMerge({ extend: tailwindMergeExtension });

A pre-configured twMerge (design-system tokens only, no extension) is also exported if you want twMerge semantics without clsx on top:

import { twMerge } from "@batthewz/response-ui-tw-merge";
twMerge("p-r3 p-r5"); // → "p-r5"

Extending

Adding your own utilities and need cn() to merge them? See docs/extending.md for the createCn / mergeExtension workflow and how it pairs with generating the utility in your CSS layer.

License

MIT