主题化组件系统 · 新资源

Chakra UI 设计系统.

Chakra UI v3 参考资料,涵盖设计令牌、语义颜色角色、配方和复合表单组件。查看实际的间距与字体比例,然后尝试使用原生组件构建工作区个人资料表单,其中包含验证、保存失败模拟以及浅色/深色外观。

OpenDesign 指南9 个章节47 条参考内容原始应用指南
01

Chakra UI 设计系统界面预览

试用空字段验证、模拟保存失败、保留输入内容、本地成功确认和外观切换。

原生 Chakra 工作区配置打开完整示例
原生 Chakra UI 3.37.0,搭配 React 19;自包含包。完整展示自定义应用语义令牌和配方。rem 值基于根字体大小;像素换算假设根字体大小为 16px。· 实现参考
02

Chakra UI 设计系统设计参考

Chakra UI 3.37.0 默认主题参考,以及明确标注的 OpenDesign 应用令牌。rem 值遵循根字体大小;像素换算假设为 16px。这是经过筛选的实用参考,并非完整导出的主题。

默认语义颜色

来源
名称 / 规则值 / 配置用途
bgwhite / black浅色 / 深色页面画布。
bg.panelwhite / gray.950浅色 / 深色卡片表面。
bg.subtlegray.50 / gray.950克制的表面。
fgblack / gray.50主文本。
fg.mutedgray.600 / gray.400辅助性文本。
bordergray.200 / gray.800面板与控件边界。
fg.errorred.500 / red.400错误文本。
bg.errorred.50 / red.950错误表面。
teal.fgteal.700 / teal.300青绿色微妙表面上的文本。
teal.subtleteal.100 / teal.900当前步骤的样式。

本示例使用的原始值

来源
名称 / 规则值 / 配置用途
gray.50#fafafa 浅色画布。
gray.200#e4e4e7 浅色边框。
gray.800#27272a 深色边框。
gray.950#111111 深色画布。
teal.700#0c5d56 自定义浅色操作使用此值。
teal.300#5eead4 自定义深色操作使用此值。

默认间距子集

来源
名称 / 规则值 / 配置用途
spacing.10.25rem / 4px状态提示的垂直内边距。
spacing.20.5rem / 8px行内控件间距。
spacing.30.75rem / 12px操作组间距。
spacing.41rem / 16px小视口内边距。
spacing.61.5rem / 24px表单字段间距。
spacing.82rem / 32px主要布局间距。
spacing.102.5rem / 40px可用的较大间距。
spacing.123rem / 48px可用的区块间距。

默认排版子集

来源
名称 / 规则值 / 配置用途
fonts.body / fonts.headingInter, system fallbacks字体令牌本身不会下载 Inter。
fontSizes.xs0.75rem示例注释。
fontSizes.sm0.875rem辅助文本。
fontSizes.md1rem输入内容与常规阅读文本。
fontSizes.lg1.125rem可用的较大正文样式。
fontSizes.xl1.25rem卡片标题。
fontSizes.2xl1.5rem示例标题。
fontWeights.medium / semibold500 / 600标签层级。
lineHeights.shorter / moderate1.25 / 1.5标题 / 段落节奏。
letterSpacings.wide0.025em小号眉题。

默认圆角

来源
名称 / 规则值 / 配置用途
radii.sm0.25rem / 4px紧凑边缘。
radii.md0.375rem / 6px本示例中的状态标签。
radii.lg0.5rem / 8px适中圆角。
radii.xl0.75rem / 12px本示例中的配置卡片。
radii.full9999px胶囊形状,本表单未使用。

默认响应式断点

来源
名称 / 规则值 / 配置用途
sm480px操作行可切换为横向布局。
md768px进度栏位于表单旁。
lg1024px可用的宽屏布局断点。
xl1280px可用的桌面端断点。
2xl1536px可用的超宽屏断点。

应用语义令牌:定义如下

来源
名称 / 规则值 / 配置用途
workspace.canvasgray.50 / gray.950自定义浅色 / 深色画布映射。
workspace.actionbrand.700 / brand.300自定义操作背景;品牌原始颜色定义在 theme.js 中。
workspace.onActionwhite / gray.950与背景搭配的自定义操作文本颜色。
03

