# @animus-ui/system 中文文档

规范地址：https://npmcn.com/package/%40animus-ui/system/

版本：0\.1\.87
npm 元数据更新时间：2026-10-24T04:19:38.285Z
中文译文更新时间：2026-11-06T04:51:58.908Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40animus-ui/system
原文对照：https://npmcn.com/package/%40animus-ui/system/?lang=original
项目主页：https://github.com/codecaaron/animus/tree/main/packages/system#readme
源码仓库：https://github.com/codecaaron/animus

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：414 kB，46 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.12\.0
- 运行依赖：2 个
- peer 依赖：react ^18\.0\.0 \|\| ^19\.0\.0
- 首次发布：2026-03-25T16:50:35.718Z
- 最新版本发布：2026-10-24T04:19:37.806Z
- 近 30 天下载量：6931（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：112（近 12 个月 112 个）

## 中文简介

Animus 设计系统构建器 — 符号, 道具组, 全球风格

## 安装

```sh
npm install @animus-ui/system
```

也可以使用：`pnpm add @animus-ui/system`、`yarn add @animus-ui/system`、`bun add @animus-ui/system`

## README

# @animus-ui/系统

React的设计系统构建器. 由零运行时间驱动的CSS-in-JS——样式提取到建设时间的静态CSS.

## 安装

```bash
npm install @animus-ui/system
```

与提取驱动程序对等 : `@animus-ui/vite-plugin`, (中文(简体) ), `@animus-ui/next-plugin`, (中文(简体) ), `@animus-ui/unplugin`,或 `@animus-ui/cli`。 。 。 .

## 快速启动

### 1\. 确定主题

```tsx
import { createTheme } from '@animus-ui/system';

const theme = createTheme()
  .addBreakpoints({ sm: 480, md: 768, lg: 1024 })
  .addColors({
    gray: { 100: '#f0f0f0', 800: '#1a1a1a' },
    blue: { 400: '#3d94ff', 700: '#003d99' },
    red: { 500: '#e63946' },
  })
  .addColorModes('dark', {
    dark: {
      primary: 'blue.400',
      danger: 'red.500',
      bg: 'gray.800',
      text: 'gray.100',
    },
    light: {
      primary: 'blue.700',
      danger: 'red.500',
      bg: 'gray.100',
      text: 'gray.800',
    },
  })
  .addScale({
    name: 'space',
    values: { sm: '0.5rem', md: '1rem', lg: '1.5rem' },
  })
  .build();

type AppTheme = typeof theme;

declare module '@animus-ui/system' {
  interface Theme extends AppTheme {}
}
```

### 2\. 与道具组创建系统

预先建造的团体船 与包裹。 把它们编成自己的语义组:

```tsx
import { createSystem } from '@animus-ui/system';
import {
  background,
  border,
  color,
  flex,
  layout,
  shadows,
  space,
  typography,
} from '@animus-ui/system/groups';

const bundle = createSystem()
  .addGroup('surface', { ...color, ...border, ...shadows, ...background })
  .addGroup('space', space)
  .addGroup('text', typography)
  .addGroup('arrange', { ...flex, ...layout })
  .build();

export const { createGlobalStyles, createKeyframes } = bundle;
```

`build()` 返回捆绑,而不是系统。 关键框架收集和 全局风格的块在模块镜下的捆绑上注册 导出名称,以及 `seal()` 生产系统组件的构建方式如下:

```tsx
export const motion = createKeyframes({
  pulse: { '0%, 100%': { opacity: 1 }, '50%': { opacity: 0.6 } },
});

export const globalStyles = createGlobalStyles({
  body: { margin: 0, bg: 'bg', color: 'text' },
});

export const ds = bundle
  .registerKeyframes({ motion })
  .registerGlobalStyles({ globalStyles })
  .seal();
```

注册密钥必须等于导出名称, 因为提取符 决定 `motion.pulse` 引用该名称。 关键框架和全球风格 块共享一个词汇名空间.

