Better Admin LogoBetter Admin
设计

UI 规范与 Design Tokens

设计基准、组件库优先级、色板与圆角档位,以及跨端的视觉一致规则。

四端各用各的组件库,但最终产品必须长得像同一套系统。这一页说明约束从哪来、Token 长什么样、哪些做法被明确禁止。

设计基准:React 是唯一的 UI 真源

页面结构、组件行为、交互、UX、Design Tokens —— 全部以 React 版本为基准,其余端按它复刻。

需要强调的是:React 是 UI 真源,但这不等于四端必须用同一个组件库。

技术栈主组件库补充
React / Next.jsHero UIShadcn UI
Vue / NuxtNuxt UI v4无(唯一组件库)

组件优先级

组件库优先级:React / Next 用 Hero UI,Vue / Nuxt 用 Nuxt UI v4React / Next.js1Hero UI@heroui/react2Shadcn UI仅作补充3项目级自定义最后兜底Vue / Nuxt1Nuxt UI v4唯一组件库2项目级自定义官方未覆盖时3第三方组件须评审后引入禁止:同种基础组件跨页混用不同库 · 因熟悉某个库就默认使用 · 一次性大规模迁移

跨库对照

需要复刻同一个交互时,按下表换算:

Hero UI(React / Next)Nuxt UI v4(Vue / Nuxt)
ButtonUButton
TextFieldUInput
ModalUModal
DrawerUDrawer / USlideover
TableUTable
useOverlayState()v-model:open

明确禁止的做法

通用禁止:同一种基础组件跨页面混用不同库;因为自己熟悉某个库就默认用它;为了"全库统一"而发起一次性大规模重构;并行维护两套互相独立的设计变量。

Vue / Nuxt 额外禁止:引入 Vuetify、Quasar、Element Plus、PrimeVue、shadcn-vue;从零手写 Sidebar / Header(必须使用 Nuxt UI 的 Dashboard 套件);移植 React 端的 theme.css 或自建一层 Token 映射。

浮层开合状态必须用 useOverlayState

React / Next 中所有由布尔值控制的浮层(Modal / AlertDialog / Drawer / Popover 等),其 open 状态统一用 Hero UI 导出的 useOverlayState() 管理

const state = useOverlayState();
// 受控写法:isOpen / onOpenChange 挂在最外层 Overlay 组件上
<AlertDialog.Backdrop isOpen={state.isOpen} onOpenChange={state.setOpen}>

禁止自己用 useState(true / false)isOpen 挂在 Root / Trigger 上 —— 会让 react-aria 的受控流不匹配,表现为弹窗不显示或控制台报错。Vue 端的等价物是 v-model:open

Design Tokens

HeroUI 设计体系为主要参考,形成一套项目级 Token,Hero UI、Shadcn UI 与自定义组件共用。真源是 apps/react/src/styles/theme.css

HeroUI Design Tokens 色板:品牌色、语义色与中性色accent品牌主色danger危险 / 错误success成功 / 通过warning警告 / 提醒foreground正文文字muted次要文字background页面底色surface卡片 / 浮层default次级填充border描边 / 分隔

颜色

Token中文语义LightDark
accent品牌主色oklch(62.04% 0.195 253.83)同左
danger危险 / 错误oklch(65.32% 0.2335 25.74)oklch(59.4% 0.1973 24.63)
success成功 / 通过oklch(73.29% 0.1941 150.81)同左
warning警告 / 提醒oklch(78.19% 0.159 72.33)同左
background页面底色oklch(97.02% 0.0015 253.83)oklch(12% 0.0015 253.83)
surface卡片 / 浮层oklch(100% 0.0008 253.83)oklch(21.03% 0.003 253.83)
foreground正文文字oklch(21.03% 0.0015 253.83)oklch(99.11% 0.0015 253.83)
muted次要文字oklch(55.17% 0.003 253.83)oklch(70.5% 0.003 253.83)
border描边 / 分隔oklch(90% 0.0015 253.83)oklch(28% 0.0015 253.83)

新增颜色必须双套定义

Dark Mode 采用 class 策略(在 <html> 上切 light / dark)。任何新增色值都要同时给出亮暗两档,只在单一模式验证过的颜色不许进主分支。

圆角

HeroUI v3 的整条圆角刻度(--radius-xs--radius-4xl--field-radius都由基准变量 --radius 派生,所以用户切换圆角偏好时,覆盖基准即可全站生效 —— 按钮、卡片、输入框、表格容器、弹窗一起变。

档位--radius--field-radius
none0rem0rem
small0.25rem0.375rem
medium(默认)0.5rem0.75rem
large0.75rem1.125rem

圆形件(头像、Chip、Switch 手柄)走 rounded-full不走这条刻度,因此不受档位影响 —— 这是预期行为。

字体

默认字体是自托管的 Maple Mono CN 子集(OFL-1.1 授权),通过 unicode-range 只对常用汉字与 ASCII 区段生效:

@font-face {
  font-family: "Maple Mono CN";
  src: url("/fonts/maple-mono-cn-regular.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+0020-007E, U+00B1, U+00B7, U+00D7, U+00F7, U+2014,
    U+2018-2019, U+201C-201D, U+2026, U+3000-303F, U+4E00-9FFF, U+FF00-FFEF;
}

子集之外的生僻字与动态数据用字自然回退系统字体,不产生额外加载。

间距与阴影

  • 间距以 0.25rem 为基准单位;主内容区 px-4 py-6,Header h-16 p-4,卡片 px-6 py-6,表单纵向 space-y-6
  • 阴影克制使用:只有 Dialog / Drawer 这类真正浮起的层用 shadow-lg,常规卡片不加阴影。

布局骨架

SidebarProvider
└── SidebarInset(@container/content)
    ├── Header
    └── Main
  • Header 右侧操作区顺序固定:Search → ThemeSwitch → ThemeSettingsDrawer → ProfileDropdown
  • 列表页 Header 用 fixed页面内禁止自写 sticky / fixed —— 滚动行为由布局统一管理,页面各自为政必然打架。

三种页面模板:

页面类型结构
列表页页头 + DataTable + 各类 Dialog
设置页左侧 sticky 导航 + ContentSectionmax-w-xl
认证页居中容器 max-w-sm

三种状态互斥

列表与详情区域必须显式处理三种非正常状态,且同时只出现一种

状态表现
EmptyContent,带说明与引导操作
ErrorContent,带重试入口
加载首屏用骨架屏;已有数据时的刷新用半透明遮罩,不要用骨架屏把已有内容闪掉

响应式

沿用 Tailwind 默认断点,不加自定义断点。表格容器统一 overflow-x-auto 横向滚动;触摸目标不小于 32px

品牌标识资源

跨端共享的品牌资产真源在仓库 assets/logo/,各端引用而不是各自复制一份。改品牌标识时先改真源,再分发。

本页目录