Chakra UI 设计系统完整指南

实用指南,介绍如何为真实界面选择、应用和评审此系统。

DESIGN-chakra-ui.md

完整指导、实现起点和源代码链接。

下载指南

Chakra UI 设计系统:v3 系统——配置、令牌与组件

构建系统,而不是传入旧版主题对象

实现分为三层:theme.js 定义设计决策,main.jsx 提供生成的系统,App.jsx 组合表单。createSystem(defaultConfig, config) 会保留默认组件配方,同时合并应用配置。若使用完全自定义的系统,则需要补充更多定义;这里特意选择扩展默认配置。

摘自本 OpenDesign 指南

预览使用的是 Chakra 组件,而非绘制出来的替代品。侧边栏是应用专用的有序进度列表,并不表示已挂载 Chakra Steps 组件。配置卡片、字段、选择框、提示框和按钮均由原生 Chakra 组件组合而成。

阅读配套规范

各层分别包含什么

  • tokens:可复用的原始值,包括本示例中的两种品牌色。
  • semanticTokens:根据条件变化的角色,例如 workspace.action,不依赖于具体屏幕。
  • recipes:可复用的组件变体;应用的 React 状态决定表单处于无效、待处理、失败还是已确认状态。

Chakra UI 设计系统原始颜色与语义主题角色

外观会变化时使用角色

bg.panel 和 fg.muted 表达界面表面和文本的用途;gray.950 和 gray.400 是对应的底层值。参考表展示了它们在浅色和深色模式下的解析结果。在演示中,将文档根节点在浅色与深色模式间切换,即可启用相应的条件值,无需逐个重写 Field 或 Card。此处的本地切换不会保存设置,也不会与系统偏好集成。

workspace.* 角色是应用自定义项。它们会在浅色界面表面上使用深青色操作色,在深色界面表面上使用浅青色操作色,并搭配相应的文本颜色。这些不是 Chakra 官方的令牌名称。将这组颜色放在主题中,可以避免深色模式按钮只更改背景、标签却仍为白色的情况。

阅读配套规范

令牌引用语法不同于组件简写

在令牌定义中,使用完整引用 {colors.gray.950}。在样式属性中,bg="workspace.canvas" 会在 color 类别中解析。在组合的 CSS 值中,则需要再次使用完整的令牌路径。区分这两种写法可以避免将普通字符串误认为主题引用。

jsx
<Box bg="workspace.canvas" color="fg" border="1px solid {colors.gray.200}" p="4" />

代码参考

Chakra UI 设计系统:使用明确令牌构建易读的字号阶梯

将字号阶梯映射到此布局

标题使用 fontSize="2xl" 和 lineHeight="shorter";卡片标题使用 xl;辅助文本使用 sm;示例标注使用 xs。这些选择形成了层级,同时不改变语义标题级别:屏幕标题是 h1,表单标题是 h2。普通表单内容仍使用默认正文尺寸。

Chakra 默认的正文和标题字体栈以 Inter 开头,并回退到平台字体。此独立演示不会请求外部字体,因此渲染时使用的回退字体可能因操作系统而异。如果需要精确的排版效果,请在本地提供已获得适当授权的字体;仅设置字体令牌并不会提供字体文件。

阅读配套规范

让排版与含义彼此独立

当前步骤标签是紧凑的元信息,不是主要指引。必填和无效状态提示仍放在字段旁边,并保持易读的字号。调整眉题的字间距不会改变表单标签;较长的工作区名称也会保留在输入框内,不会改变周围卡片的宽度。

Chakra UI 设计系统:组合 Field、NativeSelect、Card 和 Alert

Field 表达的是关联关系,而不只是带样式的输入框

Field.Root 将标签、控件、辅助文本和错误信息组合在一起。必填标记和 RequiredIndicator 用于说明必填要求;invalid 用于控制错误状态。示例通过 React 控制输入值,并将工作区名称的错误信息放在 Field.ErrorText 中。它不会在脱离表单的段落上单独设置错误样式。