要利用已公布的设计系统工具包,请从其中任一环节开始 `.extend()` 它将工具包的注册和信物合并到你的(kit as 基地,你后来的呼声赢得了冲突, 和提取管道 在同一边上发现工具包 :

```tsx
import { system as kitSystem, theme as kitTheme } from '@acme/kit';

const theme = createTheme().extend(kitTheme).build();
const bundle = createSystem()
  .extend(kitSystem)
  .addProps({ cursor: { property: 'cursor' } })
  .build();
```

`createSystem({ includes: [...] })` 财务报告和审定财务报表 `.from()` 已贬值:它们添加 在不合并登记册的情况下加入调查组.

每个组成为一组可选入的道具,组件可以使用 `.system()`数字 :

```tsx
const Box = ds
  .styles({})
  .system({ surface: true, space: true })
  .asElement('div');

// Box now accepts: color, bg, border, shadow, p, m, gap, etc.
<Box bg="bg" p="md" borderBottom="1px solid" />;
```

### 3\. 构筑组件

```tsx
export const Alert = ds
  .styles({
    display: 'flex',
    alignItems: 'flex-start',
    p: 'md',
    borderRadius: '4px',
    fontSize: '14px',
    lineHeight: '1.5',
  })
  .variant({
    prop: 'variant',
    variants: {
      filled: { color: 'bg' },
      outline: { bg: 'transparent', borderWidth: '1px', borderStyle: 'solid' },
    },
  })
  .variant({
    prop: 'intent',
    variants: {
      info: { bg: 'primary' },
      danger: { bg: 'danger' },
    },
  })
  .compound(
    { variant: 'outline', intent: 'info' },
    { borderColor: 'primary', color: 'primary' }
  )
  .compound(
    { variant: 'outline', intent: 'danger' },
    { borderColor: 'danger', color: 'danger' }
  )
  .states({
    disabled: { opacity: 0.5, pointerEvents: 'none' },
  })
  .system({ space: true })
  .asElement('div');

<Alert variant="filled" intent="info" m="sm" disabled />;
```

## 构建链

链条执行级联命令——每个方法映射到CSS `@layer`数字 :

```
ds.styles()    → @layer anm-base
  .variant()   → @layer anm-variants
  .compound()  → @layer anm-compounds
  .states()    → @layer anm-states
  .system()    → @layer anm-system
  .props()     → @layer anm-custom
  .asElement() → typed React component
```

类型系统防止调用方法出轨.

### 扩展组件

`.extend()` 在组件上启动一个继承所有 组件声明、自定义道具及其召回。 其方法 可以在任意顺序下调用; 自定义道克重新声明在 `.props()` 替换 仅用于此扩展及其自身的扩展.

```tsx
const Card = ds
  .props({
    inset: { property: 'padding', transform: (v) => `${Number(v) * 4}px` },
  })
  .asElement('div');

export const Panel = Card.extend()
  .styles({ display: 'grid' })
  .asElement('section');

<Panel inset={3} />; // padding: 12px, computed by Card's callback
```

扩展读取从父组件继承的回调, 当其 模块运行,就像作者一样 `Card.extend()` 已经 有两个后果:

-   父模块必须在扩展前完成初始化 模块:无法在导入周期内宣布扩展 首先评价扩展模块.
-   客户端模块中定义的自定义道具召回的父程序 (单位:千美元)`'use client'`无法从服务器模块中扩展; 声明 客户端模块中的扩展名.

### 倒计时值

`firstThatWorks()` 列出一个属性的值,优先. 提取器声明为倒置, 所以浏览器支持的最后一个 胜出,折出一跑赤裸的 `var()` 值变为一个嵌入式倒计时 :

```tsx
import { firstThatWorks } from '@animus-ui/system';

const Header = ds
  .styles({
    position: firstThatWorks('sticky', '-webkit-sticky', 'fixed'),
    scrollMarginTop: firstThatWorks(
      'var(--header-height)',
      'var(--bar-height)',
      '4rem'
    ),
  })
  .asElement('header');
```

```css
.animus-Header-… {
  position: fixed;
  position: -webkit-sticky;
  position: sticky;
  scroll-margin-top: var(--header-height, var(--bar-height, 4rem));
}
```

每个成员按财产打字,按其规模解决。 这个 以组件样式、全局样式和键框来工作。 写成 调用站点道具它只在运行时读取,运行时应用首选值 独自一人,且加以警告`animus.first-that-works.unextracted`) (中文(简体) ). 降低修饰符 用于浏览器目标, 如在Vite 或 Animus 自己的闪电 CSS `targets`,将每个已经支持的目标降回倒计时.

### 锁定位置后退

`createPositionTry`,在已建的捆绑上 锚定位. 以出口名称登记收藏,截至 键,并使用 `positionTryFallbacks`数字 :

