Skip to content

Evaluation v0.4 and Roadmap

Yu Ohno edited this page May 11, 2026 · 1 revision

Schatten Design System 評価レポート

対象: @yasmro/schatten v0.4.0 作成日: 2026-05-11 スコープ: デザインシステムとしての完成度 / 堅牢性 / AI 親和性 / ガバナンス


エグゼクティブサマリ

Schatten は トークン体系の洗練と日本の伝統色彩世界観 を中核価値とする独創的な DS。プリミティブ層 (lv1) は十分に揃い、CI/VRT も成熟している。一方で 合成層 (lv2) / ドキュメント / AI 親和性 / ガバナンス強制 が次の山であり、これらが整うまで「1.0」を名乗るには早い。

総合スコア

観点 評価 一言
トークン体系 ⭐⭐⭐⭐⭐ 3層構造 + OKLCH + 4-token state shape は業界水準を超える
ブランドアイデンティティ ⭐⭐⭐⭐⭐ 墨・和紙・朱・24節気 — 唯一無二の世界観
コンポーネント網羅性 ⭐⭐⭐ 18個。プリミティブ層は十分、ナビ系・データ表示系が空白
合成層 (lv2) ⭐ 空 stub。「いつ作るか」の規範がない
テーマ拡張性 ⭐⭐⭐ 季節テーマは独創的だが影響面が --color-primary-* だけで狭い。「特別テーマ」概念が未整理で将来追加に脆い (§2.4)
a11y ⭐⭐⭐ Radix + Field context は良い。自動検証はゼロ
ドキュメント ⭐⭐⭐ Color / Typography / Welcome のみ。基礎ページが不足
採用導線 ⭐⭐⭐⭐ マルチエントリ export で部分採用しやすい
ガバナンス ⭐⭐ changeset 未強制、ADR なし、貢献ガイド薄い
配布・バージョニング ⭐⭐⭐ 0.4.0 のまま、1.0 への基準が未提示
アーキテクチャ ⭐⭐⭐⭐ レイヤー依存はクリーン、ただし合成パターンと外部依存の境界が曖昧
パフォーマンス ⭐⭐ lucide-react が external 未指定で bundle 肥大化リスク、sideEffects 未指定
SSR 互換性 ⭐ 'use client' ゼロ件 → Next.js App Router で破綻
TestID 規約 ⭐⭐ ...props で通るが規約未文書化、Portal 配下の経路も未定義
Theme 切替 API ⭐⭐ ThemeProvider / useTheme 未提供、利用者が毎回自作
AI 親和性 ⭐⭐⭐ 型 export と CLAUDE.md は良いが、トークン autocomplete 不可、variant 語彙不統一
コード堅牢性 ⭐⭐⭐⭐ strict TS / Biome / VRT 整備済。changeset 未強制と test 抜けが課題

トップ強み 3点

  1. 三層トークン構造 + OKLCH — destructive と error を意味分離しつつ primitive 共有する設計は Material 3 や Polaris にもない洗練 (src/core/tokens/semantic.css)
  2. 24節気ベース seasonal theme — OSS DS で類例がない強烈な差別化要素 (src/themes/seasonal/index.ts)
  3. VRT 運用の成熟 — 失敗時 artifact + PR コメント自動生成、成功で削除 (.github/workflows/vrt.yml)

トップギャップ 6点

  1. Framework-agnostic 路線が実体化していない (phantom class) — .btn は CSS 定義なし、現状の framework-agnostic は token レベルのみで成立。Option A (1.0 DoD として保証) を満たすには 18 コンポーネント分の @layer components 書き起こしが必要 (§2.8.1)
  2. 'use client' ディレクティブがゼロ件 — Next.js App Router でビルド失敗する。Schatten が SSR フレンドリーだと誤解されるリスク
  3. lucide-react が external 未指定 — import { icons } from 'lucide-react' で全 1500+ アイコンが dist にバンドルされる可能性、サイズ計測も未実施
  4. lv2 が空 stub — DS としての「合成の正解」が存在しない (src/components/lv2/index.ts)
  5. トークンが TS 型を持たない — AI も人間も autocomplete 不能、bg-red-500 の混入を構造的に防げない
  6. 8 コンポーネントが unit test なし / 3 が VRT spec なし — テスト網羅率が読めない

1. デザインシステムとしての評価

1.1 トークン体系 ⭐⭐⭐⭐⭐

強み:

  • 三層(primitive → semantic → component)の責務分離が徹底
  • OKLCH 採用 — sRGB の hex を引きずる多くの DS より将来性がある
  • destructive と error の意味分離(同じ vermillion を共有しつつ semantic としては別レイヤー)
  • inverted-foreground の muted/subtle 階層化 (src/core/tokens/semantic.css:54) — 飽和背景上のテキスト階層まで考えられている
  • 4-token state shape(base / hover / foreground / subtle)が error, success, warning, info で統一

課題:

  • typography が composite tokens を分解して提供している(--text-body-md-size / -leading / -weight の3変数)。consumer が3つ手で当てる必要があり摩擦がある
  • shadow / radius / motion トークンが semantic 化されていない。--shadow-card, --radius-control, --motion-instant のような意味層がない → ブランド変更時にコンポーネント側を書き換える必要が出る
  • z-index 用途別 semantic がない (src/core/tokens/z-index.css) — --z-tooltip, --z-modal, --z-toast 等の意味付けがあると統治しやすい

1.2 ブランドアイデンティティと季節テーマ ⭐⭐⭐⭐⭐

sumi / alabaster / paper-white/warm/cream / vermillion / ink-black — 命名から世界観が立ち上がる。shadcn の neutral-* には絶対に出せない武器。

24節気ベースの seasonal theme は OSS DS では類例がない。

ただし生かしきれていない:

  • 季節で動くのは --color-primary-* だけ。background / accent / border は固定 → 「primary ボタンの色だけ変わる」程度の visual payoff
  • Storybook での見せ方が Color.stories.tsx のみ。コンポーネント実例での効果が見えない

提案: --color-accent-*、--color-surface-*、--shadow-card まで [data-season] で変動させる + Foundations / Seasonal Showcase ストーリーで8季節 × Button / Badge / Callout を並べる。

1.3 コンポーネント網羅性 ⭐⭐⭐

18個。プリミティブ層は十分だが、実プロダクト構築で詰まる箇所が見える:

カテゴリ 現状 不足している典型
Form Input, Textarea, Select, Radio, Checkbox, Switch, Field, FieldSet Combobox / Autocomplete, DatePicker, Slider, FileUpload, Form (送信統括)
Disclosure Dialog, Tooltip Popover, Drawer, Accordion, Collapsible, HoverCard
Navigation – Tabs, Breadcrumb, NavigationMenu, Pagination, Menu/DropdownMenu
Data display Badge, Callout, Text, Separator Table, Card, Avatar, List, EmptyState
Feedback Toast, Spinner Skeleton, ProgressBar, Alert (vs Callout の使い分け要定義)
Layout – Stack / HStack / VStack / Cluster — 不採用確定 (オーナー判断)。Tailwind 直書き + spacing-conventions.md で AI 制約 + Patterns / Layout ストーリーで運用
Icon IconName = keyof typeof icons で lucide 直依存 <Icon> 共通コンポーネント — sizing / aria / lucide 差し替え抽象化なし

特に痛い不在: Menu / Tabs / Card / Icon ラッパー。

1.4 合成層 (lv2) の不在 ⭐

src/components/lv2/index.ts は export {} のまま。これが構造的な弱点:

  • 「Input + Label + Description + Error message」のような頻出セットがない → 利用者は毎回 Field + Input + label を組み合わせる
  • 「Confirmation Dialog」「Form」のような典型パターンが lv1 から都度組まれ、プロダクト間の差異が増える
  • 判定基準が文書化されていない — 何を lv2 にし、何を利用者プロダクトに残すか

提案: lv2/FormField, lv2/ConfirmDialog, lv2/PageHeader, lv2/EmptyState から始める。

1.5 ドキュメント ⭐⭐⭐

src/docs/ は Color, Typography, Welcome のみ。必要なページが欠けている:

不足:

  • Foundations / Spacing — 4px base scale の使い分け
  • Foundations / Elevation — shadow トークンの使い分け
  • Foundations / Motion — --transition-fast/normal/slow の意図
  • Foundations / Iconography — lucide 採用、サイズ規則、a11y
  • Foundations / Accessibility — フォーカス可視性、aria-*、コントラスト保証ライン
  • Patterns / Form Composition — Field / FieldSet のレシピ集
  • Patterns / Composition with asChild — Radix Slot パターンの方針
  • Getting Started / For Astro consumers — variants エントリの意義
  • Getting Started / Migration — 0.x 間の破壊的変更ガイド
  • Contributing — コンポーネント追加プロセス、命名規約

1.6 戦略的ポジショニング

確定している方針(オーナー確認済)

Schatten は二層 DS である:

  • Layer A: Framework-agnostic CSS / Class DS — 素の HTML / Astro / Vue / Svelte で <button class="btn btn-primary"> の形で使える
  • Layer B: React component DS — Layer A の上に乗る React ラッパー (<Button variant="primary">)

これは shadcn 系 React DS との明確な差別化軸。「React に lock-in しない DS」というメッセージで打ち出せる強みであり、README の冒頭で第一に伝えるべき価値。

1.0 リリースは「両層が動く」状態で出す (Option A 確定)。現状の framework-agnostic は token レベルのみで、コンポーネントは React + Tailwind パイプライン依存 (§2.8.1 参照)。1.0 でこの実装ギャップを埋めることが Schatten の差別化を実体化する条件。

残された決定事項

  1. shadcn ベースなのに npm パッケージ配布という選択

    • shadcn の根本価値は「コピペして自由に改変できる」こと。npm 配布にした瞬間その価値は消える
    • しかし**「framework-agnostic な CSS クラス DS」という独自軸**を持つことで、単なる shadcn の劣化コピーではなく独立した価値命題を持つ
    • README で「Schatten is inspired by shadcn/ui but ships as a framework-agnostic CSS + optional React layer」と明示
  2. 0.4.0 のまま — 1.0 リリースの基準が未提示

    • 提案: 1.0 の DoD を明示する (詳細は §7 ロードマップ)
    • Framework-agnostic 路線が確定したため、CSS クラス名と CSS 変数名も「公開 API」として 1.0 で固定対象になる
  3. 対象オーディエンス

    • npm publish & GitHub Pages で Storybook 公開 → public 想定
    • public なら ADR と「なぜ existing DS を選ばないか」のステートメントが欲しい

2. アーキテクチャ評価

「堅牢性」が 個々の実装が壊れないか の評価なら、アーキテクチャは 構造が長期的に機能するか の評価。重複する論点もあるが、視点は別。