团队规模使用 NativeSelect.Root、NativeSelect.Field 和 NativeSelect.Indicator。对于固定且选项较少的选项集,这种方式保留了原生选择控件的行为。它不会伪装成支持搜索远程结果的控件;那需要使用不同的控件和数据交互方式。

阅读配套规范

反馈使用独立的组合结构

阅读配套规范

Chakra UI 设计系统:应用间距令牌和响应式样式属性

明确的间距规范

字段组之间使用 gap="6",操作项之间使用 gap="3",进度栏与表单之间使用 gap="8"。页面的内边距会在 md 断点处从 p="4" 调整为 p="8"。根字号为 16px 时,这些值分别对应 24px、12px、32px、16px 和 32px。以 rem 为单位的值会随用户的根字号缩放。

卡片使用 rounded="xl",状态标签使用 rounded="md"。两者的圆角不同是有意为之:大型容器和紧凑标签的几何形态不同。不要将这些用法视为所有 Chakra 应用都必须遵循的默认规则。

阅读配套规范

在 md 断点处调整布局

低于 md 断点时,网格为单列;从 md 断点开始,进度栏占 220px,表单则占据剩余弹性空间。minmax(0, 1fr) 允许表单在网格中收缩。操作项堆叠方式会在 sm 断点处改变。这些对象值是移动优先的覆盖规则,不是设备检测。

jsx
<Grid templateColumns={{ base: "1fr", md: "220px minmax(0, 1fr)" }} gap="8">
  <Box as="nav" aria-label="Setup progress">…</Box>
  <Card.Root rounded="xl">…</Card.Root>
</Grid>

代码参考

Chakra UI 设计系统:连接验证、加载和恢复状态

预览状态机

提交去除首尾空格后为空的名称时,会设置 invalid 并将焦点移至输入框。提交有效内容后,会进入 pending 状态、禁用编辑,并显示 Button loadingText。本地计时器结束后,由失败模拟复选框决定演示显示 failed 还是 complete。两个分支都不会发出网络请求或保存数据。

失败后,受控的名称和所选规模会保留。关闭失败模拟后即可重试。完成后,个人资料字段会被禁用,首个进度标签也会更新;重置则会返回编辑状态。这展示的是可见状态的组合,而不是后端保存契约。

阅读配套规范

按顺序试用各状态

  1. 重置表单,然后不填写名称直接提交;查看字段提示以及获得焦点的输入框。
  2. 输入名称,启用保存失败模拟后提交;确认出错后输入值仍然保留。
  3. 关闭失败模拟并再次提交;查看已确认的摘要,然后切换外观。

Chakra UI 设计系统:组合控件时保留原生语义

验证和进度信息保持清晰易懂

表单使用 noValidate,让此示例展示自定义的 Field 错误处理流程,而不是停在浏览器的验证界面。标签仍通过 Field 与控件关联,第一个无效输入框会获得焦点。待处理操作通过实时状态区域说明,而不是只用旋转图标传达。

进度列表使用有序列表语义,并在当前项上设置 aria-current="step"。它不会为无法访问的屏幕添加虚假的链接。预览中的第二步和第三步仅用于说明上下文,不可点击。这样可以清楚呈现演示的范围限制。

阅读配套规范

焦点状态是自定义操作配方的一部分

此引导流程变体为 focus-visible 明确设置了带偏移量的轮廓。在深色外观下,轮廓角色会与操作角色一同变化。原生复选框和选择框仍可通过键盘操作。在实际应用中,也请检查焦点状态、字段播报、缩放和屏幕阅读器输出;单个组件示例无法证明整个引导产品都具备无障碍性。

Chakra UI 设计系统配方、Provider 接线与版本边界

扩展 Button;在本地定义 Status

引导流程的 Button 变体添加在 theme.recipes.button 下。由于配置扩展了 defaultConfig,outline 等现有变体仍然可用。状态标签使用 defineRecipe 和 useRecipe 在本地定义:其状态变体将 current、complete 和 waiting 映射到不同的语义角色。这是应用组件,并非 Chakra 导出项。