```tsx
export const { createPositionTry } = bundle;
export const placements = createPositionTry({
  above: { positionArea: 'top', marginBottom: '{space.8}' },
  flipStart: { top: 'anchor(bottom)', insetInlineStart: 'anchor(start)' },
});
export const ds = bundle.registerPositionTry({ placements }).seal();

const Tooltip = ds
  .styles({
    positionAnchor: '--trigger',
    positionTryFallbacks: `${placements.above}, flip-block`,
  })
  .asElement('div');
```

```css
@layer anm-global {
  @position-try --animus-pt-… {
    position-area: top;
    margin-bottom: 0.5rem;
  }
}
.animus-Tooltip-… {
  position-anchor: --trigger;
  position-try-fallbacks: --animus-pt-…, flip-block;
}
```

每个职位都取自其描述词。 只不过什么 `@position-try` 接受的属性包括:设置、边距、大小和自配对属性, `positionAnchor` 财务报告和审定财务报表 `positionArea`; 其他任何东西都是类型错误,以及 掷出. 由于数组是 反应性价值。 每个注册位置都发出,是否使用.

### 查看过渡

`createViewTransitions`,在已建的捆绑上,名称视图-过渡 课程。 每个过渡 `group`, (中文(简体) ), `imagePair`, (中文(简体) ), `old` 财务报告和审定财务报表 `new` 槽样式 其伪要素,并将关键框架的参考、标志和条件作为 一个全局风格块。 以出口名称登记收藏:

```tsx
export const { createKeyframes, createViewTransitions } = bundle;
export const motion = createKeyframes({
  slideIn: { from: { translate: '100% 0' } },
  slideOut: { to: { translate: '-100% 0' } },
});
export const transitions = createViewTransitions({
  slide: {
    group: { animationDuration: '250ms', _motionReduce: { animation: 'none' } },
    old: { animationName: motion.slideOut },
    new: { animationName: motion.slideIn },
  },
});
export const ds = bundle
  .registerKeyframes({ motion })
  .registerViewTransitions({ transitions })
  .seal();

const Card = ds
  .styles({
    viewTransitionName: 'match-element',
    viewTransitionClass: transitions.slide,
  })
  .asElement('article');
```

```css
@layer anm-global {
  ::view-transition-group(*.animus-vt-…) {
    animation-duration: 250ms;
  }
  @media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*.animus-vt-…) {
      animation: none;
    }
  }
  ::view-transition-old(*.animus-vt-…) {
    animation-name: animus-kf-…;
  }
  ::view-transition-new(*.animus-vt-…) {
    animation-name: animus-kf-…;
  }
}
```

校对的指纹是其类,所以 `String(transitions.slide)` 还有名字 如果一个框架需要一个类,例如React's `<ViewTransition>`每一个 已注册的转换输出,是否使用.

### 相对状态选择器

`marker(name)` 命名要设置一个状态样式的元素的类 另一种:先祖,后人或兄弟姐妹. 将其关系登记为 选择者别名 :

```tsx
import { createSystem, marker } from '@animus-ui/system';

export const row = marker('row'); // row.className === 'animus-marker-row'

const bundle = createSystem()
  .addSelectors({
    _rowHover: row.ancestor(':hover'),
    _rowHasFocus: row.descendant(':focus-visible'),
  })
  .build();

<tr className={row.className}>
  <Cell _rowHover={{ opacity: 1 }} />
</tr>;
```

| 关系 | 选择器 |
| --- | --- |
| `ancestor(':hover')` | `&:where(.m:hover *)` |
| `descendant(':hover')` | `&:where(:has(.m:hover))` |
| `siblingBefore(...)` | `&:where(.m:hover ~ *)` |
| `siblingAfter(...)` | `&:where(:has(~ .m:hover))` |
| `anySibling(...)` | `&:where(.m:hover ~ *, :has(~ .m:hover))` |

状态是伪类或属性选择器(`[data-open]`) (中文(简体) ). 这个 标记坐在里面 `:where()`,因此,关系除了 组件的类,和元素本身的状态,例如 `_hover`, (中文(简体) ), 胜于相亲. 没有 `_group*` 或者说 `_peer*` 化名由内建而来.

## 颜色模式

`addColorModes(initialMode, modeConfig)` 输出 a `[data-color-mode="…"]` 块 每个模式。 可选的第三个参数选择主题为 OS 参与 :

