@azmr/ui

中文文档
0.12.1发布于 2026/11/01MITTypeScriptES Module构建来源已验证近 30 天下载 2365

在 Base UI 和 Tailwind v4 令牌上可访问的 React 设计系统——按钮,菜单,模式,桌子,土司等,并带有信号感知钩

中文使用文档
文档目录16 节
  1. 安装
  2. 样式和设计符号
  3. 主题、密度和地点
  4. 构成部分
  5. 按钮
  6. 投入
  7. 旋转器
  8. 正在装入
  9. 图标
  10. 入境点
  11. 网格
  12. 使用符号
  13. 网格道具
  14. 所需资源
  15. 文档
  16. 许可证

校对:soup

在 Base UI 和 Tailwind v4 令牌上所建的可访问回放设计系统:按钮,菜单,模式,桌子,土司等. 需要信号的组件,例如 Grid,当它改变时重新放弃,不需要国家管理.

安装

pnpm add @azmr/ui @azmr/core react react-dom
# or
npm install @azmr/ui @azmr/core react react-dom

@azmr/core 是一个 同伴依赖自己安装,这样你的应用程序和 @azmr/ui 共享一份( 两份不兼容) Signal 类型).

样式和设计符号

@azmr/ui 将设计符号和Tailwind v4主题映射成两个样式表。 在您的全球CSS中,选择一个:

@import "tailwindcss";
@import "@azmr/ui/styles.css";   /* tokens + global base rules (new app) */
@import "@azmr/ui/classes.css";  /* or one list per component you use */
@import "tailwindcss";
@import "@azmr/ui/tokens.css";   /* tokens only (app that already has global styles) */
@import "@azmr/ui/classes/button.css";
  • styles.css 实值 tokens.css 加上两个全局基本规则:页面背景和文本颜色 body,而我们的边框和外观颜色是每个元素的默认值。 用在一个新的应用程序.

  • tokens.css 具有同样的同义词、主题、密度、运动和公用事业,以及 改变不了我们自己班外的任何东西。当应用程序已经具有全局风格时使用它:另一个UI库中移,或者一个文档站点. 部件看起来是右侧的.

  • 按 shadcn/ ui 键名 (单位:千美元)--background, (中文(简体) ), --primary, (中文(简体) ), --ring, (中文(简体) ), --radius, (中文(简体) ), --sidebar-*因此,从任何注册的阴影组件 看着我们旁边。 阿兹马拉又说 --success, (中文(简体) ), --warning, (中文(简体) ), --info, (中文(简体) ), --chart-1 改为 --chart-8, (中文(简体) ), --motion-*, (中文(简体) ), --elevation-*, (中文(简体) ), --z-* 财务报告和审定财务报表 --density-*。 。 。 .

  • 公用事业 例如 bg-background, (中文(简体) ), text-muted-foreground, (中文(简体) ), rounded-lg, (中文(简体) ), shadow-elevation-2 财务报告和审定财务报表 ease-standard 工作从盒子。 导入您使用的每个条目的类列表( E)@azmr/ui/classes/button.css),或 @azmr/ui/classes.css 对所有人来说,Tailwind生成 包的类。 每个列表都保留着条目使用的类别,所以一个应用程序只支付其进口的组件.

  • 光和暗 使用 OKLCH 颜色 light-dark()。页面默认跟随系统;强制模式 class="dark" 编号 : class="light" 或者说 data-theme="dark|light" 任何祖先都一样 没有JavaScript,没有闪光.

  • 密度 : 设定 data-density="compact" 或者说 "spacious" 以改变控制高度、粘接和行高.

  • 减少运动: 与 prefers-reduced-motion: reduce,每个 --motion-duration-* 符号倒塌到 0.01ms 安全网可以缩短其他动画 将真正必要的动议标出 data-motion="essential"。 。 。 .

  • 测试无障碍性: 每对前地/后地令牌一对在两种模式中都与WCAG AA文本对比(4.5:1)相会,焦点环和图表颜色相会于3:1相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相会相.

