Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

class-variance-authority

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

class-variance-authority - npm Package Compare versions

Comparing version 0.0.0 to 0.0.1

dist/index.cjs.js

33

package.json
{
"name": "class-variance-authority",
"version": "0.0.0",
"version": "0.0.1",
"description": "Class Variance Authority 🧬",

@@ -26,9 +26,10 @@ "author": "Joe Bell (https://joebell.co.uk)",

"files": [
"dist",
"README.md"
"dist/*.js",
"dist/*.js.map",
"dist/*.d.ts"
],
"scripts": {
"build": "npm-run-all build:*",
"build:cjs": "esbuild src/index.ts --format=cjs --outfile=dist/index.cjs.js",
"build:esm": "esbuild src/index.ts --format=esm --outfile=dist/index.esm.js",
"build:cjs": "npx swc ./src/index.ts --config-file ./.config/.swcrc -o dist/index.cjs.js -C module.type=commonjs",
"build:esm": "npx swc ./src/index.ts --config-file ./.config/.swcrc -o dist/index.esm.js -C module.type=es6 ",
"build:tsc": "tsc --project .config/tsconfig.json --emitDeclarationOnly",

@@ -38,20 +39,20 @@ "check:tsc": "tsc --project .config/tsconfig.json --noEmit",

"check": "run-p check:*",
"ci": "npm run check && npm run build && npm run test",
"test": "run-p test:*",
"test:jest": "jest --config .config/jest.config.ts --coverage",
"test:size": "run-p build:cjs build:esm && npx bundlesize -f 'dist/*.js' -s 910B",
"dev": "jest --config .config/jest.config.ts --watch"
"test:size": "run-p build:cjs build:esm && npx bundlesize -f 'dist/*.js' -s 800B",
"dev": "jest --config .config/jest.config.ts --watch",
"prepare": "husky install",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"@babel/preset-env": "7.16.5",
"@babel/preset-typescript": "7.16.5",
"@types/jest": "27.0.3",
"@swc/cli": "0.1.55",
"@swc/core": "1.2.136",
"@swc/jest": "0.2.17",
"@types/jest": "27.4.0",
"@types/react": "17.0.38",
"@types/react-dom": "17.0.11",
"bundlesize": "0.18.1",
"esbuild": "0.14.9",
"husky": "7.0.4",
"jest": "27.2.0",
"lint-staged": "12.1.4",
"np": "7.5.0",
"jest": "27.4.7",
"lint-staged": "12.3.2",
"npm-run-all": "4.1.5",

@@ -62,4 +63,4 @@ "prettier": "2.5.1",

"ts-node": "10.4.0",
"typescript": "4.5.4"
"typescript": "4.5.5"
}
}

@@ -0,19 +1,24 @@

![CVA](/.github/assets/meta.png)
<h1 align="center">cva</h1>
<p align="center">
<strong>C</strong>lass <a href="https://www.youtube.com/watch?v=9ZcyoZlY0aU"><strong>V</strong>ariance <strong>A</strong>uthority</a> 🧬
<strong>C</strong>lass <a href="https://www.youtube.com/watch?v=9ZcyoZlY0aU"><strong>V</strong>ariance <strong>A</strong>uthority</a>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/@joebell/cva">
<img alt="NPM Version" src="https://badgen.net/npm/v/@joebell/cva" />
<a href="https://www.npmjs.com/package/class-variance-authority">
<img alt="NPM Version" src="https://badgen.net/npm/v/class-variance-authority" />
</a>
<a href="https://www.npmjs.com/package/@joebell/cva">
<img alt="Types Included" src="https://badgen.net/npm/types/@joebell/cva" />
<a href="https://www.npmjs.com/package/class-variance-authority">
<img alt="Types Included" src="https://badgen.net/npm/types/class-variance-authority" />
</a>
<a href="https://bundlephobia.com/result?p=class-variance-authority">
<img alt="Minizipped Size" src="https://img.shields.io/bundlephobia/minzip/class-variance-authority" />
</a>
<a href="https://github.com/joe-bell/cva/blob/main/LICENSE">
<img alt="Apache-2.0 License" src="https://badgen.net/github/license/joe-bell/cva" />
</a>
<a href="https://www.npmjs.com/package/@joebell/cva">
<img alt="NPM Downloads" src="https://badgen.net/npm/dm/@joebell/cva" />
<a href="https://www.npmjs.com/package/class-variance-authority">
<img alt="NPM Downloads" src="https://badgen.net/npm/dm/class-variance-authority" />
</a>

@@ -29,41 +34,71 @@ <a href="https://twitter.com/joebell_">

