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

vite-plugin-useclassy

v4.0.0

Published

UseClassy automatically appends class attributes to your components and lets you separate media queries, hover states, and other styles.

Readme

🎩 UseClassy

A Vite plugin that automatically rewrites conditional class attributes like class:hover or class:focus into standard utility classes usable by Tailwind CSS and UnoCSS. UseClassy lets you write cleaner, more maintainable variant styles in your HTML, Vue, React, Blade, and Svelte code, with no runtime overhead.

<button
  class="@container rounded px-4 bg-blue-600 text-white"
  class:hover="bg-blue-700"
  class:focus="ring-2 ring-blue-300"
  class:@md="px-6"
></button>

becomes class="@container rounded px-4 bg-blue-600 text-white hover:bg-blue-700 focus:ring-2 focus:ring-blue-300 @md:px-6". There is no runtime. Put UseClassy before Tailwind or UnoCSS so those engines see the rewritten utilities.

Install

npm i -D vite-plugin-useclassy
npx vite-plugin-useclassy init

init patches Vite and your CSS engine, plus VS Code IntelliSense for Tailwind. Run it from the app root (the folder with package.json and vite.config.*).

| Option | Default | Notes | | ---------------- | ------------ | ---------------------------------------------------------------------------------- | | --language | 'vue' | 'vue' | 'react' | 'blade' | 'svelte' | | --engine | auto-detect | 'tailwind' | 'unocss'; Tailwind wins if both are installed | | --with-skills | false | Agent skill, Cursor rules, and AGENTS.md | | --with-claude | false | Also copy to .claude/skills/ (requires --with-skills) | | --force | false | Overwrite locally edited skill files | | --dry-run | false | Print planned edits |

If detection fails, follow the manual setup below.

Usage

Vue / HTML. Use class plus class:modifier:

<button
  class="px-4 py-2 rounded bg-blue-600 text-white"
  class:hover="bg-blue-700 scale-105"
  class:focus="ring-2 ring-blue-300"
  class:disabled="opacity-50 cursor-not-allowed"
  class:dark="bg-sky-700"
/>

React. Use className and className:hover. JSX expressions work when the class tokens are string literals:

<button
  className="px-4 py-2 rounded"
  className:hover={isActive ? 'bg-blue-500 text-white' : 'bg-gray-200'}
/>

Expressions with no string literals (className:hover={hoverClasses}) are left alone. Import types with import 'vite-plugin-useclassy/react' (or ClassyProps). React 18/19 is an optional peer, only needed for those helpers.

Svelte. Quoted modifiers transform; native directives do not. Put UseClassy before @sveltejs/vite-plugin-svelte.

<button class="px-4 py-2 rounded" class:hover="bg-blue-700" class:active={isActive}>

Laravel Blade. composer require useclassy/laravel, then language: "blade". PHP ^8.2, Laravel ^11–13. Blade files sit outside Vite’s module graph, so keep the class manifest registered with Tailwind or UnoCSS (below).

Chained modifiers

class:sm:hover="underline" emits sm:hover:underline only, the same composition as Tailwind / UnoCSS, not the individual sm: and hover: pieces.

Modifier names may include letters, digits, _, -, :, / (group-hover/item), and @ (@md). Arbitrary variants ([&>*], data-[state=open]) cannot be attribute names, so leave those on the base class. In React JSX, / is invalid in an attribute name, so named groups stay on className.

Vite

import useClassy from 'vite-plugin-useclassy'

export default {
  plugins: [
    useClassy({
      language: 'vue', // 'react' | 'blade' | 'svelte'
      // engine: "unocss",
    }),
    // Tailwind / UnoCSS after UseClassy
  ],
}

| Option | Default | Notes | | ------------------------------ | -------------------------------- | ---------------------------------------------------------------- | | language | 'vue' | 'vue' | 'react' | 'blade' | 'svelte' | | engine | 'tailwind' | 'unocss' skips Tailwind @source inject | | outputDir / outputFileName | .classy / output.classy.html | Class manifest Tailwind and Uno scan | | manifestRoot | Vite root | Set when Vite’s root is a subfolder (e.g. Nuxt srcDir: "app/") | | injectTailwindSource | true | Tailwind v4 only; ignored for UnoCSS | | debug | false | Log transform and manifest writes |

Processes .vue, .svelte, .ts, .tsx, .js, .jsx, .html, and .blade.php. Skips node_modules, gitignored paths, and virtual modules.

Tailwind

UseClassy writes discovered utilities to .classy/output.classy.html (gitignored). Tailwind v4 does not scan gitignored files unless you @source them. The plugin injects that directive into stylesheets that @import "tailwindcss". init also writes it into your CSS.

@import 'tailwindcss';
@source "./.classy/output.classy.html";

@source paths are relative to the CSS file. If the stylesheet lives in src/, use ../.classy/output.classy.html.

Tailwind v3. Add the manifest to content:

content: ["./.classy/output.classy.html"],

Path helpers: getUseClassyTailwindSourceDirective, getUseClassyTailwindV3ContentEntry from vite-plugin-useclassy or vite-plugin-useclassy/tailwind. Pass the same outputDir / outputFileName you use in the plugin.

UnoCSS

useClassy({ language: 'react', engine: 'unocss' })

Place it before unocss/vite. After the rewrite, Uno’s Vite pipeline already sees hover: classes. Register the HTML manifest as a filesystem source for files Uno does not extract (plain .ts / .js, Blade, HTML that never enter Vite):

import { defineConfig, presetUno } from 'unocss'
import { getUseClassyUnoFilesystemEntry } from 'vite-plugin-useclassy/unocss'

export default defineConfig({
  presets: [presetUno()],
  content: { filesystem: [getUseClassyUnoFilesystemEntry()] },
})

UseClassy is variant-first (class:hover="bg-red"), not Attributify (bg="hover:..."). Don’t enable both on the same attributes. See demos/unocss-react.

IntelliSense

init merges this into .vscode/settings.json for Tailwind projects:

{
  "tailwindCSS.classAttributes": ["class", "class:[\\w:/@-]*", "className", "className:[\\w:/@-]*"]
}

Vue-only projects can omit the className entries. UnoCSS projects should use the UnoCSS VS Code extension instead.

Agent skill

npx vite-plugin-useclassy init --with-skills

| Path | Used by | | ------------------------------- | ---------------------------------- | | .agents/skills/useclassy/ | Cursor, Codex, Copilot | | .cursor/rules/useclassy-*.mdc | Cursor | | AGENTS.md (fenced block) | Windsurf, Aider, Cline, and others |

Add --with-claude to also copy into .claude/skills/ (opt-in so Cursor doesn’t load the skill twice). Running it again is safe; --force overwrites local edits. Templates live in templates/.

Contributing

Issues and PRs welcome.

License

MIT