```tsx
const theme = createTheme()
  .addColors({ gray: { 100: '#f0f0f0', 800: '#1a1a1a' } })
  .addColorModes(
    'dark',
    {
      dark: { bg: 'gray.800', text: 'gray.100' },
      light: { bg: 'gray.100', text: 'gray.800' },
    },
    {
      // OS preference → declared mode name.
      systemPreference: { light: 'light', dark: 'dark' },
      // CSS `color-scheme` per mode. The two mapped modes default to
      // 'light'/'dark', so `{}` is the whole opt-in here; classify any
      // additional modes explicitly.
      browserColorScheme: {},
    }
  )
  .build();
```

**`systemPreference`** 允许注意后退排放:

```css
@media (prefers-color-scheme: dark) {
  :root:not([data-color-mode]) {
    /* the dark mode's declarations */
  }
}
```

这个 `:not([data-color-mode])` 守护是使一个明确的属性获胜的 CSS独自一人,没有剧本. 这两个值必须命名已声明的模式 .

**`browserColorScheme`** 增加中央支助系统 `color-scheme` 土产 滚动条,窗体控件,以及 UA 样式跟踪活动模式. 当供应时 必须分类每个声明模式,否则模式将默默继承 先前的本地方案——有一个例外: 两种模式由 `systemPreference` 强迫 `light`编号 :`dark` 由验证,所以他们 默认并可能被省略。 在地图绘制模式上有一个明确条目被尊重 仍然有冲突.

选择两个字节都无法给出它之前释放的字节的主题 .

### "系统"是没有属性

没有 `data-color-mode="system"` ——OS跟随状态是属性 状态 **缺席**,这是上面的媒体卫士唯一能通过的价值. `system` 是一个保留模式名称并被拒绝.

### 外表记录

模糊的外表生活在一个版本的密钥下, `animus:appearance`数字 :

```
{ "v": 1, "mode": "system" | "<mode name>", "theme": "default" }
```

这个 `theme` 轴被保留,目前被忽略——只拥有 模式轴必须保存它不拥有的字段。 包裹船 写纪律,以免手卷: `@animus-ui/system/appearance` 是一个 微小, 只存储的运行时间子路径( 没有反应, 没有听众, 没有 DOM —— 应用) `data-color-mode` 留在你的身边:

```ts
import {
  SYSTEM_MODE,
  migrateLegacyModeKey,
  persistColorMode,
} from '@animus-ui/system/appearance';

persistColorMode('midnight'); // read-modify-write; unowned fields survive
persistColorMode(SYSTEM_MODE); // "follow the OS" — bootstrap restores absence

// One-shot: move YOUR app's old key into the record, then delete it.
migrateLegacyModeKey('my-app-color-mode', ['midnight', 'paper']);
```

它拒绝降级一个新版本的唱片,并拒绝 移动共享 `color-mode` 密钥(一个可能属于另一个应用程序) 来源; 拖曳已读取, 只读)。 一个失败的写入被吞噬 而不是抛出,所以一个已经应用的呼叫者 `data-color-mode` 保留 即使存储拒绝写入,用户对该会话的选择.

打电话 `migrateLegacyModeKey` 后油漆,从应用程序条目中返回 迁移模式名称以申请一次访问,或 `null` 当什么都没有的时候 迁移。 之前在OS解析模式下 修正自己——一个接受的闪光,一次——以后的每个负载都恢复 模式预绘通过生成的靴子.

为了在第一次涂料之前恢复它, 生成一个内线片段 **已建成** 主题:

```ts
import { createAppearanceBootstrap } from '@animus-ui/system/bootstrap';

const { code, cspHash } = createAppearanceBootstrap(theme, {
  storageKey: 'animus:appearance', // default
});
```

`code` 是文档头的无依赖性IIFE:它读了记录, 验证 `mode` 针对主题宣布的名称, 集 `data-color-mode` (单位:千美元) 有效的明确模式,以及 **删除** 属性 `"system"`,一个缺失 记录,或未识别值——将控件交回媒体查询. 这个 从不写存储,从不打电话 `matchMedia` (实现操作系统答案) 输入属性后,它会被冻结,以适应以后的操作系统变化。 预录 纯字符串 `color-mode` 键被读取一次,仅在记录缺失时 从来没有写.