Coming from BEM…
CSS-in-TS libraries such as [Stitches](https://stitches.dev/docs/variants) and [Vanilla Extract](https://vanilla-extract.style/documentation/) are **fantastic** options for building type-safe UI components; taking away all the worries of class names and StyleSheet composition.
```ts
import { cva } from "@joebell/cva";
…but CSS-in-TS (or CSS-in-JS) isn't for everyone.
const button = cva("button", {
variants: {
intent: {
primary: "button--primary",
secondary: "button--secondary",
warning: "button--warning",
danger: "button--danger",
},
size: {
small: "button--small",
medium: "button--medium",
large: "button--large",
},
},
compoundVariants: [
{ intent: "primary", size: "medium", class: "button--primary-small" },
],
defaultVariants: {
intent: "primary",
size: "medium",
},
});
You may need full control over your StyleSheet output. Your job might require you to use a framework such as Tailwind CSS. You might just prefer writing your own CSS.
button();
// => "button button--primary button--medium"
Creating variants with the "traditional" CSS approach can become an arduous task; manually matching classes to props and manually adding types.
button({ intent: "secondary", size: "small" });
// => "button button--secondary button--small"
CVA aims to take those pain points away, allowing you to focus on the more fun aspects of UI development.
## Acknowledgements
- [**Stitches**](https://stitches.dev/) ([Modulz](http://modulz.app))
Huge thanks to the Modulz team for pioneering the `variants` API movement – your open-source contributions are immensely appreciated
- [**clb**](https://github.com/crswll/clb) ([Bill Criswell](https://github.com/crswll))
This project originally started out with the intention of merging into the wonderful [`clb`](https://github.com/crswll/clb) library, but after some discussion with Bill, we felt it was best to go down the route of a separate project.
I'm so grateful to Bill for sharing his work publicly and for getting me excited about building a type-safe variants API for classes. If you have a moment, please go and [star the project on GitHub](https://github.com/crswll/clb). Thank you Bill!
## Installation
```sh
npm i class-variance-authority
```
Tailwind
<details>
<summary>"Do I really have to write such a long package name for every import?"</summary>
Unfortunately, yes. Originally, the plan was the publish the package as `cva`, but this name [has been taken and marked as a "placeholder"](https://www.npmjs.com/package/cva). I've reached out to the author and NPM support, but have yet to hear back.
In the meantime, you can always alias the package for your convenience…
### Aliasing in TypeScript
1. Add the alias to your [`tsconfig.json`](https://www.typescriptlang.org/tsconfig#paths) `paths`:
```json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"cva": ["node_modules/class-variance-authority"]
}
}
}
```
2. Then import like so:
```ts
import { cva } from "cva";
// …
```
</details>
## Getting Started
> **Disclaimer**: Although `cva` is a [**tiny**](https://bundlephobia.com/package/class-variance-authority) library, it's best to use in a SSR/SSG environment – your user probably doesn't need this JavaScript, especially for static components.
### Your First Component
To kick things off, let's build a "basic" `button` component, using `cva` to handle our variant's classes
> **Note:** Use of Tailwind CSS is optional
```ts
import { cva } from "@joebell/cva";
import { cva } from "class-variance-authority";

@@ -87,14 +122,2 @@ const button = cva(["font-semibold", "border", "rounded"], {

],
warning: [
"bg-yellow-500",
"text-black",
"border-transparent",
"hover:bg-yellow-600",
],
danger: [
"bg-red-500",
"text-white",
"border-transparent",
"hover:bg-red-600",
],
},

@@ -104,3 +127,2 @@ size: {

medium: ["text-base", "py-2", "px-4"],
large: ["text-lg", "py-2.5", "px-4"],
},

@@ -122,18 +144,18 @@ },

### Problem?
### TypeScript Helpers
### Prior Art
`cva` offers the `VariantProps` helper to extract variant types
- clb
- Stitches
- Vanilla Extract
```ts
// styles/components.ts
import type * as CVA from "class-variance-authority";
import { cva, cx } from "class-variance-authority";
## Installation
```sh
npm i @joebell/cva
/**
* YourComponent
*/
export type YourComponentProps = CVA.VariantProps<typeof yourComponent>;
export const yourComponent = cva(/* ... */);
```
## Getting Started
### Composing Classes

@@ -147,4 +169,4 @@

// styles/components.ts
import type * as CVA from "cva";
import { cva, cx } from "@joebell/cva";
import type * as CVA from "class-variance-authority";
import { cva, cx } from "class-variance-authority";

@@ -187,7 +209,6 @@ /**

- `cva` – build a class variance authority
- `cx` – concatenate class names
### `cva`
Builds a class variance authority
```ts

@@ -197,12 +218,18 @@ const component = cva("base", options);

#### Parameters
1. `base` – the base class name
1. `base`: the base class name (`string`, `string[]` or `null`)
1. `options` _(optional)_
1. `variants`
1. `compoundVariants`
1. `defaultVariants`
- `variants`: your variants schema
- `compoundVariants`: variants based on a combination of previously defined variants
- `defaultVariants`: set default values for previously defined variants
### `cx`
Concatenates class names
```ts
const className = cx(classes);
```
- `classes`: array of classes to be concatenated
## Examples

@@ -213,25 +240,25 @@

