12k
All articles

shadcn/ui が Radix から Base UI に切り替えた

shadcn/uiは新規プロジェクトをRadixからBase UIへ変更。何が変わったか、移行不要な場合、移行コストの実態を解説します。

OpenReplay Team
OpenReplay Team
shadcn/ui が Radix から Base UI に切り替えた

あなたの shadcn/ui アプリが Radix 上で動いているなら、移行の必要はありません。Base UI が新規プロジェクトのデフォルトになりましたが、Radix は引き続き完全にサポートされ、アップデートは両方のライブラリに提供され、shadcn チーム自身も本番アプリで Radix を使い続けています。

この切り替えは2026年7月3日に行われました。それ以降の報道の多くは書き直しが必要になるかのように示唆してきましたが、それは changelog が述べている内容とは異なります。

次にすべきことを決めるのは2つの問いです。対応が必須なのかどうか、そして移行を選んだ場合のコストはいくらか。コストはコンパイラが検出できる変更と検出できない変更に分かれ、リスクが潜むのは後者です。

要点

  • Base UI は新規 shadcn/ui プロジェクトのデフォルト。Radix は非推奨ではなく、-b radix を使えば新規 init でも Radix を維持できる。
  • 既存の Radix アプリに変更は不要。アップデートは両方のライブラリに提供され、shadcn チームも本番で Radix を使い続けている。
  • デフォルトが移った理由は、Base UI が安定版 1.6.0 に到達し週間ダウンロード数が600万を超えたこと、そして shadcn/create ユーザーが Radix より2対1の比率で Base UI を選んでいたこと。
  • 移行はビルドを壊す変更(asChild から render へ、Positioner/Popup、nullable な Select の値)と、サイレントな挙動変化(タブの手動アクティベーション、開いたままのメニュー)に分かれ、実質的なコストは後者にある。
  • 移行するなら、両方のライブラリをインストールしたままにし、1コミットにつき1コンポーネントずつ移し、codemod ではなく公式の shadcn skill を使うこと。

2026年7月3日に何が変わったのか

新規の shadcn/ui プロジェクトは Base UI をデフォルトとするようになり、既存プロジェクトについてはそれ以外に何も変わっていません。変わったのは3点です。npx shadcn init を実行すると、明示的に指定しない限り Base UI が選択されること、shadcn/create がリストの先頭に Base UI を置くこと、そしてコンポーネントのドキュメントが Base UI タブで表示され、その隣に Radix タブが並ぶようになったことです。Radix 自体は非推奨ではありません。

新規プロジェクトで Radix を維持するにはフラグを1つ渡すだけです:

pnpm dlx shadcn init -b radix

CI やスキャフォールディングスクリプトがプロンプトなしで shadcn init を呼び出し、Radix が使われることを前提としている箇所があるなら、今すぐこのフラグを渡してください。それらのスクリプトの下にあるデフォルトは変わっています。

shadcn の Base UI コンポーネントへ移行する必要があるのか

必要ありません。changelog は、すべてのアップデートと新規コンポーネントを両方のライブラリに提供すると明言しています。唯一の例外は、Base UI に存在して Radix に対応物がないコンポーネントです。さらに、チーム自身の本番コードは依然として Radix 上にあり、移行の予定はないとも述べられています。安定した Radix アプリには、強制された期限も、非推奨期間も、メンテナンスの断崖もありません。この記事の残りは、移行を「選ぶ」チームのためのものであり、移行「しなければならない」チームのためのものではありません。

なぜデフォルトが移ったのか

changelog は4つの理由を挙げています。ライブラリが安定版 1.6.0 に到達し、週間600万ダウンロードを超えていたこと。メンテナが有用なプリミティブを追加し続けていること。shadcn チームがすでに新規のものすべてで Base UI に標準化していたこと。そして shadcn/create でプロジェクトをスキャフォールドする人々の間で、Base UI が Radix に対しておよそ2対1の比率で選ばれていたことです。