单元素配方会返回一个样式对象。Field 等多部分组件包含多个插槽,如果要为其各部分统一设置主题,就需要使用插槽配方。将类似按钮的配方应用到整个 Field,无法分别控制其标签、控件和错误提示。

阅读配套规范

配套使用提供的文件

不要导入 v2 的 extendTheme 设置,也不要向此 v3 provider 传入 theme={...}。实际根组件使用 ChakraProvider value={system}。本示例有意不添加第二个色彩模式 provider:对于这个独立预览,本地浅色/深色类切换已足够;实际应用则可能需要持久化偏好设置和服务端渲染支持。

阅读配套规范

Chakra UI 设计系统:同时验证主题与表单

此示例验证的内容

有意义的审查单元,是同时涵盖两种外观的完整个人资料卡片:标签、输入框、辅助文本、无效状态反馈、待处理按钮、失败警告和成功摘要。单独查看按钮,无法发现语义背景缺失,或控件错误状态与标签未关联等问题。

将参考表与实际渲染的界面进行对比。自定义青绿色操作按钮应与默认轮廓按钮有所区别;间距 6 应用于分隔字段;视口宽度低于 md 时,网格应变为单列。这些检查能将书面规则与渲染结果对应起来。

示例未涵盖的内容

此预览不包含账户创建、邀请发送、数据持久化、身份验证,也未与其他引导屏幕集成。计时器明确只是模拟。接入真实端点时,请保留示例中的字段状态与请求状态区分,用实际请求替代计时器,并明确完成状态代表本地已接受、远程已保存,还是已全部激活。

Chakra UI 设计系统组件示例

theme.js — 基础令牌、语义角色与配方

此示例使用的完整应用主题。工作区角色和引导流程变体为新增内容;defaultConfig 提供 Chakra 的标准主题。

javascript
import { createSystem, defaultConfig, defineConfig, defineRecipe } from '@chakra-ui/react';

export const statusRecipe = defineRecipe({
  base: { display: 'inline-flex', px: '2', py: '1', rounded: 'md', fontSize: 'xs', fontWeight: 'semibold' },
  variants: {
    state: {
      current: { bg: 'teal.subtle', color: 'teal.fg' },
      complete: { bg: 'bg.success', color: 'fg.success' },
      waiting: { bg: 'bg.muted', color: 'fg.muted' },
    },
  },
  defaultVariants: { state: 'waiting' },
});

const config = defineConfig({
  theme: {
    tokens: { colors: { brand: { 700: { value: '#0c5d56' }, 300: { value: '#5eead4' } } } },
    semanticTokens: { colors: {
      'workspace.canvas': { value: { base: '{colors.gray.50}', _dark: '{colors.gray.950}' } },
      'workspace.action': { value: { base: '{colors.brand.700}', _dark: '{colors.brand.300}' } },
      'workspace.onAction': { value: { base: '{colors.white}', _dark: '{colors.gray.950}' } },
    } },
    recipes: {
      button: defineRecipe({ variants: { variant: {
        onboarding: {
          bg: 'workspace.action', color: 'workspace.onAction',
          _hover: { opacity: 0.9 },
          _focusVisible: { outline: '2px solid', outlineColor: 'workspace.action', outlineOffset: '2px' },
        },
      } } }),
    },
  },
});
export const system = createSystem(defaultConfig, config);

代码参考

  • 品牌色值有意与参考中的青绿色基础色值保持一致。
  • 状态配方在本地定义;Button 变体已在系统中注册。

App.jsx — 完整的原生表单与状态示例

预览所用的实际 React 组合。包含主题切换、Field 验证、原生选择框、待处理反馈、模拟失败、确认和重置。

jsx
import React, { useEffect, useRef, useState } from 'react';
import { Box, Button, Card, Field, Grid, Heading, Input, NativeSelect, Stack, Text, Alert, chakra, useRecipe } from '@chakra-ui/react';
import { statusRecipe } from './theme';