2.1 レイヤー構造と依存方向

                                            [Framework: React]
                                                    │
  primitives.css  ──→  semantic.css  ──→  variants/*.ts  ──→  components/lv1
       (raw)            (meaning)         (CVA, no React)         (React)
                            ↑                                          ↑
                            │                                          │
                       themes/*  (override semantic)               contexts/* (perpendicular)

良い点:

  • 単方向依存が守られている — primitive → semantic → variants → components の流れに逆流がない
  • src/variants/ が React に依存しない — CVA 自体は framework-agnostic なので、Astro / Vue / Svelte への展開可能性を残した設計 (tsup.config.ts:18 で React 抜きエントリを切っているのと整合)
  • themes は semantic を上書きするだけ — components 側を変えずにブランド変更可能

懸念:

  • contexts (FieldContext, FieldSetContext) はレイヤーに垂直に存在する。どの lv1 から消費して OK か / lv2 が context を消費するときの規範が暗黙
  • lib/utils.ts (cn) と lib/merge-refs.ts は共有ユーティリティだが、将来 lv2 が増えたとき lv2 が lv1 から import するのか直接 lib から import するのか未規定

2.2 公開 API 設計

package.json の exports は意図的にマルチエントリ:

Entry 内容 評価
. style: ./dist/schatten.css のみ ⚠️ JS / types エントリが未定義 — 意図的ではなく、追加すべき欠落 (オーナー確認済)。import { Button } from '@yasmro/schatten' が動くようにすべき
./schatten.css バンドル済み CSS ◎
./core/tokens tokens CSS ◎ 部分採用の窓口
./themes/default デフォルトテーマ CSS ◎
./themes/seasonal TS (getCurrentSeason 等) ◎ JS 実装が伴う唯一のテーマ
./variants TS (CVA, React 抜き) △ README に説明なし — 戦略的な隠し玉が利用者に伝わっていない
./components/lv1 TS ◎ 現状の主要 import 点
./components/lv2 TS (export {}) ⚠️ 空のまま export している — import しても何も得られない

評価: マルチエントリは DS としての強み (段階的採用が可能)。ただし . の JS/types 未提供と空の lv2 で「API として未確定なものが混じっている」印象を与える。両方とも Phase 1 で解消する。

2.3 合成パターンの不統一

コンポーネント 形 asChild 備考
Button flat ✅ shadcn 標準
Input flat (内部に wrapper) ?
Select compound (11 exports) (Radix)
Dialog compound (Radix)
Tooltip compound (Provider + Trigger + Content) (Radix)
Radio hybrid (Radio + RadioGroup) ?
Field / FieldSet context-only n/a

問題: 「いつ compound にするか」「いつ asChild を提供するか」の規範がない。新規追加するときに過去から類推するしかなく、AI も人間も毎回判断にコストがかかる。

提案: .claude/rules/component-architecture.md で明文化:

  • Radix primitive をラップする場合は compound を踏襲
  • 自前実装の場合は基本 flat。合成パターンが必要なら lv2 で
  • asChild は「他要素として renderable な必要があるもの」(Button / Link 系) のみ

2.4 テーマ機構の重複と「特別テーマ」の未整理(要設計)

並行する 2 つのテーマ機構:

  1. Mode theme: prefers-color-scheme + .dark class (light/dark)
  2. Special theme: [data-season="..."] 属性 (seasonal の 8 種)

現状の課題(オーナー確認済の未解決事項): seasonal は「特別テーマ」の最初の例だが、特別テーマというカテゴリが概念として確立していない。将来、季節以外の特別テーマ(イベントテーマ / コラボテーマ / 色弱モード / 高コントラストモード)が追加される可能性が高く、その時に都度ルールを後付けすると破綻する。

整理が必要な論点:

論点 例
特別テーマが上書きしてよい token の範囲 seasonal は --color-primary-* のみ? それとも --color-accent-*, --shadow-card も?
特別テーマ同士の併存可否 spring-early と christmas-2026 を同時適用したらどうなる?
Mode theme との優先順位 dark + spring-early のとき --color-primary-* は seasonal が勝つべきか dark が勝つべきか
高コントラストモードの位置づけ a11y 要件としてのモード? それとも特別テーマ?
利用者が独自テーマを足せるか yasmro 内製専用? OSS 公開時に第三者がテーマを追加可能?

提案する整理モデル:

Theme Axis 1: Mode      (排他)  → light | dark | high-contrast
Theme Axis 2: Special   (累積)  → seasonal-{x} / event-{y} / custom-{z}
                                  各 special は token allowlist を持つ

Cascade rule:
  Special (最後勝ち) > Mode > base semantic

各特別テーマは 「自分が上書きする token 一覧」を宣言的に持つ。例:

export const springEarlyTheme = {
  name: 'spring-early',
  allowedTokens: ['--color-primary-*', '--color-accent-*'],
  // Special テーマはこの allowlist 内のみ上書き可能。
  // それ以外の token (foreground / background / border 等) は Mode テーマ (light/dark) が担当。
}

Phase 1 で必要な対応:

  • .claude/rules/theme-architecture.md 新設 — Mode / Special の二軸モデルと cascade ルールを明文化
  • 「特別テーマは何を上書きしてよいか」の allowlist を CSS コメント or TS const で明示
  • Foundations / Theme Composition ストーリーで 8 seasonal × 2 mode = 16 パターンを視覚検証
  • (将来) 利用者定義特別テーマを受け入れる API を検討

2.5 Anti-corruption Layer の漏れ

外部ライブラリの型・名前が Schatten の公開 API に直接漏れている箇所:

漏れているもの 場所 影響
lucide の icon 名集合 IconName = keyof typeof icons (Button.tsx:7) lucide のバージョン上げで Schatten の API が破壊的に変わる
Radix の Props 型 各 compound component (Select, Dialog, Tooltip) で間接 re-export Radix のメジャー更新に追従が必要
Lucide のアイコン Props <IconComponent className=...> を Button 内で展開 アイコンライブラリ移行が困難に

影響: 「1.0 で API 固定」を宣言したくても、外部依存に縛られて固定できない。

対策 (5章 ROI 順 #4 と統合):

  • <Icon> ラッパー + 許可リスト型でアイコン境界を閉じる
  • Radix Props の公開は意図的なら明文化、そうでないなら型ガードを挟む

2.6 スケーリング懸念

現状 18 個が flat 配置 (src/components/lv1/):

src/components/lv1/
├── Badge/  Button/  Callout/  Checkbox/  Dialog/  Field/  FieldSet/
├── Input/  Radio/   Select/   Separator/ Spinner/ Switch/ Text/
├── Textarea/  Toast/  Tooltip/   ← 計 18

50 個に増えたときの想定:

  • フラット配置だとファイラーで一覧不能
  • index.ts の re-export が巨大化
  • カテゴリ別の grep が困難

提案: lv1 内に category subdirectory を導入する閾値を決める。例: 25 個超えたら form/, disclosure/, navigation/, data/, feedback/, layout/ に再編成。あるいは Phase 3 の新規追加と同時に最初から category-based にする。

2.7 Type Composition

良い点:

  • ButtonProps extends ButtonHTMLAttributes, ButtonVariants パターンが標準化
  • VariantProps<typeof buttonVariants> で variant 型が自動派生

未対応:

  • asChild を使うと 戻り値の DOM 型が変わる が、ButtonProps はそれを表現していない (forwardRef<HTMLButtonElement> に固定)
  • polymorphic component pattern (as prop) は未採用 — これは shadcn 慣習との整合で OK だが、「採用しない」を明文化しないと AI / 人間が迷う

2.8 ビルドアーキテクチャ — Framework-Agnostic 路線(確定方針)

tsup.config.ts は 3 つの独立ビルドを定義:

  1. variants/index (React 抜き — CSS クラス生成のみ)
  2. components/{index,lv1,lv2} (React 必須)
  3. themes/seasonal/index + CSS 複製

確定方針(オーナー確認済): Schatten は 「React コンポーネント DS」であると同時に「framework-agnostic な CSS / クラス DS」 という二層構造で位置づける。素の HTML / Astro / Vue / Svelte でも <button class="btn btn-primary"> の形で組み込み可能であることを一級市民として扱う。

この方針が DS 全体に与える含意:

領域 含意
ポジショニング shadcn 系 React DS とは差別化される独自軸。「React lock-in しない DS」というメッセージが立つ
API 安定性 CSS クラス名 (.btn, .btn-primary, .input-wrapper 等) は公開 API として 1.0 で固定する必要がある
variants の型 buttonVariants({ variant: 'primary' }) で得られる class string も公開 API。CVA の出力形式に依存しない契約が必要
トークン --color-primary-600 のような変数名も公開 API。現状の primitive 名 (vermillion, sumi, alabaster) も同様に固定対象
ドキュメント 「React 利用例」と「素の HTML 利用例」を並列で示すストーリーが必須
バージョニング クラス名のリネームは破壊的変更扱い

Phase 1 で必要な対応:

  • README の冒頭に「Schatten works without React. Use plain HTML + CSS or import the React components.」と明示
  • Storybook に Getting Started / Vanilla HTML ストーリー追加
  • Getting Started / For Astro Getting Started / For Vue も並列で(Vue/Svelte は class 利用例のみ)
  • CSS クラス名・variant 出力・CSS 変数名を**「公開 API」として CHANGELOG / migration guide の対象に含める**ことを .claude/rules/api-stability.md に明文化
  • クラス名公開 API の棚卸し(下記チェックリスト)を実施

2.8.1 クラス名公開 API 棚卸しチェックリスト

オーナー判断(確定): 1.0 リリースの DoD として棚卸しを完遂する (Option A)。1.0 を「真の framework-agnostic を保証する」リリースにする。Phase 1 で横断ルール決定 → Phase 3 で 18 コンポ実装 → Phase 4 で出口条件確認、という流れ。

前提となる現状認識:

  • .btn クラスは variants/button.ts:5 で参照されているが、CSS 定義が存在しない (phantom class)
  • src/schatten.css は CDN 利用を想定 (コメントあり) だが、現状 import しているのは token 4種 + デフォルトテーマ + Spinner.css + Toast.css のみ
  • 現状の「素の HTML で使える」は token / 色レベルでのみ成立。コンポーネント styling は React + Tailwind パイプラインに依存している
  • 1.0 で framework-agnostic を保証するには CVA 出力相当を @layer components で CSS rule 化する必要がある
横断ルール(棚卸し前に決定)
  • 命名規約を 1 つに統一:
    • 案 A: BEM スタイル (.btn, .btn--primary, .btn--sm)
    • 案 B: チェーン (.btn.btn-primary.btn-sm)
    • 案 C: data 属性 (<button class="btn" data-variant="primary" data-size="sm">)
    • → 推奨は A (BEM) または C (data 属性)。Tailwind utility chain (btn btn-primary btn-sm) は内部実装を漏らすので避ける
  • CSS layer 戦略: Tailwind v4 @layer components を採用するか、独自レイヤーか
  • Single source of truth: CVA 文字列か @layer components か。両方持つなら生成側(コードジェネ)を決める
  • State 表現: :disabled, [aria-invalid], [data-state="open"], .dark のうちどれを公式に採用するか
  • internal-only utility の扱い: animation / focus-visible / transition 等を public class に含めるか分離するか
  • ダーク対応: .dark .btn { ... } か [data-mode="dark"] .btn か :where(.dark) .btn
コンポーネント別棚卸し(lv1 全 18)

各コンポーネントについて以下を埋める:

  • ルート semantic class 名を確定 (例: .btn, .input, .input-wrapper, .toast, .toast-item)
  • variant modifier 一覧を列挙 (例: Button → .btn--primary, .btn--secondary, .btn--tertiary, .btn--inverted, .btn--destructive, .btn--link)
  • size modifier 一覧を列挙
  • state 表現を確定 (例: .btn:disabled, .btn[data-loading="true"])
  • CVA 出力 → @layer components への書き起こし (Tailwind utility chain を CSS property に展開)
  • vanilla HTML 利用サンプルを Storybook に追加
  • public class 一覧を .d.ts または manifest に export (AI / IDE 補完用)
# コンポーネント 担当 状態
1 Badge – ⬜
2 Button – ⬜
3 Callout – ⬜
4 Checkbox – ⬜
5 Dialog – ⬜
6 Field – ⬜
7 FieldSet – ⬜
8 Input – ⬜
9 Radio (+ RadioGroup) – ⬜
10 Select – ⬜
11 Separator – ⬜
12 Spinner – ⬜
13 Switch – ⬜
14 Text – ⬜
15 Textarea – ⬜
16 Toast (+ Toaster) – ⬜
17 Tooltip – ⬜
棚卸し完了の出口条件
  • 全 18 コンポーネントで @layer components への書き起こしが完了
  • dist/schatten.css に全コンポーネントの CSS ルールが含まれている
  • Storybook で 「同じ見た目を React と vanilla HTML の両方で再現できる」検証ストーリーが動く
  • public class 一覧が dist/schatten.manifest.json に export されている
  • .claude/rules/api-stability.md でクラス命名規約と破壊的変更ポリシーが定義済み

3. 横断的観点 — Performance / SSR / TestID / Theme API

DS 評価でもアーキテクチャ評価でも完全には括れない、**「利用者が実プロダクトに組み込んだ瞬間に痛みが出る」**4つの観点。

3.1 パフォーマンス ⭐⭐

バンドルサイズ

観点 現状 評価
Multi-entry exports 9 entries で部分採用可能 ◎
Tree-shaking external 設定 external: ['react', 'react-dom'] のみ (tsup.config.ts:25) ⚠️
package.json の sideEffects 未指定 ⚠️ bundler が安全側に倒して全 import が活性化
lucide-react の取り扱い external 未指定 + import { icons } from 'lucide-react' で 全 icon map を読み込み (Button.tsx:2) ❌ 最重要懸念
Radix の取り扱い external 未指定 — dependencies 経由で重複インストールはないが、dist に同梱される ⚠️
CSS バンドル lightningcss --minify --bundle で dist/schatten.css 1 ファイルに統合 ◎ サイズ自体は小、ただし利用者が「Button だけ使う」時も全 CSS が読まれる
CI でのサイズ計測 なし ❌

最重要懸念の検証手順:

pnpm build && du -sh dist/components/lv1/index.js
# 想定外に大きければ (>200KB)、lucide が丸ごとバンドルされている

対策:

  • lucide-react を peerDependencies に移す + README で install を促す
  • Icon ラッパー化 (5.3 と統合) + import { ArrowRight, Trash2 } from 'lucide-react' の named import に統一して動的アクセスを排除
  • package.json に "sideEffects": ["*.css"] を追加 — CSS 以外は副作用なしを宣言
  • CI に size-limit か bundlewatch 導入

実行時パフォーマンス

観点 現状 評価
useMemo で context value 安定化 Field, FieldSet が実施 ◎
外部 store によるレンダー分離 Toast は use-toast.ts で分離 ◎
CSS-in-JS なし (CVA + Tailwind) ランタイムコスト最小 ◎
Portal の遅延マウント 制御なし ⚠️ 大規模ページで Tooltip 群が早期マウントされる懸念

3.2 SSR 互換性 ⭐

観点 現状 評価
'use client' ディレクティブ ゼロ件 (src/ 全体) ❌
useId / useRef 使用 8 コンポーネント (Input, Radio, Checkbox, Switch, Field, FieldSet, Textarea, Select) クライアント側で必要
Radix Portal 使用 Tooltip / Dialog / Select クライアント側で必要
document / window 直接参照 なし (Radix が抽象化) ◎
README に SSR 注意書き なし ❌

結論: 現状 Next.js App Router の Server Components から直接 import するとビルド失敗する。Radix 自体は 'use client' 付きで配布されているため、Schatten もそれに揃えるのが業界標準。

対策(一つを選ぶ):

案 推奨度 説明
A. 全 lv1 ファイル先頭に 'use client' を追加 ★★★ tsup の banner で一括注入可能。利用者は何も考えず使える
B. ./components/lv1/client 別エントリ ★★ server-safe な部分 (型 export 等) と分離できるが複雑
C. README に「Client Components 内のみ」と明示 ★ 最低限の対応、DX は悪い

推奨は A。lv1 全てが client 前提なので、tsup の banner: { js: "'use client';" } を該当ビルドに追加するだけ。VRT も Storybook も影響なし。

3.3 TestID 規約 ⭐⭐

現状:

  • 各コンポーネントは ...props を forward しており、data-testid は通る (Separator.test.tsx:7, Callout.test.tsx:132)
  • testId のような専用 prop は採用していない (DOM 属性そのままパス)
  • 規約として明文化されていない
  • Portal 配下の要素 (Dialog Content, Select Content, Tooltip Content) への testid 経路が未定義

問題: 利用プロダクトの E2E (Playwright / Cypress) で testid 命名が散らかる。特に Dialog 内部の要素を捕まえるとき:

// 利用者が書きうる N パターン
<Dialog>
  <DialogContent data-testid="confirm-dialog-content"> ... </DialogContent>
</Dialog>

// vs
<Dialog data-testid="confirm-dialog"> ... </Dialog>

// vs (Schatten が内部で testid を生成する)
<Dialog testId="confirm-dialog">  // → root, content, overlay 全てに自動 prefix

推奨方針: 現状の A 方式 (...props 直 pass) を維持しつつ、.claude/rules/component-testid-guideline.md で明文化:

  • ルート要素には ...props 経由で data-testid を通せる
  • compound component では、各サブ component が独立して data-testid を受ける
  • Schatten 内部では data-testid を自動付与しない (ユーザの testid 戦略を侵食しない)
  • E2E 推奨パターンを Storybook の Patterns / Testing ストーリーに掲載

3.4 Theme 切替 API ⭐⭐

現状:

  • React 側に ThemeProvider / useTheme の export なし
  • getCurrentSeason() (日付ベースの pure function) だけが src/themes/seasonal/index.ts から export
  • 実装例は Storybook の preview.tsx にしかない — そこでは document.documentElement.classList.toggle('dark') を手動で行う (.storybook/preview.tsx)

問題:

  1. 利用者は自前で全部書く — localStorage 永続化 / システム設定マッチ / FOUC 回避 / SSR hydration mismatch 回避
  2. 誤実装の温床 — 特に Next.js App Router で 'use client' を付け忘れる、または hydration 前に DOM を触る問題
  3. DS としてのオピニオン不在 — next-themes 推奨か、自前 provider 提供か、未決定

選択肢:

案 メリット デメリット
A. ThemeProvider を schatten が提供 利用者は1行で完結 SSR / framework 依存性が DS に入り込む
B. next-themes を peer dep として推奨し README に書く 既存エコシステムに乗る Next.js 寄りに見える
C. 切替パターンを .claude/skills/setup-theme-toggle/ で各 framework 向けレシピ化 レシピが並列で出せる コード自動化されない
D. 何もしない (現状) DS が薄い 利用者が毎回はまる

推奨: A を Phase 2 で実装。framework-agnostic な ThemeProvider として作る:

<ThemeProvider
  defaultMode="system"          // 'light' | 'dark' | 'system'
  seasonal={{ auto: true }}      // 日付から自動判定
  storageKey="schatten-theme"
>
  {children}
</ThemeProvider>

SSR ガード用の インラインスクリプト snippet を README に掲載し、FOUC を防ぐ。


4. 堅牢性・コード品質評価

4.1 良い点

  • TS strict 有効 (tsconfig.json:12) + Biome + lefthook の pre-commit 二重ガード
  • VRT の運用が成熟 (.github/workflows/vrt.yml)
  • tsup のマルチエントリ + CSS 複製で components/lv1, variants, themes/seasonal を独立 import 可能
  • Field / FieldSet の context 設計が文書化済み

4.2 明確な堅牢性ギャップ(優先度順)

# 問題 場所 影響
1 Stories / Tests が typecheck から除外 tsconfig.json:24 "exclude": ["**/*.stories.tsx", "**/*.test.tsx"] pnpm typecheck が story / test の型エラーを検出しない
2 8 コンポーネントが unit test なし Badge / Checkbox / Radio / Select / Spinner / Switch / Text / Textarea テスト網羅率が読めない
3 3 コンポーネントが VRT spec なし Field / FieldSet / Tooltip 視覚回帰のブラックホール
4 changeset 必須が CI で強制されていない .github/workflows/ci.yml に changeset status チェックなし バージョン bump 漏れ
5 a11y 自動テストなし – @axe-core/playwright を VRT に同居可能
6 Biome が recommended のみ biome.json:13 noUnusedImports 等で品質強制可能
7 lv2 が空 stub のまま src/components/lv2/index.ts 判定基準が未定義
8 bundle size 監視なし – size-limit 等を CI 化推奨
9 Storybook 公開ビルドの a11y check なし – storybook-addon-a11y
10 tsup の CSS 複製が onSuccess 紐付き tsup.config.ts:37 エントリ順を変えるとサイレントに崩れる

4.3 設計レベルの懸念

  • Compound component(Select, Dialog, Tooltip)と単一 export(Button, Input)の使い分け方針が未文書化
  • lv1 内に Toaster.tsx、use-toast.ts、Toast.css のような付随ファイルが共存 — CSS ファイルを許容する基準が暗黙

5. AI 親和性評価 ⭐⭐⭐

「AI(Claude / Cursor / Copilot / v0 など)がこの DS をどれだけ正しく使い・拡張できるか」の評価。

5.1 既に AI フレンドリーな点

  1. Props 型を index.ts から全部 export している — AI が .d.ts を読めば正しい prop が分かる
  2. CVA で variant が型として現れる — 補完に出る
  3. .claude/rules/ が CLAUDE.md から参照済み — Claude Code はワークツリー起動時に CLAUDE.md を読む
  4. variants ディレクトリの集中 — src/variants/ を1パスで列挙できる
  5. TS strict + Biome + CI — AI 出力への即フィードバックループ

5.2 AI が高確率で踏み抜く落とし穴

B-1. デザイントークンが型を持たない(最大の問題)

  • CSS 変数 + Tailwind ユーティリティのみ
  • AI には「使える Tailwind クラスの全集合」が見えない → bg-red-500, text-gray-700 を書きがち
  • セマンティック名(bg-error vs bg-error-subtle)の使い分けがコード上で区別不能

B-2. Icon 名の hallucination

  • IconName = keyof typeof icons — lucide のバージョン依存。AI は学習時点の名前を混在させる

B-3. variant 語彙がコンポ別で揃っていない

  • Button: primary | secondary | tertiary | inverted | destructive | link
  • Badge/Callout/Toast は独自語彙
  • AI が <Badge variant="primary"> と書く → CVA は未定義 variant でデフォルト fallback、silent fail

B-4. compound component のインポートが推測ゲーム

  • Select は 11 個の sub-component を export
  • 「Dialog は compound、Button は単一」というメンタルモデルがコード上に明示されていない

B-5. asChild パターンの誤用

  • Button にしか asChild がない(Input, Select には?)
  • AI は全コンポにあると仮定して書きがち

B-6. lv2 が空 → AI が毎回違う合成を作る

  • 「Field + Input + label + error 表示」を書かせると毎回少しずつ違う JSX
  • 正解の参照点が存在しないため、AI 同士の出力が DS 採用前より散らかるという皮肉

B-7. Stories が AI 用 example として最適化されていない

  • render: () => ... 形式で variant 列挙が宣言的でない
  • AI は「コードを読んで抽出」する必要があり、宣言的でない

B-8. 「これは DS だから書くな」が AI に伝わらない

  • 直接 <input className="border rounded p-2"> を書く誘惑
  • CLAUDE.md でカバーされているが、Claude Code 外の AI(Copilot 等)には届かない

5.3 AI 親和性を上げる打ち手(ROI 順)

🥇 即効性が高い(数時間〜半日)

1. Props 型に JSDoc を全面付与

export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, ButtonVariants {
  /**
   * Visual style of the button.
   * - `primary`: solid fill, main CTA
   * - `secondary`: outlined, secondary actions
   * - `destructive`: for delete/remove actions (red)
   * @default 'primary'
   */
  variant?: ButtonVariants['variant']
}
  • 効果: hover tooltip / autocomplete に description が出る → Copilot 含む全 AI が文脈を獲得
  • 現状の argTypes.description は Storybook 内専用で再利用されていない