これらの数値は changelog で引用されているものです。Base UI はその後もリリースを続けており、2026年9月4日に 1.8.0 がリリースされました。changelog はまた、Base UI が Radix を作ったのと同じ人々によるものであることにも触れています。インストールするパッケージは @base-ui/react です。古い @base-ui-components/react という名前には npm 上で非推奨通知が付いており、新しいパッケージへリダイレクトされます。

移行で実際に変わるもの

移行のうちビルドを壊す側は機械的です。リネームと型の変更で、コンパイラが即座に検出します。

RadixBase UI
トリガーの asChildrender prop
Portal > ContentPortal > Positioner > Popup
OverlayBackdrop
data-[state=open]: バリアントdata-open: バリアント
onOpenChange(open) + event.preventDefault()onOpenChange(open, details) + details.cancel()

1点補足すると、Positioner/Popup の分割は Menu、Select、Popover、Tooltip のようなアンカー付きポップアップに適用されます。Dialog には Positioner がなく、Dialog.BackdropDialog.Popup の組み合わせになります。

コールバックの変更は次のようになります:

// Radix: block closing via the event
onEscapeKeyDown={(event) => event.preventDefault()}

// Base UI: one callback, with a reason and a cancel()
onOpenChange={(open, details) => {
  if (details.reason === "escape-key") {
    details.cancel()
    return
  }
  setOpen(open)
}}

値の型も変わります。制御された Select は文字列ではなく Value | null を返すようになり、これが最も多いビルドエラーの原因になっています:

const [fruit, setFruit] = useState<string | null>(null)

AccordionToggle Group の値は、単一選択モードであっても常に配列です。したがって value="a"value={["a"]} になります。

コンパイルは通るが挙動が変わる変更

移行の危険な側は、型チェックをきれいに通過しながら、それでもランタイムの挙動を変えてしまいます。特に目立つ差分は3つです:

  • Tabs はデフォルトで手動アクティベーションになる。 矢印キーはトリガー間でフォーカスを移動しますが、Tabs.ListactivateOnFocus を設定しない限り、表示されるパネルは切り替わりません。この prop のデフォルトは false です。Radix のデフォルトは自動アクティベーションでした。
  • Menu のチェックボックス項目とラジオ項目はメニューを開いたままにする。 Menu.CheckboxItemMenu.RadioItem では closeOnClick のデフォルトが false であり、選択時に閉じる Radix とは逆です。素の Menu.Item は依然としてデフォルトが true なので、項目の種類によって挙動が異なります。
  • NavigationMenu はホバーでより速く開く。 Base UI の delay はデフォルト50ms、Radix の delayDuration はデフォルト200ms です。以前はユーザーがかすめて通り過ぎていたメニューが開くようになります。

これらはいずれもエラーを発生させません。クリック後も開いたままのメニューや、矢印キーを無視するタブは、何も throw されないためエラーモニタリングには映りません。この種のリグレッションが表面化するのはセッションリプレイです。ユーザーが矢印キーを押す様子や、チェックボックス項目を2回クリックする様子を見て、UI が期待どおりに反応していないことに気づけます。

Base UI に移るべき人と、移るべきでない人

Radix が提供しなかった Combobox、Autocomplete、Number Field が必要な場合、あるいは新しいレジストリコンポーネントがリリースされるたびに歩調を合わせたい場合は移行してください。アプリが安定していてそのどれにも当てはまらないなら、Radix に留まってください。サポートの約束は明示されていますし、正常に動いている本番アプリがプリミティブの入れ替えから得るものはありません。

コンポーネントの欠落についての噂を判断材料にしないでください。Base UI は Context MenuToast、そして Preview Card という名前の hover-card プリミティブを提供しており、shadcn の Base UI ドキュメントもこの3つすべてをカバーしています。

移行する場合の進め方

