Communitygithub.com

0xAlchemist-cs/personal-ui-system

使用 Chakra UI v3 建置易於存取、符合無障礙標準的 UI 元件與版面,並協助在新專案或既有專案中安裝或設定 Chakra UI,以及設計可擴展的主題。

personal-ui-system 是什麼?

這個技能專為使用 Chakra UI v3 的開發者設計,能夠自動偵測專案環境(框架、套件管理器、TypeScript/JavaScript),並生成符合專案慣例的程式碼。它涵蓋從安裝、提供者設定、到建立響應式元件(如按鈕、表單、圖表、導覽列)的完整工作流程。技能內建詳細指南,包括使用語意型 tokens 實現深色模式、使用 recipes/slot recipes 進行主題客製化、Next.js 的 'use client' 最佳實踐,以及透過 @chakra-ui/cli 自動產生程式碼片段。對於圖表需求,它會參考 charts.md 文件,並使用 useChart hook 整合 Recharts。此技能旨在減少樣板程式碼、提升開發效率,並確保最終產出可維護且符合無障礙標準。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/0xAlchemist-cs/personal-ui-system/tree/HEAD/.agents/skills/chakra-ui-builder

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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 Reactsrc/components/ui/
Remixapp/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 GridGrid + 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 元件,並針對何時選擇某個元件而非類似替代品提供了指引。


輸出格式

請產生:

  1. 完整、可執行的程式碼 — 正確的匯入、無 TODO 或 ...rest of component 這類佔位符
  2. 正確的匯入陳述 — 先分組 Chakra 匯入,再放本地匯入
  3. 元件分離 — 如果元件複雜或包含可明確分離的部分,請拆分成多個元件/檔案
  4. 響應式樣式 — 版面至少要有 base 和 md 中斷點
  5. 程式碼後的簡短說明 — 2–4 句說明所做的關鍵決策(版面方法、無障礙選擇、響應式策略)。如果需求很簡單,則省略說明。
// 良好的匯入風格
import { Box, Button, Field, Stack, Text } from "@chakra-ui/react"
// 然後是本地匯入
import { SomeLocalComponent } from "./SomeLocalComponent"

何時先提問

如果需求足夠明確以產出有用的內容,請立即建置。當以下情況時,先提問:

  • 資料形狀未知且會改變整體結構(例如「建立一個表格」— 多少欄?什麼資料?)
  • 存在使用者可能關心的重大設計選擇(版面方向、欄數、色板)
  • 使用者引用你尚未看過的檔案或現有元件

若有疑慮,請在回應開頭列出你的假設,然後進行建置 — 讓使用者從具體的成果而非空白開始,調整會更快。

相關技能