2. ルートに AGENTS.md を新設

  • 業界で AGENTS.md が AI 向けの README 標準として浮上中
  • 内容: CLAUDE.md と重複してよい

3. src/tokens.ts で CSS 変数を TS の constant として再 export

export const tokens = {
  color: {
    error: 'var(--color-error)',
    errorSubtle: 'var(--color-error-subtle)',
    foreground: 'var(--color-foreground)',
  },
  spacing: { /* ... */ },
} as const
export type ColorToken = keyof typeof tokens.color

🥈 中期(1-3日)

4. Icon ラッパーコンポーネント + 許可リスト型

const ALLOWED_ICONS = ['ArrowRight', 'Trash2', 'Check'] as const
export type IconName = (typeof ALLOWED_ICONS)[number]

5. variant 語彙の意図的な統一 ✅ Phase 1 に確定済み (オーナー判断)

  • 提案: 全コンポで variant の意味を「色トーン」に統一、形は別 prop (appearance) で分離
  • Pre-1.0 のため破壊的変更を恐れず実施。以降の Phase が最終 API を前提に進められる

6. lv2 を最低3個作る

  • FormField / ConfirmDialog / EmptyState

7. .claude/skills/ で能動ワークフロー

  • add-lv1-component / audit-component Skill

🥉 戦略(1-2週間)

