EY-Office ブログ

先週の続きです shadcn/ui も使われているようなので調べた

先週のブログプログラマーがTailwind CSSを使うならdaisyUIも一緒に使った方が良いと思うの続きです。Tailwind CSSで使われるCSSフレームワーク(CSSコレクション)としてはshadcn/uiも有名なので調べてみました。

shadcn/ui Bing Image Creatorが生成した画像を使っています

shadcn/uiとは

いつものように、AI(Claude Opus 4.6)にまとめもらいました。

shadcn/uiは、再利用可能なUIコンポーネントのコレクションで、従来のコンポーネントライブラリとは異なるアプローチを取っています。

基本コンセプト

shadcn/uiはnpmパッケージとしてインストールするライブラリではなく、必要なコンポーネントのソースコードを自分のプロジェクトに直接コピーして使う仕組みです。CLIツール(npx shadcn@latest add button など)でコンポーネントを追加すると、プロジェクト内にコードが生成されます。

技術スタック

  • Radix UI — アクセシビリティ対応のヘッドレスUIプリミティブがベース
  • Tailwind CSS — スタイリングに使用
  • TypeScript 対応
  • React向け(Next.js、Vite、Remixなどで利用可能)

主な特徴

所有権が開発者にある — コードがプロジェクト内にあるため、自由にカスタマイズできる。ライブラリのアップデートに振り回されない。

依存関係が軽い — 必要なコンポーネントだけを追加するので、バンドルサイズを抑えられる。

デザインが洗練されている — デフォルトのスタイルがモダンで、そのままでも十分使える品質。テーマのカスタマイズもCSS変数で容易。

豊富なコンポーネント — Button、Dialog、Select、Table、Form、Toast、Command Palette など、実用的なコンポーネントが40種以上揃っている。

注意点

  • Tailwind CSSが前提なので、他のCSSアプローチとは相性が悪い場合がある
  • コードをコピーする方式のため、上流の修正を自動的に取り込む仕組みはない(手動マージが必要)
  • Radix UIへの依存があるため、完全にゼロ依存ではない

ちなみにshadcn/uiの読み方はシャッドシーエヌ スラッシュ ユーアイが一般的なようです。

どれくらい使われているのでしょうか?

2025年のReactユーザーへのアンケートState of React 2025: UI Librariesでは、MUIとほぼ同じシェアで僅差で2位でした。

また、npmライブラリーのダウンロード数では以下の画像のように、2025年後半からはdaisyUIを抜き2026年には凄い勢いで伸びています❗(なぜでしょうか? 後で書きます)

いつものジャンケンアプリをでshadcn/ui作ってみた

先週のジャンケンアプリからdaisyUI・Tailwind CSSを取り除いたコードにshadcn/uiを適応してみました。

インストール・設定

インストール・設定はDocs→Installation→Viteに書かれている通り。

  1. Tailwind CSSのインストール npm install tailwindcss @tailwindcss/vite
  2. src/index.css@import "tailwindcss"; を指定
  3. tsconfig.json, tsconfig.app.jsonに baseUrl, pathを追加
  4. vite.config.tsの plugin: に tailwindcss()resolve: paths: を追加
  5. shadcnの初期化 npx shadcn@latest init
  6. 必要なコンポーネントの追加、今回はButtonとテーブルを追加 npx shadcn@latest add button table

shadcn/uiのUIコンポーネントはnpmライブラリーとしてインストールされるのではなく、コンポーネントのコードがプロジェクトに追加されます。

├── src
│   ├── components
│   │   ├── ApplicationBar.tsx
│   │   ├── JyankenBox.tsx
│   │   ├── ScoreList.tsx
│   │   ├── StatusBox.tsx
│   │   ├── SubHeader.tsx
│   │   └── ui
│   │       ├── button.tsx         ← npx shadcn@latest add button で追加
│   │       └── table.tsx          ← npx shadcn@latest add table  で追加

コンポーネントの利用結果

daisyUIとshadcn/uiとの違いを見てみましょう。

button

shadcn/uiにはButtonコンポーネントが定義されています。

daisyUI版
export default function JyankenBox ({pon}: JyankenBoxProps) {
  return (
    <div className="w-57.5 mx-auto flex mb-10 gap-5">
      <button onClick={() => pon(Te.Guu)} className="btn btn-primary">グー</button>
      <button onClick={() => pon(Te.Choki)} className="btn btn-primary">チョキ</button>
      <button onClick={() => pon(Te.Paa)} className="btn btn-primary">パー</button>
    </div>
  );
}
shadcn/ui版
export default function JyankenBox ({pon}: JyankenBoxProps) {
  return (
    <div className="w-57.5 mx-auto flex mb-10 gap-5">
      <Button onClick={() => pon(Te.Guu)}>グー</Button>
      <Button onClick={() => pon(Te.Choki)}>チョキ</Button>
      <Button onClick={() => pon(Te.Paa)}>パー</Button>
    </div>
  );
}

ボタンの色はCSS変数で指定しました。 --primary: oklch(0.488 0.243 264.376);

table

MUI同様にTable, TableRowなどの専用タグを使う必要があります(個人的にはあまり好きではないです)。

