Foundation
PackagesUIArchitecture

Primitives

スタイルの定義と管理を担う最小構成単位。

責務

Primitivesは 「どう見えるか」(what)を定義する 最小構成単位である。

  • HTMLネイティブ要素にデザイントークンベースのスタイルを適用する
  • CVAでvariant(見た目のバリエーション)を定義・管理する
  • CSS擬似クラス(:hover, :focus-visible, :disabled 等)による見た目の変化を定義する
  • Radix UI Slotによる asChild パターンで、レンダリングする要素の差し替えを可能にする
  • className を受け取り、利用者側でのスタイル拡張を許容する

Primitivesが決めること

対象
色・背景色variant="destructive" のときの bg-destructive
サイズsize="sm" のときの h-8 px-3 text-sm
インタラクション時の見た目hover時の色変化、focus時のリング、disabled時の透明度
角丸・シャドウrounded-lg, shadow-md
内部レイアウトinline-flex items-center gap-2

Primitivesが決めないこと

対象決める層
いつ disabled にするかElements
いつ variant="destructive" を使うかElements
どのPrimitivesを組み合わせるかElements
外部レイアウト(margin、配置)利用者(Elements / アプリケーション)

責務外

Primitivesが行ってはならないことを定義する。

  • ビジネスロジックや状態管理を持たない — ローディング状態の制御やバリデーションはElementsの責務である
  • 他のPrimitivesを内部で組み合わせない — Primitivesは単一のHTML要素(またはRadixプリミティブ)に対応する
  • 'use client'を宣言しない — Primitives自体はサーバーコンポーネントとして使用可能な状態を保つ
  • 用途を限定する命名をしないSubmitButton ではなく Button のように、汎用的な名前にする
  • 外部にエクスポートしない — アプリケーションコードから直接使用させない

状態の視覚定義

すべてのインタラクティブなPrimitivesは、以下の状態に対する見た目を定義しなければならない。状態の見た目はCSS擬似クラスまたはCVAで実装し、Elementsに判断を委ねない。

状態実装方法視覚表現の例
defaultCVAベーススタイル通常の見た目
hoverhover:背景色を一段濃くする
active / pressedactive:さらに濃くする、またはわずかに縮小する
focusfocus-visible:フォーカスリング(ring-ring)を表示する
disableddisabled: / aria-disabled:透明度を下げる(opacity-50)+ pointer-events-none
erroraria-invalid:ボーダーを border-destructive に変更する

loading 状態の見た目(Spinner表示等)はElementsの責務である。Primitivesは disabled の見た目だけを定義し、Elementsが isLoading 時に disabled を渡すことでローディング中の見た目を実現する。

// Primitiveのベーススタイル例(Button)
const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-lg transition-colors ' +
    'focus-visible:ring-3 focus-visible:ring-ring ' +
    'disabled:pointer-events-none disabled:opacity-50 ' +
    'aria-invalid:border-destructive aria-invalid:ring-destructive/20',
  {
    variants: {
      variant: {
        default:
          'bg-primary text-primary-foreground ' +
          'hover:bg-primary-hover active:bg-primary-active',
        // ...
      },
    },
  },
);

要件

要件詳細
CVA variant定義見た目のバリエーションはすべてCVAで管理する
状態の視覚定義インタラクティブ要素は default / hover / active / focus / disabled / error の見た目を定義する
asChild対応Radix UI Slotを使用し、要素の差し替えを可能にする
data属性の付与data-slot, data-variant, data-size を付与する
Props拡張React.ComponentProps<"element"> を拡張する
className合成cn() で内部クラスと外部classNameをマージする
フォーカス管理focus-visible でフォーカスリングを表示する
外部余白の禁止margin を持たない。内部余白(padding, gap)のみ定義する

On this page