主题、密度和地点

服务器布局(Next.js App Router). 从服务器上的 cookie 读取存储首选项, 并将其转换为 <html>,因此第一种颜料已经正确,没有内含脚本(严格CSP下的工作):

// app/layout.tsx
import { cookies } from "next/headers";
import { htmlAttributes, parseDensity, parseThemePreference, THEME_COOKIE, DENSITY_COOKIE } from "@azmr/ui/theme";
import { LocaleProvider, ThemeProvider } from "@azmr/ui/react";

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const jar = await cookies();
  const theme = parseThemePreference(jar.get(THEME_COOKIE)?.value);
  const density = parseDensity(jar.get(DENSITY_COOKIE)?.value);
  return (
    <html lang="en-NZ" {...htmlAttributes({ theme, density })}>
      <body>
        <ThemeProvider defaultTheme={theme} defaultDensity={density}>
          <LocaleProvider locale="en-NZ" currency="NZD">{children}</LocaleProvider>
        </ThemeProvider>
      </body>
    </html>
  );
}
  • system (默认)不需要属性和 JavaScript: 符号使用 light-dark(),因此页面遵循操作系统.
  • useTheme() 返回时 { theme, resolvedTheme, setTheme, density, setDensity }更新更改 <html> 立即被记起persist={false} 关掉它.
  • 无法在服务器上读取 cookie 的静态站点可以内入 themeInitScript() 相反(将您的 CSP 非ce 添加到标签中) .
  • createTheme({ primary, secondary, success, warning, info, destructive, radius, font, density }) 转换出品牌颜色( e)#rrggbb, (中文(简体) ), oklch(L C H) 或者说 { l, c, h })成为符号覆盖. 每个颜色选项都是可选的,省略时保留默认值(destructive 是"危险"的颜色。 它保证WCAG AA两种模式,必要时调整光度并保持色调:
    • 每个 -foreground 颜色至少是4.5:1, 包括在坚固的按钮的悬浮表面 (按键与悬浮上页相混合,可以拉出只从4.5:1下经过的颜色;取出时检查该相混合;);
    • success, (中文(简体) ), info 财务报告和审定财务报表 destructive 也可读取为 文本 页面和卡片Text tone,格式错误),以及 warning 获得单独的可读性 --warning-text· ;
    • 焦距环至少为3:1. 输入被严格验证,因为输出是 CSS,一个错误命名了错误的选项.
import { createTheme } from "@azmr/ui/theme";
const theme = createTheme({
  primary: "#1E88E5",
  success: "#2E7D32",
  destructive: "#D32F2F",
  radius: "0.5rem",
});
// <style>{theme.css}</style>   or   <html style={theme.cssVariables}>