8. コンポーネントマニフェスト JSON を生成

  • dist/schatten.manifest.json を CVA + 型 + argTypes から自動生成
  • v0, Cursor, MCP server からプログラマブルに DS を検査可能に

9. Storybook MCP サーバ化

  • Storybook 9 系のロードマップ次第

10. ESLint / Biome custom rule

  • bg-red-* 等の primitive 色を JSX で禁止 → state token 強制

6. Claude Skill / Rules 統一化提案

現状: .claude/ には rules/ 4本と commands/review-pr.md のみ。Rules は読まれる前提なので網羅的だが、能動的なトリガーがない点が課題。

6.1 推奨ディレクトリ構成

.claude/
├── rules/                              # 既存: 受動的な参照ドキュメント
│   ├── component-architecture.md       ★新設: lv1/lv2 判定基準・compound vs単一の方針
│   ├── component-api-conventions.md    ★新設: isError/disabled/size の命名・型統一
│   ├── field-context-guideline.md      (既存)
│   ├── state-token-guideline.md        (既存)
│   ├── storybook-guideline.md          (既存)
│   ├── vrt-spec-guideline.md           (既存)
│   └── testing-guideline.md            ★新設: 必須テストケース表 + 未実装の補完方針
│
├── skills/                             # ★新設: 能動的に呼ばれるワークフロー
│   ├── add-lv1-component/SKILL.md      "新しい lv1 コンポーネントを追加する" 起動
│   ├── add-vrt-spec/SKILL.md           "VRT spec を追加" 起動
│   ├── audit-component/SKILL.md        1コンポーネントを全 rule で監査
│   └── prepare-release/SKILL.md        changeset → version → publish 手順
│
├── commands/                           # ユーザーが叩く slash 専用
│   ├── review-pr.md                    (既存)
│   └── audit-coverage.md               ★新設: テスト/VRT 抜けスキャン
│
└── settings.json                       # ★新設: hook で機械的強制
    ├── PostToolUse(Edit) → lv1 配下なら test/vrt 存在チェック
    └── Stop → CLAUDE.md がリストする lv1 件数 と index.ts の export 数を整合チェック