function Status({ state, children }) {
  const recipe = useRecipe({ recipe: statusRecipe });
  return <chakra.span css={recipe({ state })}>{children}</chakra.span>;
}

export default function App() {
  const [dark, setDark] = useState(false);
  useEffect(() => { document.documentElement.className = dark ? 'dark' : 'light'; }, [dark]);
  const [name, setName] = useState('Northstar Studio');
  const [size, setSize] = useState('2–10');
  const [invalid, setInvalid] = useState(false);
  const [phase, setPhase] = useState('editing');
  const [simulateFailure, setSimulateFailure] = useState(false);
  const nameInput = useRef(null);
  const pending = phase === 'pending';
  const complete = phase === 'complete';
  const save = (event) => {
    event.preventDefault();
    if (!name.trim()) { setInvalid(true); nameInput.current?.focus(); return; }
    setInvalid(false); setPhase('pending');
    window.setTimeout(() => setPhase(simulateFailure ? 'failed' : 'complete'), 600);
  };
  return <Box className={dark ? 'dark' : 'light'} bg='workspace.canvas' color='fg' p={{ base: '4', md: '8' }}>
    <Box maxW='960px' mx='auto'>
      <Stack direction={{ base: 'column', sm: 'row' }} justify='space-between' align={{ base: 'stretch', sm: 'center' }} gap='4' mb='8'>
        <Box><Text fontSize='xs' fontWeight='semibold' color='teal.fg' letterSpacing='wide'>CHAKRA UI · NATIVE SPECIMEN</Text><Heading as='h1' fontSize='2xl' lineHeight='shorter' mt='2'>Set up your workspace</Heading></Box>
        <Button variant='outline' size='sm' onClick={() => setDark(!dark)} aria-pressed={dark}> {dark ? 'Light appearance' : 'Dark appearance'} </Button>
      </Stack>
      <Grid templateColumns={{ base: '1fr', md: '220px minmax(0, 1fr)' }} gap='8'>
        <Box as='nav' aria-label='Setup progress'>
          <Stack as='ol' gap='6' listStyleType='none' m='0' p='0'>
            <Box as='li' aria-current={complete ? undefined : 'step'}><Status state={complete ? 'complete' : 'current'}>{complete ? 'Complete' : 'Current'}</Status><Text fontWeight='semibold' mt='2'>1. Workspace profile</Text><Text fontSize='sm' color='fg.muted'>Name and team size</Text></Box>
            <Box as='li'><Status state='waiting'>Next</Status><Text fontWeight='medium' mt='2'>2. Invite your team</Text><Text fontSize='sm' color='fg.muted'>Available in the full product</Text></Box>
            <Box as='li'><Status state='waiting'>Optional</Status><Text fontWeight='medium' mt='2'>3. Connect tools</Text><Text fontSize='sm' color='fg.muted'>Complete this later</Text></Box>
          </Stack>
          <Box mt='8' borderTopWidth='1px' borderColor='border' pt='4'><Text fontSize='xs' color='fg.muted'>Scale in this specimen</Text><Text fontSize='sm' mt='2'>Field gap 6 · Card padding 6<br/>Page gap 8 · Radius xl</Text></Box>
        </Box>
        <Card.Root bg='bg.panel' borderColor='border' rounded='xl'>
          <Card.Header><Heading as='h2' fontSize='xl'>Workspace profile</Heading><Text color='fg.muted' fontSize='sm'>The name appears on your team's workspace.</Text></Card.Header>
          <Card.Body>
            <form onSubmit={save} noValidate>
              <Stack gap='6'>
                <Field.Root required invalid={invalid} disabled={pending || complete}>
                  <Field.Label>Workspace name <Field.RequiredIndicator /></Field.Label>
                  <Input ref={nameInput} value={name} onChange={e => {setName(e.target.value);setInvalid(false);}} autoComplete='organization' />
                  <Field.HelperText>Use a name your teammates will recognize.</Field.HelperText>
                  <Field.ErrorText>Enter a workspace name.</Field.ErrorText>
                </Field.Root>
                <Field.Root disabled={pending || complete}>
                  <Field.Label>Team size</Field.Label>
                  <NativeSelect.Root><NativeSelect.Field value={size} onChange={e => setSize(e.target.value)}><option>Just me</option><option>2–10</option><option>11–50</option><option>51+</option></NativeSelect.Field><NativeSelect.Indicator /></NativeSelect.Root>
                  <Field.HelperText>Used only for this local preview summary.</Field.HelperText>
                </Field.Root>
                <Box><label style={{display:'flex',gap:'8px',alignItems:'center',fontSize:'14px'}}><input type='checkbox' checked={simulateFailure} disabled={pending || complete} onChange={e=>setSimulateFailure(e.target.checked)} />Simulate a failed save</label></Box>
                {phase === 'failed' && <Alert.Root status='error'><Alert.Indicator /><Alert.Content><Alert.Title>Demo save failed</Alert.Title><Alert.Description>Your values are still here. Turn off failure simulation and retry.</Alert.Description></Alert.Content></Alert.Root>}
                {complete && <Alert.Root status='success'><Alert.Indicator /><Alert.Content><Alert.Title>Profile confirmed in this preview</Alert.Title><Alert.Description>{name.trim()} · {size} people. Nothing was sent or stored.</Alert.Description></Alert.Content></Alert.Root>}
                <Stack direction={{base:'column',sm:'row'}} gap='3'>
                  <Button type='submit' variant='onboarding' loading={pending} loadingText='Checking profile' disabled={complete}>Confirm profile</Button>
                  <Button type='button' variant='outline' disabled={pending} onClick={()=>{setPhase('editing');setInvalid(false);setName('');setSize('2–10');setSimulateFailure(false);nameInput.current?.focus();}}>Reset example</Button>
                </Stack>
                <Text role='status' aria-live='polite' fontSize='sm' color='fg.muted'>{pending ? 'Simulating a response. No network request is made.' : complete ? 'Profile step complete. Reset to try another state.' : 'Try an empty name, a failed save, or a different appearance.'}</Text>
              </Stack>
            </form>
          </Card.Body>
        </Card.Root>
      </Grid>
      <Text mt='6' fontSize='xs' color='fg.muted'>Actual Chakra UI 3.37.0 components. Custom workspace semantic tokens and button recipe. Memory-only demonstration.</Text>
    </Box>
  </Box>;
}