当地人. LocaleProvider 默认为 en-NZ, (中文(简体) ), NZD 周一开始. useLocale() 给定缓存 Intl 格式化器( e)formatNumber, (中文(简体) ), formatCurrency, (中文(简体) ), formatDate, (中文(简体) ), formatDateTime)和字符串组件显示(messages,压倒一切。 只约会字符串, 如 2026-10-15 在每个时区打印日历日; 缺少或无效的值格式为空字符串, 而不是扔出.

构成部分

组件只读取设计符号( 没有原始颜色), 接受 className (最后合并,因此可以覆盖默认),向前 ref 到真正的 DOM 元素,并跟随密度符来表示高度和粘贴。 从根或从子道导入;子道和根都具有树能活性.

按钮

import { Button } from "@azmr/ui/button";

<Button>Save</Button>
<Button variant="destructive" loading loadingText="Deleting">Delete</Button>
<Button variant="outline" startIcon={<PlusIcon />}>New customer</Button>
<Button size="icon" aria-label="Close"><XIcon /></Button>            {/* icon-only needs a name */}
<Button nativeButton={false} render={<a href="/docs" />}>Docs</Button>   {/* renders a link */}
  • 备选案文: default, (中文(简体) ), secondary, (中文(简体) ), outline, (中文(简体) ), ghost, (中文(简体) ), destructive, (中文(简体) ), success, (中文(简体) ), warning, (中文(简体) ), info, (中文(简体) ), link。 。 。 . 大小 : sm, (中文(简体) ), md (按照密度符号), lg, (中文(简体) ), icon。 。 。 .
  • loading数字 : 显示旋转器, 套 aria-busy,忽略了点击和键盘激活, 保持可聚焦 (键盘用户保留位置). loadingText 装入时替换标签; startIcon 由旋转器取代, endIcon 留下来.
  • type 实值 "button" 默认,所以表格中的按钮绝不是偶然提交的;通过 type="submit" 当然.
  • 只检查图标按钮类型 : size="icon" 需求 aria-label 或者说 aria-labelledby。 。 。 .

投入

import { Input } from "@azmr/ui/input";
import { useForm } from "react-hook-form";

const { register } = useForm();
<label htmlFor="email">Email</label>
<Input id="email" type="email" {...register("email")} />   {/* no Controller needed */}

ref 是真实的 <input>这样 register() {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}直接工作 土著 onChange 键入 onValueChange(value) 两个火. aria-invalid="true" 样式无效状态;焦点使用全强环(WCAG 2.2焦点外观).

旋转器

<Spinner /> 装饰; <Spinner label="Loading customers" /> 宣布为状态。 它不停地旋转 prefers-reduced-motion 因为冷冻的旋转器读作挂起的一页. size (单位:千美元)xs 改为 xl,或 inherit, (中文(简体) ), tone 财务报告和审定财务报表 delay (ms在它消失之前,纯CSS)是可选的.

正在装入

import { Loading } from "@azmr/ui/loading"; // Server Component: fine in loading.tsx
import { LoadingBar, LoadingOverlay } from "@azmr/ui/loading/client";

<Loading label="Loading invoices…" variant="page" />           // a Next loading.tsx
<Loading label="Loading data" logo={<img src="/logo.svg" alt="" />} />
<LoadingOverlay active={isRefetching}>{table}</LoadingOverlay>  // dims, aria-busy, spinner on top
<LoadingBar loading={isNavigating} />                          // thin bar at the top of the page

图标

Icon 使任何图标组件的大小、中风、运动和无障碍性一致。 这是一个 服务器组件 (没有钩子,没有) "use client"),所以它的工作在 loading.tsx,布局和悬浮倒计时.

import { Icon } from "@azmr/ui/icons";
import { Search } from "lucide-react";
import { IconBell } from "@tabler/icons-react";   // optional: any set, or your own SVG component