6.2 Skill と Rule の使い分け基準

  • Rule = 「そのトピックに触れる時に読むべきこと」(受動). 設計原則・命名規約・トークン解説など
  • Skill = 「ユーザーがこういう依頼をした時に走るべき手順」(能動). 新規追加・監査・リリース等
  • Command = ユーザーが明示的に起動するもの(/review-pr, /audit-coverage)
  • Hook = 機械的に強制すべきもの(コミット時のチェック等)

6.3 CI 側で同時に締めるべき項目

  1. .github/workflows/ci.yml に pnpm exec changeset status --since=origin/main を追加 → changeset 強制
  2. tsconfig.json の exclude から stories/test を外す(または tsconfig.test.json を別建て)
  3. lefthook.yml の pre-push に pnpm test:vrt --grep <changed-component> を追加(任意)
  4. @axe-core/playwright を VRT spec に同居 → add-vrt-spec Skill のテンプレに axe assertion を含める

7. 統合ロードマップ (v0.5.0 → v1.0.0)

Pre-1.0 の破壊的変更ポリシー (オーナー確認済): 現時点で実利用者がいないため、1.0 リリースまでは破壊的変更を恐れずに API 整理を進める。api-stability.md で定義する公開 API 安定化契約は 1.0 以降にのみ適用する。 結果として、各 Phase で「無破壊で漸進」を優先する必要はなく、最適な形に直接書き換える。例: typography の 3 変数 API は shorthand に置換、variant 語彙統一も同様。