代码参考

  • 不会发送请求;600ms 延迟仅用于演示待处理界面。
  • 后续步骤只是说明上下文的标签,并非可用的导航。
04

Chakra UI 设计系统 Agent 设置

实现起点

使用所安装的 Vite 和 Chakra 版本支持的 Node.js(Chakra 文档要求 Node 20 或更高版本)。此代码块将终端命令与 src/main.jsx 分开。上文已提供完整的主题和 App 文件;无需隐藏的 provider 代码片段或外部 CSS。

文本
# Terminal: create a JavaScript React application
npm create vite@latest chakra-profile -- --template react
cd chakra-profile
npm install
npm install @chakra-ui/[email protected] @emotion/react

# Save the two complete examples as src/theme.js and src/App.jsx.
# Replace src/main.jsx with:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { ChakraProvider } from '@chakra-ui/react';
import { system } from './theme';
import App from './App';
createRoot(document.getElementById('root')).render(<ChakraProvider value={system}><App /></ChakraProvider>);

# Start from the project directory:
npm run dev

适用于你项目的提示词

Agent 提示词
使用 Chakra UI 3.37.0,并以提供的 theme.js 和 App.jsx 为起点。保留工作区语义角色、Field 组合、原生选择框,以及无效输入与提交失败之间的区分。仅将模拟计时器替换为实际持久化 API;在确认结果之前,不要标记个人资料已完成。保留键盘焦点、响应式 base/md 布局以及浅色/深色模式的值。说明任何新增的令牌或配方变体。
05

Chakra UI 设计系统的来源与范围

基于有文档说明的 Chakra UI v3 基础功能编写的原创 OpenDesign 实现指南。默认令牌引用与应用专属的工作区角色分开。原生预览仅演示本地状态;它不会保存工作区数据,也不会实现完整的引导流程。