## 概要 [[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] > ここから