## 概要
[[Class Variance Authority]] のドキュメントの要点を原点を提示したうえでまとめる。
| 対象 | バージョン |
| ---------------------------- | ----- |
| [[Class Variance Authority]] | 0.7.1 |
| [[TypeScript]] | 6.0.3 |
## Introduction
https://cva.style/docs
- [[CSS-in-JS]]では[[バリアント]]を使ってUIを型安全に可読性高く定義できる
- しかし、[[CSS-in-JS]]はすべての人に向いているわけではない
- [[Tailwind CSS]]を使っているなど
- [[cva]]は[[CSS-in-JS]]以外でも使えるようにしたもの
## Installation
https://cva.style/docs/getting-started/installation
```console
toki pnpm cva-sandbox
cd cva-sandbox
pnpm i class-variance-authority
```
`package.json`
```json
{
"name": "cva-sandbox",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "tsx watch ./index.ts",
"check": "tsc --noEmit --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": "^11.5.2",
"onFail": "download"
}
},
"type": "module",
"devDependencies": {
"@biomejs/biome": "2.5.0",
"@tsconfig/recommended": "1.0.13",
"@types/node": "25.9.3",
"tsx": "4.22.4",
"typescript": "6.0.3"
},
"dependencies": {
"class-variance-authority": "0.7.1"
}
}
```
### [[Tailwind CSS]]ユーザー向け
[[Tailwind CSS]]ユーザーなら以下を設定。
[[VSCode]]向け
```json
{
"tailwindCSS.classFunctions": ["cva", "cx"]
}
```
[[Neovim]]向け
```json
require 'lspconfig'.tailwindcss.setup({
settings = {
tailwindCSS = {
classFunctions = { "cva", "cx" },
},
},
})
```
## Variants
https://cva.style/docs/getting-started/variants
- [[cva]]
- 第1引数は共通クラス
- 第2引数はkey-value
- variants
- variantの選択肢と、それぞれで付与されるクラス名
- [[Compound Variants]]
- `variants` 内のプロパティの組み合わせが成立したときに付与されるクラス名
- defaultVariants
- `variants` 内のプロパティを省略したときのデフォルト値
## TypeScript
https://cva.style/docs/getting-started/typescript
- [[VariantProps型]] で `VariantProps<typeof button>` とすると型定義できる
- ただし、すべてのプロパティは `p?: T | null | undefined` のようになってしまう
- [[Omit型 (TypeScript)|Omit型]]と[[Required型 (TypeScript)|Required型]]を継承して付け替える
```ts
export interface ButtonProps
extends
Omit<ButtonVariantProps, "required">,
Required<Pick<ButtonVariantProps, "required">> {}
```
> [!thinking]
> 毎回 `extends` するのは面倒なので、以下のように型定義した方が使いやすいと思う。
>
> ```ts
> type RequireNonNullable<T, K extends keyof T> = Omit<T, K> & {
> [P in K]-?: Exclude<T[P], null | undefined>;
> };
> ```
>
> ついでに `null` と `undefined` も除外。意図せず `null` や `undefined` が入るのはリスクなので。
## Extending Components
> [!fixme]
> ここから