@aircall/ds - 空呼设计系统
由TailwindCSS 4, Base UI原始和TypeScript所建的现代反应组件库.
技术堆栈
- 反应 19 - 与编译器优化的最新反应
- 尾风CSS 4 - 具有OKLch色彩空间的功能第一CSS
- 基础UI - 无风格、无障碍组件原始(
@base-ui/react(中文(简体) ) - 类型脚本 5.7 - 安全型发展
- 差异管理局(CVA) - 以变式为基础的组件样式
- 故事集 10 - 互动部分文件
为 AI 代理/ 编码助理
如果您是一个 AI 助理生成代码 @aircall/ds读取
AGENTS.consumer.md (运入本包)
TypeScript 类型不能表达—— Base UI 常规( 使用) render没有 asChild页:1
所需经费 @aircall/ds/globals.css 导入,图标从 @aircall/react-icons,以及
黑暗模式设置 。 运出 .d.ts 文件是道具名称和
数值(变量被打成字形结合)——不发明道具.
迁出 @aircall/tractor打开AI的迁移技能
这个包裹船 TanStack 意图 移徙技能 内
联合国 skills/ 目录(在 npm tarball 中发布) —— 版本匹配, 代理可装入
用于移动应用程序的指南 @aircall/tractor 编号 : @aircall/icons (和 @dashboard/library
→ @aircall/blocks改为: @aircall/ds。在您的回购中启用它们( 一次性) :
# 1. install / upgrade — @aircall/react-icons MUST be >= 0.4.0 (the ds bundle imports flags from it)
pnpm add @aircall/ds@latest @aircall/blocks@latest @aircall/react-icons@latest
# 2. let your AI agent discover the skills — writes a discovery block into CLAUDE.md / AGENTS.md
npx @tanstack/intent install
# 3. allowlist the packages in package.json, then verify discovery:
# { "intent": { "skills": ["@aircall/ds", "@aircall/blocks"] } }
npx @tanstack/intent list # should list @aircall/ds and @aircall/blocks
您的代理从设置开始按需求加载指导 :
npx @tanstack/intent load "@aircall/ds#aircall-ds/setup"
# then per file: aircall-ds/migrate-tractor · aircall-ds/migrate-icons · aircall-blocks/migrate-dashboard
每种移徙技能都附有一个端到端的游戏本(设置-库存-迁移-核实)和
requires setup (包括供应商在内). DsI18nProvider,则 globals.css 导入和jsdom
测试shims。 保留 @aircall/tractor 安装到最后的拖拉机导入已消失..
移徙是渐进的(同居).
安装
用于 Monorepo Apps( Hydra 工作空间)
如果你在海德拉单体内部发展(例如, apps/aw-web, (中文(简体) ), apps/hubspot-cti:
# In your app's package.json
{
"dependencies": {
"@aircall/ds": "workspace:*"
}
}
对于外部应用程序
如果你在外部项目中使用设计系统或消耗已公布的国家预防机制包:
pnpm add @aircall/ds
必要的同伴依赖性 :
pnpm add react react-dom @aircall/react-icons @aircall/numbers
可选的对等者依赖性( 只有使用这些组件时才会安装) :
| 构成部分 | 要安装的软件包 |
|---|---|
Calendar | react-day-picker, (中文(简体) ), date-fns |
# If using Calendar
pnpm add react-day-picker date-fns
软件包及其模块图被保存(
tsdownunbundle)并标出sideEffects: ["**/*.css"]这样Calendar'同龄人只是被拉入 消费者的捆绑Calendar已实际导入。 导入其他组件(例如:.Button)将树摇走——不需要安装.DataTable是因为@tanstack/react-table运行时间为常规@aircall/ds相反的依赖性——它自动安装,没有什么可以补充自己.
使用量
导入组件
组件在单列波和外部应用中都以同样的方式工作:
import { Button } from '@aircall/ds';
function App() {
return (
<Button variant="default" color="primary" size="default">
Click me
</Button>
);
}
导入 CSS 样式
有一个样式表, @aircall/ds/globals.css但它决定了不同的文物 取决于你是如何消耗包裹. (没有单独的) styles.css 导出。 )
Monorepo Apps (英语:workspace:*(中文(简体) )
包裹 exports 点 来源这样 @aircall/ds/globals.css 是未编译的 Tailwind 源(@import "tailwindcss", (中文(简体) ), @theme(中文(简体) ). 您的应用程序的 Tailwind v4 构建编译它 @source 为类名扫描自己的文件 :
/* your app's entry CSS — DS only */
@import '@aircall/ds/globals.css';
@source "your_own_source_file";
如果您还使用了 @aircall/blocks导入 仅限 块状环球——其来源已经导入了DS环球,所以 postcss-import 分解表示DS编译一次:
/* your app's entry CSS — DS + blocks */
@import '@aircall/blocks/globals.css';
@source "your_own_source_file";
外部 Apps( 已发布 npm 套件)
已出版的焦油丸重写 exports 改为 dist这样 @aircall/ds/globals.css 是一个 已预编译 Tailwind v4 捆绑 — Preflight, sirs, 以及已经生成的每个DS通用类.
只有DS, 没有定制的 Tailwind 课:
// main.tsx
import '@aircall/ds/globals.css';
DS + 数字化 @aircall/blocks数字 : 仅导入块 Global —— 它已经捆绑了所有的 DS( Preflight, 主题符号, 所有 DS 公用设备) 。 导入两者都会复制整个DS编译输出 :
// main.tsx
import '@aircall/blocks/globals.css'; // already includes @aircall/ds/globals.css
编写您的 Tailwind 工具类 并用 DS 或 块 —— 使用分块导入来激活 Tailwind for @source 扫描而不添加第二个飞行前:
/* style.css */
/* Required: locks layer order so @layer utilities beats @layer base.
Without this, Preflight's border-width: 0 / display: block beat utility classes. */
@layer theme, base, components, utilities;
/* Split import — no Preflight. The .css extension is required;
bare specifiers (tailwindcss/theme) silently produce no output in Rsbuild/webpack. */
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);
@import '@aircall/ds/globals.css'; /* DS only */
/* OR: @import '@aircall/blocks/globals.css'; for DS + blocks (don't import both) */
@source "./src/**/*.{ts,tsx}"; /* scan YOUR code, not node_modules */
模块化消费者 (你的应用程序是一个已经装入DS Globals的主机内部的远程——例如. dashboard-v4: 不导入 DS 或块环球 。 主机的 Preflight 覆盖了整个文档; 从您的遥控器注入的复制件 <style> 标记将打破 DS 组件边框 .
/* style.css */
@layer theme, base, components, utilities;
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);
@source "./**/*.{ts,tsx}";
黑暗模式
黑暗模式通过 data-theme 属性 :
// Light mode (default)
<html>
// Dark mode
<html data-theme="dark">
设计系统使用基于此属性自动调整的CSS变量.
构成部分
按钮
具有多种变体和大小的 Versatile 按钮组件,建于 Base UI
按钮原始( 因此它也接受 Base UI) Button 道具,例如: disabled) (中文(简体) ).
道具 :
variant: “ 默认” ; “ 次要” ; “外线” ; “鬼魂” ; “毁灭” ; “链接”( 默认 :'default'(中文(简体) )size: “ 默认 ” ; “ sm” ; “lg” ; “icon” ; “icon- sm” ; “icon- lg” (默认 :'default'(中文(简体) )block: boolean – 全宽( 默认 :false(中文(简体) )render: reactElement ——使按钮成为不同的元素(例如.<a>) (中文(简体) ). 替换前一个asChild/槽图案.
图标是儿童传入的。 从
@aircall/react-icons(从来没有)lucide-react页:1.
实例:
import { Button } from '@aircall/ds';
import { Phone, Mail } from '@aircall/react-icons';
// Primary button (default variant)
<Button>Primary</Button>
// Secondary / outline / ghost
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
// Icon-only button — use an `icon*` size
<Button variant="outline" size="icon-sm">
<Phone />
</Button>
// Button with a leading icon
<Button>
<Mail />
Send Email
</Button>
// Full-width button
<Button block>Full Width</Button>
// Destructive button
<Button variant="destructive">Delete</Button>
// Render as a link — use the `render` prop (not `asChild`)
<Button render={<a href="/profile" />}>Go to Profile</Button>
故事书
互动组件文档,包含现场实例、控制和无障碍测试.
快速启动
cd packages/ds
pnpm sb:dev
查看时间:http://localhost:6008
特征
- QQ 互动组件游乐场, 进行现场编辑
- 通过工具栏切换器进行轻/暗模式测试
- 使用a11y加通进行无障碍测试
- * 响应式取景台测试
- QQ Pseudo- state 模拟( hover, 焦点, 活动)
- 图片设计集成
- 从类型Script自动生成文档
构建故事书
pnpm sb:build # plain build — no recipe registry
pnpm sb:build:deploy # full build including the recipe registry (what CI deploys)
静态站点输出 : storybook-static/。见 食谱(阴影登记) 下方用于何时使用.
发展
添加组件
本套件在组件开发中使用了shadcn/ui模式:
# Add a new component from shadcn (wraps `pnpx shadcn@latest add`)
pnpm shadcn:add <component-name>
文件结构
src/
├── components/ # React components, one flat file per component (published to npm)
│ ├── button.tsx
│ ├── dialog.tsx
│ └── …
├── stories/ # Storybook stories (PascalCase, e.g. Button.stories.tsx)
├── styles/ # Global styles
│ ├── globals.css # TailwindCSS + theme variables
│ └── brand.css # Aircall brand colors
├── lib/ # Utilities
│ └── utils.ts # cn() helper for class merging
├── hooks/ # Custom React hooks
├── recipes/ # shadcn registry recipes (copy-paste patterns, NOT published to npm)
│ ├── combobox-searchable-select.tsx
│ ├── combobox-dropdown-search.tsx
│ └── combobox-multi-select.tsx
└── fonts/ # Fellix Aircall font files
样式系统
组件使用 差异管理局(CVA) 基于变体的样式:
const buttonVariants = cva('base-classes', {
variants: {
variant: {
default: 'variant-specific-classes',
outline: 'outline-specific-classes'
}
},
defaultVariants: {
variant: 'default'
}
});
该条规定:
- 类型安全变种道具
- 自动类型脚本推论
- 可组成类生成
- 通过 TailwindCSS 类合并
tailwind-merge
主题系统
设计系统使用带有OKLch色彩空间的CSS变量来更好的色彩感知:
/* Light mode (default) */
:root {
--primary: oklch(52.42% 0.201 192.01);
}
/* Dark mode */
[data-theme='dark'] {
--primary: oklch(78.09% 0.128 192.01);
}
颜色在 data-theme="dark" 设置在根元素上.
食谱(阴影登记)
食谱是建在顶部的预建、复制-粘贴组件模式 @aircall/ds 原始的 原始的 原始的 他们通过 阴影登记册 ——消费者运行 shadcn add 在他们的项目中安装一个食谱,然后他们拥有代码。 他们可以随意定制.
注:在阴影登记图中,这些物品被打入
registry:block——那是"阴影"的值,不是我们的名词. 内部我们称之为"recipes".
书记官处是什么?
注册是一套JSON文件,用来描述每种食谱——它的名称,描述,npm依赖,以及完整的源代码. 这些 JSON 文件由 shadcn build 并且作为静态文件 与DS的故事本.
如何运作:
- 食谱源文件存在
src/recipes/使用相对进口量../components/combobox(中文(简体) ) pnpm run registry:build复制食谱、重写进口到@aircall/ds运行shadcn build,并输出 JSON 文件到public/r/- 故事书服务
public/作为静态文件通过staticDirs配置 - 一个消费者跑
shadcn add <url>——CLI取取JSON,取出源代码并写入他们的工程中@aircall/ds进口
地方发展
运行 pnpm run registry:build 在启动 Storybook 生成 JSON 文件之前。 然后开始故事书:
pnpm run registry:build
pnpm run sb:dev
食谱 JSON 文件在 http://localhost:6008/r/<name>.json。您可以在本地测试全部消费流量:
pnpm dlx shadcn@latest add http://localhost:6008/r/combobox-searchable-select.json
制作(出版故事书)
当DS的故事书被部署到 ds.aircall.io,同样的JSON文件在公共URL中提供. 消费者安装配方:
pnpm dlx shadcn@latest add https://ds.aircall.io/r/combobox-searchable-select.json
部署CI任务运行 pnpm sb:build:ds 重播根,该根将映射到 sb:build:deploy 在这个包裹里。 脚本运行 registry:build 先说 storybook build - 故事书 staticDirs: ['../public'] 配置捡起 public/r/ 复制到 storybook-static/r/ 所以JSON把船和部署的"故事本"一起归档. sb:build 登记册本身不捆绑 ——使用 sb:build:deploy (或 pnpm sb:build:ds 当您需要包含登记册时,请输入.
可用的食谱
| 食谱 | 说明 |
|---|---|
combobox-searchable-select | 单选组合框——输入起到触发和搜索过滤的作用 |
combobox-dropdown-search | 按键触发的组合框, 可在下拉内搜索 |
combobox-multi-select | 多选择内置芯片和排入头过滤 |
添加新食谱
- 创建
src/recipes/<name>.tsx- 从../components/ - 添加条目到
registry.json在软件包根 - 在其中添加一个故事
src/stories/从食谱进口的 - 运行
pnpm run registry:build生成 JSON 在public/r/ - 验证时间
http://localhost:6008/r/<name>.json故事书开始后
脚本
# Development
pnpm sb:dev # Start Storybook development server
pnpm lint # Run ESLint
# Building for Distribution
pnpm build:package # Build both JS and CSS for publishing
pnpm build:js # Build JavaScript bundle only
pnpm build:css # Build pre-compiled CSS only
# Registry
pnpm registry:build # Generate recipe JSON files in public/r/
# (rewrites relative imports to @aircall/ds)
# Storybook — three distinct builds
pnpm sb:build # Plain Storybook build. NO registry JSON.
pnpm sb:build:chromatic # Storybook build for Chromatic (--test --stats-json). NO registry JSON.
pnpm sb:build:deploy # Full deployment build: runs registry:build, builds Storybook,
# and copies public/r into storybook-static/r/.
# This is what CI runs (via `pnpm sb:build:ds` at the repo root).
# Testing Package Locally
pnpm pack # Create tarball for local testing
# Component Management
pnpm shadcn:add <component> # Add new shadcn component
# Maintenance
pnpm clean # Remove build artifacts