daisyUI版
export default function ScoreList ({scores}: ScoreListProps)  {
  const dateHHMMSS = (d: string) => d.substring(0, 8);

  return (
    <table className="table table-zebra">
      <thead className="bg-slate-100 border">
        <tr>
          <th>日時</th>
          <th>人間</th>
          <th>コンピュータ</th>
          <th>結果</th>
        </tr>
      </thead>
      <tbody>
        {scores.map((score, ix) => (
          <tr key={ix} className={JudgmentColor[score.judgment]}>
            <td>{dateHHMMSS(score.matchDate)}</td>
            <td>{teString[score.human]}</td>
            <td>{teString[score.computer]}</td>
            <td>{judgmentString[score.judgment]}</td>
        </tr>))}
      </tbody>
    </table>
  );
}
shadcn/ui版
export default function ScoreList ({scores}: ScoreListProps)  {
  const dateHHMMSS = (d: string) => d.substring(0, 8);

  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>日時</TableHead>
          <TableHead>人間</TableHead>
          <TableHead>コンピュータ</TableHead>
          <TableHead>結果</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {scores.map((score, ix) => (
          <TableRow key={ix} className={JudgmentColor[score.judgment]}>
            <TableCell>{dateHHMMSS(score.matchDate)}</TableCell>
            <TableCell>{teString[score.human]}</TableCell>
            <TableCell>{teString[score.computer]}</TableCell>
            <TableCell>{judgmentString[score.judgment]}</TableCell>
        </TableRow>))}
      </TableBody>
    </Table>
  );
}

shadcn/uiにはnavbar的なコンポーネントはないので、自分で作る必要がありました(もちろんAIに作ってもらいました😅)。

daisyUI版
export default function ApplicationBar() {
  return (
    <div className="navbar bg-primary text-primary-content">
      <div className="flex flex-wrap">
        <h1 className="ml-5 text-2xl font-bold">じゃんけん ポン!</h1>
      </div>
      <div className="flex-none">
        <ul className="menu menu-horizontal px-1">
          <li><Link to="/scores">対戦結果</Link></li>
          <li><Link to="/status">対戦成績</Link></li>
        </ul>
      </div>
    </div>
  );
shadcn/ui版
export default function ApplicationBar() {
  return (
    <nav className="flex items-center gap-8 bg-blue-600 px-6 py-4">
      <h1 className="text-2xl font-bold text-white tracking-wide">
        じゃんけん ポン!
      </h1>
      <div className="flex items-center gap-6">
        <Link to="/scores" className="text-sm text-blue-100 hover:text-white transition-colors">
          対戦結果
        </Link>
        <Link to="/status" className="text-sm text-blue-100 hover:text-white transition-colors">
          対戦成績
        </Link>
      </div>
    </nav>
  );
}

なぜshadcn/uiが流行っているのか?

どれくらい使われているのでしょうか?のグラフのように、shadcn/uiは2025年後半から急速に使われるようになったのは何故でしょうか? 気になったのでAI(Claude Opus 4.6)に聞いてみました。

2025年末からshadcn CLIのダウンロード数が増加している主な要因は、複数の大きなアップデートとAIコーディングブームの相乗効果です。

主な要因

1. npx shadcn create のリリース(2025年12月)

2025年12月に npx shadcn create コマンドが追加され、コンポーネントライブラリ、アイコン、ベースカラー、テーマ、フォントなどをすべてカスタマイズして、自分だけのshadcn/uiを構築できるようになりました。 従来のテーマ変更がカラーを変えるだけだったのに対し、新しい設定はコンポーネントコード自体を書き換えて開発者の好みに合わせます。 ビジュアルビルダーで、コードを書く前にプロジェクトのデザインシステム全体をプレビュー・カスタマイズできるようになりました。これはnpx shadcn createを実行するたびにnpmダウンロードとしてカウントされるため、直接的にダウンロード数を押し上げます。

2. CLI 3.0とMCPサーバー(2025年8月)

CLI 3.0では名前空間レジストリ、プライベートレジストリ、検索・ディスカバリー機能、MCPサーバー統合が追加されました。 MCPサーバーにより、Cursor、Claude Code、VS CodeなどのAIツールがshadcnコンポーネントを正確に理解・生成できるようになりました。

3. AIコーディングツールとの親和性

shadcnはほとんどのAIコーディングツールでデフォルトとなっており、AIがこれらのコンポーネントを最もよく「理解」するため、より正確な結果と高速なプロンプティングが実現します。 v0、Lovable、Bolt、Cursor、Claude Codeなどのツールがshadcn/uiをベースに生成するため、これらのツールの普及がそのままCLIの利用増加につながっています。

4. 2025年後半の継続的な機能追加

2025年は毎月のように大きなアップデートがあり、radix-ui移行(6月)、Universal Registry Items(7月)、Registry Index(9月)、Registry Directory(10月)、新コンポーネント追加と、非常に活発な開発が続きました。 2026年1-2月にもRTLサポートやBase UI対応など新機能が追加されています。

要するに、AIコーディングツール(特にvibe coding)の爆発的普及 × shadcn側の積極的なAI対応(MCPサーバー等) × shadcn createという新しいCLIコマンドの追加、という3つの要因が重なった結果です。

まとめ

shadcn/uiは、daisyUIに比べると大げさな作りになっていますが、ある程度の大きさのあるアプリ(サービス)を作る際、統一されたページのデザインを提供するためにはshadcn/uiは良い選択しかもしれませんね。 さらにClaude CodeやCodexなどのバイブコーディングツールがデフォルトで使うので、これからますます使われるようになってくると思われます。

ただし、小規模なアプリやツール等を手早く作るにはdaisyUIの方が良いかなと思いました。

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