バージョニング方針 (オーナー確認済): 0.x.0 の x を1つずつ進める。Phase はコンセプト粒度として残し、各 Phase 内を 2-3 個の minor バージョン (1-2 週間スプリント想定) に分割する。x ≥ 10 も許容 (v0.10, v0.11, ...)。各 minor は GitHub milestone と 1:1 で対応させる。

Phase 1: 基盤整備

Versions: v0.5.0 → v0.6.0 → v0.7.0 → v0.8.0 目的: AI 親和性を ⭐⭐⭐ → ⭐⭐⭐⭐⭐ に底上げし、規範を明文化し、API 整理を実装し、production 採用の壁を除去する

v0.5.0 — AI / DX 基盤

テーマ: 「Schatten が IDE / AI で使いやすくなった」

  • Props 型に JSDoc 全面付与(全 lv1 コンポーネント)
  • src/tokens.ts で TS 型付き token export を追加
  • ルートに AGENTS.md 新設(Claude 以外の AI 向け)
  • tsconfig.json の exclude から stories/test を外す
  • CI に changeset status チェックを追加
  • Biome ルール強化(noUnusedImports, useExhaustiveDependencies 等)
  • 8 コンポーネントの unit test を補完
  • 3 コンポーネントの VRT spec を補完

v0.6.0 — 規範整備 (Rules / Hooks)

テーマ: 「設計原則と命名規約が文書化された」(以降のすべての実装の前提)

  • .claude/rules/component-api-conventions.md 新設 — variant 語彙統一の方針 + isError/disabled/size の型・命名 (v0.7 での実装の前提)
  • .claude/rules/component-architecture.md 新設 — 以下を含む:
    • lv1/lv2 判定基準
    • compound vs flat の選択基準
    • asChild 採用基準
    • polymorphic component pattern (as prop) を採用しないことを明文化
    • contexts の消費規範 (どの lv1 が Field/FieldSet を消費して OK か、lv2 が context を消費する時の順序)
    • lib/utils.ts の import 規範 (lv2 は lib/ から直接 import、lv1 経由しない 等)
    • lv1 内に component CSS ファイル (Toast.css, Spinner.css) を置く許容基準 (アニメーション / Tailwind で表現困難なものに限定)
  • .claude/rules/spacing-conventions.md 新設 — AI 向けに「gap / padding は DS スケールのみ使用」(Layout primitives 不採用判断の補完)
  • .claude/rules/testing-guideline.md 新設 — 必須テストケース表
  • .claude/rules/theme-architecture.md 新設 — Mode × Special の二軸モデルと cascade ルール (Special > Mode > base semantic) を文書化
  • .claude/rules/api-stability.md 新設 — CSS クラス名・variant 出力・CSS 変数名を「公開 API」として CHANGELOG 対象にする規約 (1.0 以降に発効)
  • .claude/rules/component-testid-guideline.md 新設 — ...props 直 pass 方式の明文化 + Portal 経路ルール
  • .claude/settings.json の hook 整備 — PostToolUse(Edit): lv1 編集で test/vrt 存在チェック / Stop: lv1 件数と export 数の整合

v0.7.0 — API 実装 + Framework-Agnostic 正式化

テーマ: 「最終 API がほぼ確定。素の HTML で動く道筋が見えた」

  • variant 語彙の意図的な統一の実装 — v0.6 の component-api-conventions.md に従って 18 コンポを refactor (「色トーン」と「形」を別 prop に分離)
  • package.json の . exports に JS/types エントリを追加 — import { Button } from '@yasmro/schatten' を動かす
  • ./components/lv2 の空 export を一旦削除 (lv2 実装後に復活)
  • README 冒頭に「Schatten works without React」を明示
  • Storybook Getting Started / Vanilla HTML ストーリー追加
  • Storybook Getting Started / For Astro / For Vue ストーリー追加 (class 利用例のみ)
  • 各特別テーマの token allowlist を CSS コメント or TS const で実装
  • Foundations / Theme Composition ストーリーで 16 パターン視覚検証 (8 seasonal × 2 mode)

v0.8.0 — Production 統合 (Perf / SSR)

テーマ: 「Next.js App Router で動く。サイズ計測も入る」

  • 'use client' を tsup banner で全 lv1 ビルドに自動注入 — Next.js App Router 対応 (最優先)
  • lucide-react を peerDependencies 移動 + import { icons } を named import に置換
  • package.json に "sideEffects": ["*.css"] 追加
  • CI に size-limit 導入 (lv1 全体で 100KB を初期閾値)
  • README に SSR 利用ガイド追加 (Client Components 内のみで動作する旨)
  • tsup の CSS 複製を onSuccess から独立スクリプト化 (scripts/copy-css-assets.ts)
  • Biome custom rule で primitive 色クラス (bg-red-* 等) の JSX 内使用を禁止 — state token 強制

Phase 2: 価値証明

Versions: v0.9.0 → v0.10.0 → v0.11.0 目的: lv2 で「合成の正解」を示し、ドキュメント完備、トークン拡充で DS の価値を証明

v0.9.0 — lv2 + Provider + Skill