`cspHash` 授权准确的脚本。 从文物中取出信头 构建时间和 **单引号** 数值 - `script-src 'sha256-…'`。没有引用它 解析为主机源并默默地屏蔽脚本;手抄取后,便去 暂停已宣布的模式名称或存储密钥更改的时刻,并暂停 散列是一个被屏蔽的脚本和错误模式的闪光.

这个子路径正在构建工具. 它从未被组件或运行时间导入 条目,因此无法到达提取的应用程序捆绑 —— 生成 装入您捆绑配置的文物并将其交给插件 (单位:千美元)[`@animus-ui/vite-plugin`](https://github.com/codecaaron/animus/tree/main/packages/vite-plugin) 接受 `appearanceBootstrap`; 在 Next.js 中,应用程序的位置 `code` 本身, 这样它就可以控制 CSP 不ce和订购.

## 融合合同

**出版自定义别名.** 从已建成的系统中增加两个登记册:

```ts
import type { ConditionsOf, SelectorsOf } from '@animus-ui/system';

declare module '@animus-ui/system' {
  interface Selectors extends Record<SelectorsOf<typeof ds>, true> {}
  interface Conditions extends Record<ConditionsOf<typeof ds>, true> {}
}
```

虽然两个接口都是空的, `_`\- 前置的块键保持允许. 任何一种增量都会使整个 `_` 命名空间验证, 所以另一个 登记处的别名被拒绝,直到其扩大。 已注册的选择器 别名也作为组件调用道具类型(`<Box _hoverChild={{ p: 8 }} />`(三); 条件化名只是样式-块键.

**关键框架.** 框架接受 CSS 属性名称( mamlCase,转换为 排放时的kebab-case),原始CSS值,以及 `{scale.key}` 符号引用 作为 `{shadows.glow-text}`,主题解析器可替换。 赤度键 没有牙套是逐字发射的,所以总是写出被划定的表格.

**`className` 点菜.** 在正常的路由 消费者提供 `className` 在生成的类后合并, 道具转发跳过 `className` 因为它的合并拥有它。 就是这样 `className="group"` 因此,祖先模式,如 `.group:hover &` 工作时.

## 出口

| 路径 | 里面有什么东西 |
| --- | --- |
| `@animus-ui/system` | Full API — 构建器,主题,运行时间,类型 |
| `@animus-ui/system/groups` | 预建道具组: `space`, (中文(简体) ), `color`, (中文(简体) ), `typography`, (中文(简体) ), `layout`, (中文(简体) ), `flex`, (中文(简体) ), `grid`, (中文(简体) ), `border`, (中文(简体) ), `shadows`, (中文(简体) ), `background`, (中文(简体) ), `positioning`, (中文(简体) ), `transitions`, (中文(简体) ), `mode`, (中文(简体) ), `vars` |
| `@animus-ui/system/compose` | `compose` - 共用变种传播的插槽家庭 |
| `@animus-ui/system/compose-with-context` | `composeWithContext` 共用道具的家庭通过反应环境旅行 `requireRoot: true`,其根外的成员投向发展 |
| `@animus-ui/system/runtime` | `createComponent` 和组成家庭的运行时间 |
| `@animus-ui/system/class-resolver` | `createClassResolver` ——无反应运行时间的类解析,面向非反应消费者 |
| `@animus-ui/system/bootstrap` | `createAppearanceBootstrap` ——仅构建时间,从未通过应用程序代码导入 |
| `@animus-ui/system/appearance` | `persistColorMode`, (中文(简体) ), `migrateLegacyModeKey`, (中文(简体) ), `SYSTEM_MODE` ——仅存储外观记录写入路径(运行时间,客户端安全) |

## 许可证

麻省理工学院

## 常见问题

### @animus-ui/system 是什么？

Animus 设计系统构建器 — 符号, 道具组, 全球风格

### 如何安装 @animus-ui/system？

在项目目录运行 npm install @animus-ui/system，或使用 pnpm add / yarn add / bun add。

### @animus-ui/system 支持 TypeScript 吗？

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

### @animus-ui/system 支持 ESM 还是 CommonJS？

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

### @animus-ui/system 需要什么版本的 Node\.js？

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

### @animus-ui/system 可以商用吗？

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

### @animus-ui/system 的下载量有多少？

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

### @animus-ui/system 还在维护吗？

最新版本 0\.1\.87 发布于 2026/10/24（14 天前）；至今共发布 112 个版本，其中过去 12 个月发布了 112 个；首次发布于 2026/03/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