<Icon icon={Search} />                              {/* decorative: aria-hidden */}
<Icon icon={Search} aria-label="Search" size="lg" /> {/* meaningful: role="img" + name */}
<Icon icon={IconBell} strokeWidth={1.5} />
<Icon icon={Loader} spin />                          {/* keeps spinning under reduced motion */}
  • 大小 : xs, (中文(简体) ), sm, (中文(简体) ), md (违约), lg, (中文(简体) ), xl 遵循大小符号;数字是像素大小. className 最后合并,所以 className="size-8" 赢了.
  • 默认可访问 : 装饰性(aria-hidden除非你通过 aria-label 或者说 aria-labelledby。仅由图标的按钮由标签图标命名.
  • 带任何一套. Lucide( ISC) 是默认值; Taller( MIT) 和您自己的 SVG 组件通过同一程序工作 icon 无适配器的道具. react-icons 故意不捆绑:它通过精确的子路径进口来混合许可证和树摇.
  • 树摇被测试: 图标核心完全不捆绑图标, 和一个只导入图标的图标捆绑的应用程序.

以名为相. 从大多数到最不孤立的三种方式:

// 1. The curated Lucide set, with typed names (about 60 everyday icons; Lucide's own kebab-case names)
import { Icon } from "@azmr/ui/icons/lucide";
<Icon name="circle-alert" />

// 2. Your own typed set: nothing global, only the icons you list are bundled
import { createIconSet } from "@azmr/ui/icons";
export const { Icon } = createIconSet({ check: Check, "my-logo": MyLogo });

// 3. A global registry for custom SVGs (names are untyped strings)
import { registerIcons } from "@azmr/ui/icons";
registerIcons({ "my-logo": MyLogo });   // then <Icon name="my-logo" />

一个未知的名称会让一个开发警告无所事事并日志; 它永远不会崩溃页面 .

从 @mui/icons-material。 。 。 . @azmr/ui/icons/mui-map 是纯数据 : resolveMuiIcon("SearchOutlined") 返回时 { name: "Search", variant: "outlined", lucide: "search", tabler: "IconSearch" }它覆盖300多块通用材料图标 Outlined 编号 : Rounded 编号 : Sharp 编号 : TwoTone 变体(和遗产) Outline 拼写旧的 MUI 版本导出),仅将品牌图标映射到 Tabler (Lucide 没有), 并列出它故意不映射的常见名称 unmappedMuiIcons。里面的每个名字都通过测试来检查真实的 @mui/icons-material, (中文(简体) ), lucide-react 财务报告和审定财务报表 @tabler/icons-react。 迁移代码模块使用它, 并报告任何未刷新而非猜测 .

入境点

导入目录指令
@azmr/ui所有东西( a)Grid, (中文(简体) ), useSignal, (中文(简体) ), cn(中文(简体) )"use client"
@azmr/ui/hooks反应钩子( R)useSignal, (中文(简体) ), useDebouncedCallback, (中文(简体) ), useDebouncedValue, (中文(简体) ), useReducedMotion, (中文(简体) ), useUrlTab(中文(简体) )"use client"
@azmr/ui/theme服务器安全主题助手 : createTheme饼干, htmlAttributes, (中文(简体) ), createLocale无, 从服务器组件和中间软件可导入
@azmr/ui/reactThemeProvider, (中文(简体) ), useTheme, (中文(简体) ), LocaleProvider, (中文(简体) ), useLocale"use client"
@azmr/ui/buttonButton, (中文(简体) ), buttonVariants"use client"
@azmr/ui/inputInput, (中文(简体) ), Textarea"use client"
@azmr/ui/input-groupInputGroup, (中文(简体) ), InputGroupInput, (中文(简体) ), InputGroupAddon, (中文(简体) ), InputGroupButton"use client"
@azmr/ui/password-inputPasswordInput, (中文(简体) ), passwordRequirements, (中文(简体) ), defaultPasswordScorer"use client"
@azmr/ui/number-fieldNumberField, (中文(简体) ), MoneyField, (中文(简体) ), numberOrNull"use client"
@azmr/ui/field-arrayFieldArray (重复行:添加,去除,拖放或键盘重排,总计)"use client"
@azmr/ui/rhfForm, (中文(简体) ), FormField, (中文(简体) ), FormErrorSummary, (中文(简体) ), FormFieldArray (反应钩形式7,可选对等)"use client"
@azmr/ui/zodzodResolver, (中文(简体) ), fieldsFromSchema, (中文(简体) ), fieldFromSchema, (中文(简体) ), toFieldErrors (Zod 4,可选对等点)无, 服务器安全
@azmr/ui/fieldField, (中文(简体) ), FieldRoot, (中文(简体) ), FieldLabel, (中文(简体) ), FieldDescription, (中文(简体) ), FieldError"use client"
@azmr/ui/formFieldset, (中文(简体) ), FieldsetRoot, (中文(简体) ), FieldsetLegend, (中文(简体) ), FormSection, (中文(简体) ), ErrorSummary, (中文(简体) ), toErrorSummaryItems"use client"
@azmr/ui/spinnerSpinner (单位:千美元)size, (中文(简体) ), tone, (中文(简体) ), delay(中文(简体) )无,可以从服务器组件导入
@azmr/ui/loadingLoading (内置、部分或页;可见标签;带有旋转环的标志), Spinner无,可以从服务器组件导入
@azmr/ui/state-viewStateView (一个区域装入状态、 空状态和出错状态的布局)无,可以从服务器组件导入
@azmr/ui/error-boundaryErrorBoundary (单位:千美元)onError 报告钩, reset, (中文(简体) ), resetKeys, (中文(简体) ), rethrow 框架错误)"use client"
@azmr/ui/loading/clientLoadingOverlay, (中文(简体) ), LoadingBar (上页栏), useLoadingState (单位:千美元)delay 财务报告和审定财务报表 minDuration(中文(简体) )"use client"
@azmr/ui/iconsIcon, (中文(简体) ), createIconSet, (中文(简体) ), registerIcons无,可以从服务器组件导入
@azmr/ui/icons/lucideIcon 被捆绑在Lucide的套房里, lucideIcons无,可以从服务器组件导入
@azmr/ui/icons/mui-mapresolveMuiIcon, (中文(简体) ), muiIconMap, (中文(简体) ), unmappedMuiIcons (移徙数据)无, 纯数据
@azmr/ui/libcn() 和其他服务器安全助手无,可以从服务器组件导入

