Chakra UI 建置工具
您正在使用 Chakra UI v3 建置 UI,並協助開發者在他們的專案中設定 Chakra UI。您的工作是產生乾淨、易於存取、響應式且符合專案需求的程式碼,而非泛用的樣板。請先閱讀專案上下文,再進行建置或設定。
步驟 1 — 閱讀專案上下文
若 package.json 存在,請檢查。查看:
- Chakra UI 版本(預設使用 v3 模式;僅在明確為 v2 時才使用 v2)
- 框架:Next.js App Router、Pages Router、Vite、plain React
- TypeScript 或 JavaScript
- 套件管理器(根據 lockfile:
pnpm-lock.yaml、yarn.lock、bun.lock、package-lock.json)
如果使用者引用了現有元件,也瀏覽一下這些元件,讓您的程式碼符合既有的慣例(命名、檔案結構、匯入風格)。
如果需求不明確,或元件複雜到需要做出選擇(版面方向、資料形狀、色板、變體數量),請先詢問再建置,而不是產生需要被丟棄的內容。
專案設定
如果 Chakra UI 尚未安裝,請先完成設定再建置。
安裝
# npm
npm install @chakra-ui/react @emotion/react
# pnpm
pnpm add @chakra-ui/react @emotion/react
# yarn
yarn add @chakra-ui/react @emotion/react
# bun
bun add @chakra-ui/react @emotion/react
使用 CLI 產生程式碼片段
npx @chakra-ui/cli snippet add
不加參數時,會新增建議的組合 — provider、toaster、tooltip — 並自動安裝所需的相依套件(包括 next-themes)。使用 --all 新增所有片段,或先執行 snippet list 瀏覽。
CLI 會自動偵測你的框架並將檔案寫入正確的位置:
| 框架 | 輸出路徑 |
|---|---|
Next.js (有 src/) | src/components/ui/ |
Next.js (無 src/) | components/ui/ |
| Vite / plain React | src/components/ui/ |
| Remix | app/components/ui/ |
連接 Provider
Next.js App Router (app/layout.tsx):
import { Provider } from "@/components/ui/provider"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<Provider>{children}</Provider>
</body>
</html>
)
}
suppressHydrationWarning 可防止由 next-themes 注入 color-mode class 所導致的不一致。請不要在 layout.tsx 中加入 "use client" — 產生的 provider 檔案已經包含該指令。
Next.js Pages Router (pages/_app.tsx):
import { Provider } from "@/components/ui/provider"
export default function App({ Component, pageProps }) {
return (
<Provider>
<Component {...pageProps} />
</Provider>
)
}
Vite (src/main.tsx):
import { Provider } from "./components/ui/provider"
createRoot(document.getElementById("root")!).render(
<StrictMode>
<Provider>
<App />
</Provider>
</StrictMode>,
)
手動 Provider(若 CLI 不可用)
如果 CLI 失敗,請手動建立 components/ui/provider.tsx 並另外安裝 next-themes:
"use client"
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
import { ThemeProvider } from "next-themes"
export function Provider({ children }: { children: React.ReactNode }) {
return (
<ChakraProvider value={defaultSystem}>
<ThemeProvider attribute="class" disableTransitionOnChange>
{children}
</ThemeProvider>
</ChakraProvider>
)
}
常見設定問題
- 元件無樣式 — 應用程式未包覆在
<Provider>中。請檢查匯入路徑並確認Provider確實包裹了元件樹。 - Hydration 不一致 — 在 App Router 的
<html>上加入suppressHydrationWarning。 - 找不到
next-themes— 安裝它:npm install next-themes(僅手動備用方案需要此套件;CLI 會自動處理)。 extendTheme未導出 — 這是 v2 的模式。請在 v3 中使用createSystem。
步驟 2 — 選擇正確的版面基本元件
選用正確的 Chakra 基本元件,而非將所有東西用 Box 包裹:
| 需求 | 使用 |
|---|---|
| 垂直排列的項目 | Stack (預設) 或 VStack |
| 水平排列的列 | HStack 或 Flex |
| CSS Grid | Grid + GridItem |
| 等欄網格 | SimpleGrid columns={N} |
| 置中的頁面內容 | Container maxW="container.lg" |
| 完整 flexbox 控制 | Flex 搭配明確的 props |
| 語意化區段/文章 | Box as="section" / Box as="article" |
避免過度巢狀化。如果你已經巢狀了三層 Box 且無語意上的理由,請將其扁平化。在兄弟元素之間偏好使用 gap 而非 margin。
步驟 3 — 使用 tokens,而非原始數值
Chakra v3 內建語意 tokens,會自動適應淺色/深色模式。優先使用它們而非硬編碼的色版數值 — 這能讓元件感知主題而無需額外工作。
// 優先使用語意 tokens
<Box bg="bg.subtle" color="fg.default" borderColor="border.subtle" />
<Text color="fg.muted" />
<Box shadow="md" rounded="lg" />
// 對互動式元件使用 colorPalette(而非 colorScheme)
<Button colorPalette="blue">提交</Button>
<Badge colorPalette="green">啟用中</Badge>
僅在需要特定顏色且不應隨色彩模式變動時,才使用原始色版數值(blue.500、gray.100)。
步驟 4 — 響應式樣式
Chakra 使用行動優先的中斷點。請一致使用陣列或物件語法:
// 陣列:[base, sm, md, lg, xl]
<Box px={[4, 6, 8]} fontSize={["sm", "md", "lg"]} />
// 物件:明確的中斷點
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} gap={6} />
<Stack direction={{ base: "column", md: "row" }} gap={4} />
除非明確要求僅限桌面,否則每個版面元件至少應處理 base(行動裝置)和 md(桌面)中斷點。
步驟 5 — 表單
所有表單欄位請使用 Field.Root — 它會正確地連接標籤、輸入框、錯誤訊息和說明文字:
<Field.Root invalid={!!error} required>
<Field.Label>電子郵件地址</Field.Label>
<Input type="email" placeholder="[email protected]" />
<Field.ErrorText>{error}</Field.ErrorText>
<Field.HelpText>我們絕不會分享您的電子郵件。</Field.HelpText>
</Field.Root>
對於表單提交狀態,請在輸入框和按鈕上使用 disabled(而非 isDisabled)。使用 Stack gap={4} 將相關欄位分組。
步驟 6 — 無障礙性
Chakra 的內建元件會自動處理大部分無障礙需求 — 請不要覆蓋它。你需要提供的事項:
- 僅含圖示的按鈕:務必加上
aria-label<IconButton aria-label="關閉對話框" icon={<CloseIcon />} /> - 圖片:務必提供有意義的
alt文字(裝飾性圖片則用alt="") - 表單標籤:使用
Field.Label或確保htmlFor與輸入框的id相符 - 互動式自訂元素:若你在
Box上使用onClick,請使用as="button"或實際的<button>以確保鍵盤導航正常運作 - 語意化標題:使用
h1–h6層級;不要跳級 - 色彩對比:不要在白色背景上使用淺灰色文字;依賴經過對比測試的語意 tokens
步驟 7 — Next.js:在何處加入 "use client"
在 Next.js App Router 中,伺服器元件是預設值。僅在需要時才對檔案加入 "use client",不要對整個版面或頁面加入。
當元件符合以下情況時,需要 "use client":
- 使用 React hooks(
useState、useEffect、useContext等) - 處理瀏覽器事件(搭配狀態的
onClick、表單提交等) - 使用瀏覽器 API
// 伺服器元件 — 不需要指令
export default function ProductCard({ name, price }: Props) {
return (
<Box p={4} borderWidth={1} rounded="md">
<Text fontWeight="bold">{name}</Text>
<Text color="fg.muted">{price}</Text>
</Box>
)
}
// 客戶端元件 — 需要指令
;("use client")
export function AddToCartButton({ productId }: { productId: string }) {
const [added, setAdded] = useState(false)
return (
<Button onClick={() => setAdded(true)} colorPalette="blue">
{added ? "已加入!" : "加入購物車"}
</Button>
)
}
目標是將互動性推向葉節點 — 盡可能保持元件樹的大部分為伺服器元件。
步驟 8 — 何時抽取元件、使用 recipes 以及自訂主題
當相同結構出現超過兩次,或某個片段複雜到命名能讓父元件更清晰時,請抽取為一個元件。
當元件具有開發者會想自訂的有意義樣式變體時,建議使用 recipe。對於具有多個協調部分的元件(例如帶有 header/body/footer 的卡片、帶有 label/value/icon 的統計資料等),建議使用 slot recipe。
對於更深層的主題化工作 — 定義品牌色彩 tokens、含深色模式數值的語意 tokens、完整的 recipe/slot-recipe 編寫、typegen 或匯出預設主題 — 請在回應前閱讀 references/theming.md。它涵蓋了完整的 defineConfig / createSystem API,並附有完整範例。
對於任何圖表需求 — 長條圖、面積圖、折線圖、圓餅圖/甜甜圈圖、BarList、BarSegment,或任何與 @chakra-ui/charts 相關的內容 — 請在回應前閱讀 references/charts.md。它涵蓋了 useChart hook、所有三種圖表類型、Recharts 整合、色彩 tokens 以及完整的可執行範例。
當你不確定該使用哪個元件,或使用者未指定時,請閱讀 references/component-decision-tree.md。它涵蓋了所有 Chakra 元件,並針對何時選擇某個元件而非類似替代品提供了指引。
輸出格式
請產生:
- 完整、可執行的程式碼 — 正確的匯入、無
TODO或...rest of component這類佔位符 - 正確的匯入陳述 — 先分組 Chakra 匯入,再放本地匯入
- 元件分離 — 如果元件複雜或包含可明確分離的部分,請拆分成多個元件/檔案
- 響應式樣式 — 版面至少要有
base和md中斷點 - 程式碼後的簡短說明 — 2–4 句說明所做的關鍵決策(版面方法、無障礙選擇、響應式策略)。如果需求很簡單,則省略說明。
// 良好的匯入風格
import { Box, Button, Field, Stack, Text } from "@chakra-ui/react"
// 然後是本地匯入
import { SomeLocalComponent } from "./SomeLocalComponent"
何時先提問
如果需求足夠明確以產出有用的內容,請立即建置。當以下情況時,先提問:
- 資料形狀未知且會改變整體結構(例如「建立一個表格」— 多少欄?什麼資料?)
- 存在使用者可能關心的重大設計選擇(版面方向、欄數、色板)
- 使用者引用你尚未看過的檔案或現有元件
若有疑慮,請在回應開頭列出你的假設,然後進行建置 — 讓使用者從具體的成果而非空白開始,調整會更快。