codemod ではなく公式の skill を使い、段階的に進めてください。その理由は筋が通っています。codemod はファイルの標準バージョンしか知らないため、手を加えていないコンポーネントには対応できても、変更したコンポーネントでは破綻します。skill は実際にあなたが持っているコードを読み取り、あなたの編集内容を引き継ぎ、挙動の差分を黙って書き換えるのではなくレポートします。

pnpm dlx skills add shadcn/ui

その後、コーディングエージェントに1コンポーネントずつ移行を依頼します。たとえば migrate accordion to base-ui のように。両方のライブラリを同時にインストールしたままにできるので、ステップの間もビルドはグリーンのままです。各実行は生成したコードを型チェックし、そのコンポーネントに関するメモを .migration/ フォルダに書き出し、破棄可能なブランチ上に独立したコミットとして反映します。まず button や label のようなリーフコンポーネントから始め、それらを import するコンポーネントは後回しにしてください。そしてマージ前に各レポートの behavior-changes セクションを必ず読んでください。

1つ警告があります。一部のガイドは、components.json を Base UI に向け直し、すべてのコンポーネントを --overwrite で再追加することを勧めています。これはそれらのファイルに加えたローカルの編集をすべて破棄してしまう方法であり、まさに skill が存在する理由となっている失敗そのものです。

結論

デフォルトは変わりましたが、あなたの義務は変わっていません。既存の Radix アプリは動き続け、新規プロジェクトは -b radix を渡さない限り Base UI になり、移行は任意のプロジェクトです。その目に見えるコストはリネームであり、隠れたコストは挙動です。移行するなら、サイレントな差分のための QA 時間を確保してください。そこがコンパイラの助けが止まる地点だからです。まずは changelog のエントリを自分で読み、Combobox やレジストリとの歩調合わせがブランチを切るに値するかを判断してください。

よくある質問

Base UI は Radix と比べて本番投入可能な水準か?

はい。Base UI は2025年12月に '@base-ui/react' パッケージとして安定版 1.0.0 をリリースし、その後も継続的にリリースを重ね、2026年9月4日に 1.8.0 に到達しました。Radix、Floating UI、Material UI の作者たちによるもので、チームは2つのライブラリ間の移動が少ない労力で済むよう、意図的に API を Radix に似せて設計したと述べています。shadcn チームも新規に始めるプロジェクトすべてで Base UI を使っています。

Base UI では value 系の prop はすべて配列になるのか?

いいえ。Accordion の 'value' は常に配列で、Toggle Group の 'value' は単一選択モードでも常に文字列の配列ですが、Tabs の 'value' はデフォルト 0 の単一値のままで、Select は単一値、配列、または null として型付けされています。Accordion と Toggle Group の値は配列でラップし、制御された Select の state は nullable として型付けし、Tabs はそのままにしてください。

Base UI への移行は、Radix を使っていなかった shadcn コンポーネントに影響するか?

いいえ。Command は cmdk をラップし、Sonner は独立したトーストライブラリ、Calendar は react-day-picker、Input OTP は input-otp、Charts は recharts をベースにしています。いずれも Radix のプリミティブに依存していないため、Radix から Base UI への移行では手つかずのままです。変更が必要なのは、Dialog、Menu、Select、Tabs、Popover のように、プリミティブが Radix 由来のコンポーネントだけです。

shadcn の移行 skill には pnpm が必要か?

いいえ。changelog は pnpm、npm、yarn、bun での skill のインストール方法を記載しており、'npx skills add shadcn/ui' は pnpm コマンドの npm ベースの有効な等価物です。インストール後、skill はコーディングエージェントを通じて実行され、パッケージマネージャに関係なく、1度に1コンポーネントずつ移行し、型チェック済みのコード、'.migration' ディレクトリ内のコンポーネントごとのレポート、そしてコンポーネントごとに1つのコミットを生成します。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.