chakra-ui-refactor について
Chakra UI v3 を使う開発者向けに、UI コードのレビューやリファクタリング、他のスタイリング方式からの変換を支援するスキルです。依頼内容とプロジェクト状況に応じて、アクセシビリティ、レスポンシブ対応、API の使用、保守性を確認します。
主な機能
- 01レビューとリファクタリングの依頼を判別
- 02アクセシビリティとレスポンシブ対応の確認
- 03Chakra UI v3 API の使用状況を検証
- 04HTML、CSS、Tailwind などを Chakra に変換
- 05動作を維持しながら改善点を提示
活用シーン
- 01Chakra UI コンポーネントのレビューと問題特定
- 02Tailwind の UI を Chakra に変換
- 03旧 Chakra API とスタイル記法の更新
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ chakra-ui/ chakra-ui --skill chakra-ui-refactorインストール後、Claude Code で/chakra-ui-refactorを入力して読み込まれたか確認します。
詳細
Chakra UI リファクタリング & レビュー
あなたは Chakra UI v3 を使用した UI コードをレビューし、改善しています。開発者の ニーズに応じて、構造化された批評、書き換えたコード、またはその両方を生成します。 出力を生成する前に、コードとプロジェクトのコンテキストを十分に読んでください。
ステップ 1 — 状況を把握し、意図を判断する
出力の前に、以下を確認してください。
- Chakra UI のバージョン —
package.jsonを確認してください。デフォルトでは v3 を使用します - フレームワーク — Next.js App Router、Pages Router、Vite、素の React
- ソースの種類 — 既存の Chakra、素の HTML/CSS、Tailwind、CSS Modules、 styled-components
- ユーザーが求めていること:
- レビューのみ — 「これを確認して」「これは正しい/慣用的か」「何が問題か」 「私のコードをレビューして」→ 的を絞った修正を伴う批評を生成し、全面的な書き換えは行いません
- リファクタリング / 変換 — 「これをリファクタリングして」「Tailwind から変換して」 「これを整理して」→ 書き換えたコードを生成します
- 両方 — 「レビューして修正して」→ まず批評を、次に書き換えたコードを生成します
レスポンスの冒頭にあなたの解釈を記載してください(例:「既存の Chakra v3 コードとして レビューします。Next.js App Router を想定しています。」)。
まだコードが共有されていない場合は、コードを求めてください。コードの説明を レビューしないでください。
ステップ 2 — コードを分析する
出力モードに関係なく、これらの観点からコードを検討してください。レビューの場合、 これらは指摘事項になります。リファクタリングの場合、これらは修正すべき項目の チェックリストになります。
アクセシビリティ
- すべてのインタラクティブ要素にアクセシブルなラベルがありますか?(アイコン
ボタンの
aria-label、label+input ペアのhtmlFor/id、画像のalt) - キーボードナビゲーションは可能ですか?(フォーカスリングが抑制されていない、 インタラクティブ要素が実際にフォーカス可能である)
- 見出しの階層は理にかなっていますか?(レベルが飛んでいない、
h1が スタイルの近道として使われていない) - フォームフィールドは
Field.LabelとField.ErrorTextを伴うField.Rootで ラップされていますか? - コンポーネントは色だけを唯一のシグナルとして機能しますか?
レスポンシブ対応
- レイアウトコンポーネントは複数のブレークポイントでの挙動を指定していますか?
- レスポンシブトークンの方がうまく機能する箇所に、ハードコードされたピクセル値が ありますか?
- これはモバイルで崩れませんか?(固定幅、小さなビューポートでの
overflow: hidden)
Chakra API の正確性
- v3 のプロップ名が使用されていますか?(
isDisabledではなくdisabled、colorSchemeではなくcolorPalette、spacingではなくgap、isOpenではなくopen) - 複合コンポーネントは正しく使用されていますか?(
Field.Root/Field.Label、Dialog.Root/Dialog.Contentなど) - Next.js App Router で
"use client"は正しく配置されていますか? - v2 のパターンがまだ残っていますか?(
extendTheme、ColorModeScript、useColorModeValue、sxプロップ)
トークンとスタイルの使用
- セマンティックトークンが機能する箇所にハードコードされた色が使用されていますか?
(
bg="#f9fafb"→bg="bg.subtle") - セマンティックトークンの代わりに生の hex 値やパレット値が使用されていますか? これらはダークモードを尊重しません。
- Chakra のスタイルプロップであるべきインラインの
style={{}}プロップが ありますか?
コンポーネント構造
- 不要なネストがありますか?(1 つで済むところに
Box > Box > Box) Stack gap={4}の方がすっきりする箇所に手動のスペーシング(すべての子にmt={4})が使用されていますか?- 適切なレイアウトプリミティブが使用されていますか?(
Flex対Stack対Grid対SimpleGrid)
保守性
- 同じ視覚的パターンが 3 回以上繰り返されていますか?(コンポーネントまたは レシピの候補)
- レシピやスロットレシピを示唆する一回限りのスタイルオーバーライドがありますか?
- プロップの型 / TypeScript の型が存在し、正確ですか?
ステップ 3a — 出力のレビュー
ユーザーがリライトではなく批評を求めている場合に使用します。
指摘事項を影響度別に分類します。
重大 — 動作を壊したり、ユーザーを排除したりするバグやアクセシビリティの不具合
- アイコンのみのボタンに
aria-labelがない - ラベルとの関連付けがないフォームフィールド
onClickがあるのにキーボードで操作できないインタラクティブなBox- 黙って何も起こらない誤った v3 の props 名(v3 では
isDisabledは無効化しません) - App Router でフックを使用しているコンポーネントに
"use client"がない
改善 — 緊急ではないが、正確性や品質に関する問題
- ダークモードを壊すハードコードされた色
- レスポンシブのブレークポイントがない
- 不要なネストや誤ったレイアウトプリミティブ
- まだ動作するが更新すべき v2 のパターン
任意の提案 — ブロッキングではないアイデア
- 繰り返されるパターンをコンポーネントとして抽出する
- 一回限りのスタイルをレシピのバリアントに置き換える
- 不足している TypeScript の型を追加する
重大な問題と重要な改善については、最小限の修正を示します。
**Missing aria-label on close button** (Critical)
The IconButton for closing the dialog has no accessible label.
// Before
<IconButton icon={<CloseIcon />} onClick={onClose} />
// After
<IconButton aria-label="Close dialog" icon={<CloseIcon />} onClick={onClose} />
報告する内容がないセクションは省略します。長さはコードに合わせて調整します — 20 行のコンポーネントには簡潔なレビューが必要であり、網羅的なレビューではありません。
ステップ 3b — 出力のリファクタリング / 変換
ユーザーがリライトまたは変換されたコードを求めている場合に使用します。
ソース別の変換戦略
プレーンな HTML / CSS から
| HTML | Chakra での相当 |
|---|---|
<div> レイアウトラッパー | Box、Flex、Stack、Grid |
<section>、<article> | Box as="section"、Box as="article" |
<nav> | Box as="nav" |
<ul> / <li> | Box as="ul" / Box as="li"、または Stack |
<button> | Button または IconButton |
<a> | Link |
<img> | Image(alt を保持) |
<input>、<select> | Field.Root 内の Input、NativeSelect |
| CSS | Chakra スタイルプロパティ |
|---|---|
display: flex | Flex または display="flex" |
flex-direction: column | Stack または flexDir="column" |
gap: 16px | gap={4}(1 ユニット = 4px) |
padding: 16px 24px | py={4} px={6} |
border-radius: 8px | rounded="md" |
color: #6b7280 | color="fg.muted" |
background: #f9fafb | bg="bg.subtle" |
Tailwind CSS から
| Tailwind | Chakra |
|---|---|
flex、flex-col、flex-row | Flex、flexDir |
gap-4 | gap={4} |
p-4、px-6、py-2 | p={4}、px={6}、py={2} |
text-sm、font-bold | fontSize="sm"、fontWeight="bold" |
rounded-lg、shadow-md | rounded="lg"、shadow="md" |
w-full、max-w-lg | w="full"、maxW="lg" |
hidden md:flex | display={{ base: "none", md: "flex" }} |
grid grid-cols-3 | SimpleGrid columns={3} |
text-gray-500、bg-gray-100 | color="fg.muted"、bg="bg.subtle" |
hover:bg-gray-100 | _hover={{ bg: "bg.subtle" }} |
Tailwind のレスポンシブプレフィックスは Chakra のブレークポイントオブジェクト構文に置き換えます:
// Tailwind: text-sm md:base lg:text-lg
<Text fontSize={{ base: "sm", md: "md", lg: "lg" }} />
CSS Modules から — できるものは Chakra プロパティに変換し、プロパティで表現できないスタイル(アニメーション、複雑なセレクター)には className を残します:
// Before
<div className={styles.card}>...</div>
// After — converted to props; className kept only for unconvertible styles
<Box p={4} rounded="lg" shadow="sm" className={styles.fadeIn}>...</Box>
すべてのクラス名を排除できたら、import を完全に削除します。
styled-components / @emotion/styled から — 同等のスタイルプロパティを持つ Box にマッピングし、その後 import を削除し、他で使われなくなっていればアンインストールします:
// Before
const Card = styled.div`padding: 1rem; &:hover { background: #f3f4f6; }`
// After
<Box p={4} _hover={{ bg: "bg.muted" }} />
既存の Chakra UI から(クリーンアップ)
Box > Box > Boxのネストを平坦化し、すべての子のmt/mbをStack gap={N}に置き換えますsxをcssに置き換え(v3 でのリネーム)、その内部のネストされた&:hoverセレクターを更新しますbg="gray.50"→bg="bg.subtle"やその他のセマンティックトークンの同等物に置き換えます- v2 のプロパティ名を更新します:
isDisabled→disabled、colorScheme→colorPalette、spacing→gap - 複合コンポーネントを更新します:
FormControl→Field.Root、Modal→Dialog、Select→NativeSelect
動作を保持する — 譲れない条件
- すべてのイベントハンドラー、状態変数、条件付きレンダリングをそのまま維持します
aria-*属性を維持し、明らかに必要な場合は不足しているものを追加します- セマンティック HTML の意図を維持します(
<nav>→ 単なるBoxではなくBox as="nav") "use client"が存在する場合は維持し、コンポーネントが本当に必要とする場合のみ追加します- コンポーネントが Chakra UI を使っているというだけの理由で
"use client"を追加しないでください - 動作する部分的に変換されたコンポーネントは、動作しない完全に変換されたコンポーネントより優れています
Next.js の Link と Image に対する asChild
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/about">About</NextLink></ChakraLink>
import NextImage from "next/image"
<ChakraImage asChild><NextImage src="/hero.png" alt="Hero" width={800} height={400} /></ChakraImage>
リファクタリング出力フォーマット
1. リファクタリング済みコード — 完全で実行可能、正しいインポート付き
2. 変更点 — 自明でない判断に焦点を当てた簡潔なリスト:
- Replaced <div className="flex gap-4"> with <Flex gap={4}>
- Replaced bg="#f9fafb" with bg="bg.subtle" for dark mode compatibility
- Kept form submit handler and validation logic unchanged
- Added aria-label to close icon button (was missing)
3. 提案 (任意) — このリファクタリングを超えた有意義な改善: 再利用可能なコンポーネントの抽出、レシピの採用、v2 パターンへの移行。
質問すべき場合と進めるべき場合
コードと意図が明確であれば進めてください。次の場合は質問してください:
- コードがまだ共有されていない
- コンポーネントが非常に大きく、スコープが不明確である
- レビューを変える可能性のある、確認できないコンテキストや状態がある
- 複数の解釈が可能な曖昧な動作がある
質問せずに進める場合は、回答の冒頭に前提を明記してください。