cn(...classes) 合并类名并解决矛盾的 Tailwind 公用事业, 最后一位获胜: cn("p-2", "p-4") → "p-4"。 。 。 .

网格

import { Signal } from "@azmr/core";
import { Grid } from "@azmr/ui";

const customers = new Signal([
  { name: "Aroha", balance: 150 },
  { name: "Mere",  balance: 320 },
]);

function App() {
  return (
    <Grid
      signal={customers}
      labels={{ name: "Customer", balance: "Balance ($)" }}
    />
  );
}

// Grid updates automatically
customers.set([...customers.peek(), { name: "Tane", balance: 0 }]);

使用符号

Hook 将任何反应组件订阅到信号上 .

import { useSignal } from "@azmr/ui";

function Counter({ count }: { count: Signal<number> }) {
  const value = useSignal(count); // push-based, no polling
  return <span>{value}</span>;
}

网格道具

Prop类型说明
signalSignal<T[]>反应数据源
columns(keyof T)[]可选列顺序
labelsPartial<Record<keyof T, string>>可选列标签覆盖
emptyMessagestring信号为空时显示的消息

所有细胞值都是通过 React 的 JSX 逃出—— dangerouslySetInnerHTML 从未使用.

所需资源

  • 节点.js 18
  • 反应 18 或 19
  • TypeScript 第 5 (包括类型)

文档

完整文件时间 互联网档案馆的存檔,存档日期2013-12-02

许可证

麻省理工学院 阿兹马拉实验室

版本与发布记录

@azmr/ui 共发布 15 个版本,首次发布于 2026/04/10;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.12.1latest2026/11/016 天前
0.12.02026/11/016 天前
0.11.02026/10/317 天前
0.10.02026/10/317 天前
0.9.02026/10/308 天前
0.8.02026/10/309 天前

关于 @azmr/ui 的常见问题

@azmr/ui 是什么?

在 Base UI 和 Tailwind v4 令牌上可访问的 React 设计系统——按钮,菜单,模式,桌子,土司等,并带有信号感知钩

如何安装 @azmr/ui?

在项目目录运行 npm install @azmr/ui,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.0.0 || ^19.0.0)、react-dom(^18.0.0 || ^19.0.0)、@azmr/core(>=0.0.2 <1.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@azmr/ui 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@azmr/ui 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@azmr/ui 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@azmr/ui 可以商用吗?

@azmr/ui 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@azmr/ui 的下载量有多少?

根据 npm 官方下载统计,@azmr/ui 在 2026/10/08 – 2026/11/06 这 30 天内被下载 2,365 次,日均约 79 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@azmr/ui 还在维护吗?

最新版本 0.12.1 发布于 2026/11/01(6 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/04/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。