テーマ: 「合成パターンの正解が見える」

  • lv2/FormField 実装
  • lv2/ConfirmDialog 実装
  • lv2/EmptyState 実装
  • lv2/PageHeader 実装
  • Icon 共通コンポーネント + 許可リスト型
  • ThemeProvider / useTheme 提供 (light/dark + seasonal を統括する framework-agnostic provider)
  • README に FOUC 回避用 SSR snippet 掲載
  • .claude/skills/add-lv1-component/ 新設(テスト・VRT・story テンプレを必ず展開)
  • .claude/skills/add-vrt-spec/ 新設 (VRT spec 追加専用、axe assertion 込み)
  • .claude/skills/audit-component/ 新設 (1 コンポを全 rule で監査)
  • .claude/skills/prepare-release/ 新設 (changeset → version → publish 手順自動化)
  • .claude/commands/audit-coverage.md 新設 (テスト/VRT 抜けスキャンを slash command 化)

v0.10.0 — ドキュメント完備

テーマ: 「学習リソースが揃った」

  • Foundations ページ 5枚追加(Spacing / Elevation / Motion / Iconography / Accessibility)
  • Patterns / Form Composition ストーリー (Field/FieldSet レシピ集)
  • Patterns / Composition with asChild ストーリー (Radix Slot パターン方針)
  • Patterns / Layout ストーリー (Tailwind 直書きで DS スケールを守るレシピ)
  • Patterns / Testing ストーリー (testid 規約と E2E 推奨パターン)

v0.11.0 — トークン拡充 + a11y + 季節テーマ

テーマ: 「微細な仕上げ」

  • Typography を shorthand 一本化 — @utility text-body-md 等を 1 クラスで完結。既存の 3 変数 API は撤去 (破壊的変更可)
  • Shadow / radius / motion の semantic token 追加 — --shadow-card, --radius-control, --motion-instant 等
  • Z-index 用途別 semantic token — --z-tooltip, --z-modal, --z-toast 等
  • @axe-core/playwright を VRT に組み込み
  • Storybook addon-a11y 導入 (開発時の即時 a11y フィードバック)
  • 季節テーマの影響面を --color-accent-*, --shadow-card まで拡張
  • Foundations / Seasonal Showcase ストーリー追加 (8季節 × Button / Badge / Callout)

Phase 3: ナビ・データ系コンポーネント + 大型リファクタ

Versions: v0.12.0 → v0.13.0 → v0.14.0 目的: 「実プロダクトで詰まらない DS」へ + クラス名棚卸し実装

v0.12.0 — Disclosure / Navigation 系

テーマ: 「ナビ系がない」を解消

  • Menu / DropdownMenu
  • Popover
  • Tabs

v0.13.0 — Data 表示系

テーマ: 「データを並べる」基盤

  • Card
  • Avatar
  • Skeleton
  • Table(最小機能)

v0.14.0 — 大型リファクタ + クラス名棚卸し実装

テーマ: 「framework-agnostic を実体化、API を最終形へ」

  • Alert vs Callout の使い分け定義 — Phase 1 で確定した variant 語彙のもとで、Alert を新規追加するか Callout に変種を追加するか決定
  • クラス名公開 API 棚卸しの実装 (§2.8.1) — 18 コンポーネント × CVA → @layer components への書き起こし
  • lv1 を category-based subdirectory に再編 (form/, disclosure/, navigation/, data/, feedback/)
  • Radix Props の re-export 方針を明文化 (公開する/型ガードを挟む)

Phase 4: 1.0 リリース

Versions: v0.15.0 → v1.0.0

v0.15.0 — 1.0 RC

テーマ: 「1.0 で固定する全ドキュメントを揃える」

  • Migration guide 整備
  • ADR ディレクトリ整備 (なぜ shadcn ベース / なぜ npm 配布 / なぜ framework-agnostic 等)
  • AGENTS.md / CLAUDE.md / Contributing.md の三点セット完備
  • Storybook Foundations / Patterns ページの最終チェック
  • Framework-agnostic 動作確認 — Storybook で Vanilla HTML / Astro / Vue 利用例が動く
  • dist/schatten.manifest.json export 動作確認 (public class 一覧)

v1.0.0 — 正式リリース

1.0 の DoD (チェックのみ、新規実装ゼロ):

  • a11y 自動テスト合格(全 lv1)
  • lv1 主要 8 種に lv2 ラッパー存在
  • Tabs / Menu / Popover / Card 追加完了
  • Migration guide / ADR / 三点セット完備
  • クラス名公開 API 棚卸し完了 (§2.8.1 出口条件をすべて満たす)
  • Framework-agnostic 利用例が Storybook で動作確認済み (Vanilla HTML / Astro / Vue)
  • CHANGELOG / アナウンス公開
  • API stability commitment 開始 — api-stability.md に従い、CSS クラス名 / variant 出力 / CSS 変数名 を公開 API 扱いに切り替え

Phase 5: Post-1.0 / 持ち越し研究テーマ

1.0 リリース後に取り組む方が良い未解決テーマ:

テーマ・a11y:

  • 特別テーマの token allowlist 強制機構 (§2.4 関連)
    • lightningcss plugin で違反検出する方式の検証
    • 利用者定義特別テーマを受け入れる API 設計
    • 「event テーマ」「コラボテーマ」等の追加方針
  • 高コントラストモードの位置づけ (§2.4 関連)
    • Mode 軸 (light/dark/high-contrast) として追加するか、Special 軸として追加するか
    • prefers-contrast: more メディアクエリ対応
    • WCAG AAA レベルとの整合
  • 色弱モード対応 (deuteranopia / protanopia / tritanopia)

追加コンポーネント (高機能 / 専門系):

  • Form 系: Combobox / Autocomplete, DatePicker, Slider, FileUpload, Form 送信統括
  • Disclosure 系: Drawer, Accordion / Collapsible, HoverCard
  • Navigation 系: Breadcrumb, NavigationMenu, Pagination
  • Data display 系: List, ProgressBar
  • Layout primitives (Stack / HStack / VStack / Cluster) — 採用判断含む (現状は Tailwind 直書きで運用 + spacing-conventions.md で AI 制約)

ツール / エコシステム:

  • Portal 遅延マウント検討 — 大規模ページでの Tooltip 早期マウント計測 → 必要なら lazy mount API
  • Storybook MCP サーバ化 (§5.3 #9)
  • Vue / Svelte 公式ラッパーコンポーネント (現状はクラス利用のみ提供、コンポーネントとしての提供は将来検討)

付録: 参照ファイル一覧

評価で参照した主要ファイル

プロジェクト設定:

トークン / テーマ:

コンポーネント / バリアント:

Claude rules / commands:

Clone this wiki locally