<details>
<summary>React (with CSS Modules)</summary>
<summary>BEM</summary>
```css
/* button.css */
.base {
/* styles.css */
.button {
/* */
}
.primary {
.button--primary {
/* */
}
.secondary {
.button--secondary {
/* */
}
.small {
.button--small {
/* */
}
.medium {
.button--medium {
/* */
}
.primaryMedium {
.button--primary-small {
/* */

@@ -241,31 +268,18 @@ }

```tsx
// button.tsx
import React from "react";
import { cva } from "@joebell/cva";
import * as CVA from "@joebell/cva";
```ts
import { cva } from "class-variance-authority";
import {
base,
primary,
secondary,
small,
medium,
primaryMedium,
} from "./button.css";
// ⚠️ Disclaimer: Use of Tailwind CSS is optional
const button = cva(base, {
const button = cva("button", {
variants: {
intent: {
primary,
secondary,
primary: "button--primary",
secondary: "button--secondary",
},
size: {
small,
medium,
small: "button--small",
medium: "button--medium",
},
},
compoundVariants: [
{ intent: "primary", size: "medium", class: primaryMedium },
{ intent: "primary", size: "medium", class: "button--primary-small" },
],

@@ -278,7 +292,7 @@ defaultVariants: {

export type ButtonProps = CVA.VariantProps<typeof button>;
button();
// => "button button--primary button--medium"
export const Button: React.FC<ButtonProps> = ({ intent, size, ...props }) => (
<button className={button({ intent, size })} {...props} />
);
button({ intent: "secondary", size: "small" });
// => "button button--secondary button--small"
```

@@ -289,9 +303,7 @@

<details>
<summary>React (with Tailwind)</summary>
<summary>11ty (with Tailwind)</summary>
```tsx
// button.tsx
import React from "react";
import { cva } from "@joebell/cva";
import * as CVA from "@joebell/cva";
```js
// button.11ty.js
const { cva } = require("class-variance-authority");

@@ -327,2 +339,73 @@ // ⚠️ Disclaimer: Use of Tailwind CSS is optional

module.exports = function ({ label, intent, size }) {
return `<button class="${button({ intent, size })}">${label}</button>`;
};
```
</details>
<details>
<summary>React (with CSS Modules)</summary>
```css
/* button.css */
.base {
/* */
}
.primary {
/* */
}
.secondary {
/* */
}
.small {
/* */
}
.medium {
/* */
}
.primaryMedium {
/* */
}
```
```tsx
// button.tsx
import React from "react";
import { cva } from "class-variance-authority";
import * as CVA from "class-variance-authority";
import {
base,
primary,
secondary,
small,
medium,
primaryMedium,
} from "./button.css";
// ⚠️ Disclaimer: Use of Tailwind CSS is optional
const button = cva(base, {
variants: {
intent: {
primary,
secondary,
},
size: {
small,
medium,
},
},
compoundVariants: [
{ intent: "primary", size: "medium", class: primaryMedium },
],
defaultVariants: {
intent: "primary",
size: "medium",
},
});
export type ButtonProps = CVA.VariantProps<typeof button>;

@@ -338,7 +421,9 @@

<details>
<summary>11ty (with Tailwind)</summary>
<summary>React (with Tailwind)</summary>
```js
// button.11ty.js
const { cva } = require("@joebell/cva");
```tsx
// button.tsx
import React from "react";
import { cva } from "class-variance-authority";
import * as CVA from "class-variance-authority";

@@ -374,5 +459,7 @@ // ⚠️ Disclaimer: Use of Tailwind CSS is optional

module.exports = function ({ label, intent, size }) {
return `<button class="${button({ intent, size })}">${label}</button>`;
};
export type ButtonProps = CVA.VariantProps<typeof button>;
export const Button: React.FC<ButtonProps> = ({ intent, size, ...props }) => (
<button className={button({ intent, size })} {...props} />
);
```

@@ -388,4 +475,4 @@

<script lang="ts">
import { cva } from "@joebell/cva";
import type * as CVA from "@joebell/cva";
import { cva } from "class-variance-authority";
import type * as CVA from "class-variance-authority";

@@ -443,4 +530,4 @@ const button = cva("button", {

import { cva } from "@joebell/cva";
import type * as CVA from "@joebell/cva";
import { cva } from "class-variance-authority";
import type * as CVA from "class-variance-authority";

@@ -509,1 +596,30 @@ const button = cva("button", {

</details>
### Other Use Cases
Although primarily designed for handling class names, at its core, `cva` is really just a fancy way of managing a string…
<details>
<summary>Dynamic Text Content</summary>
```ts
const greeter = cva("Good morning!", {
variants: {
isLoggedIn: {
true: "Here's a secret only logged in users can see",
false: "Log in to find out more…",
},
},
defaultVariants: {
isLoggedIn: "false",
},
});
greeter();
// => "Good morning! Log in to find out more…"
greeter({ isLoggedIn: "true" });
// => "Good morning! Here's a secret only logged in users can see"
```
</details>
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc