English · 中文

--- # Contributing Thanks for your interest in contributing to SoybeanUI! This guide covers how to set up the project, follow our conventions, and submit a pull request. ## Table of Contents - [Project Overview](#project-overview) - [Development Setup](#development-setup) - [Development Workflow](#development-workflow) - [AI Skills & Agents](#ai-skills--agents) - [Coding Conventions](#coding-conventions) - [Component Development](#component-development) - [Testing](#testing) - [Documentation](#documentation) - [Commit & Pull Request](#commit--pull-request) ## Project Overview SoybeanUI is a Vue 3 component library built on a **headless / styled separation**: | Package | Path | Responsibility | | --------------------- | -------------------- | ---------------------------------------------------------- | | `@soybeanjs/headless` | `packages/headless/` | Logic, state, accessibility, composables. **Zero styles.** | | `@soybeanjs/ui` | `packages/ui/` | Styled wrappers (UnoCSS). Variants, theme, UI injection. | | Playground | `apps/playground/` | Interactive demos (Vite). | | Docs | `apps/docs/` | Bilingual docs (en / zh-CN). Vite + vite-ssg. | Data flows one way: `headless` → `ui` (never reverse). The UI layer injects styles via `provideXUi(ui)`; headless reads them through `useUiContext`. **Tech stack:** Vue 3 + TypeScript (strict) + UnoCSS + Vitest + pnpm workspaces. ## Development Setup ### Prerequisites - **Node.js** ≥ 20 - **pnpm** ≥ 9 (this repo uses `pnpm@11.5.2`) ### Install ```bash git clone https://github.com/soybeanjs/soybean-ui.git cd soybean-ui pnpm install ``` ### Local Development ```bash # Stub packages for instant source-to-dist linking pnpm stub # Start the playground (hot-reload for component dev) pnpm dev ``` Open the playground URL shown in the terminal to preview your changes in real time. ### Common Commands | Command | Purpose | | -------------------- | ------------------------------------ | | `pnpm dev` | Start playground dev server | | `pnpm build` | Build headless → ui → CSS | | `pnpm lint` | oxlint + eslint (Vue) | | `pnpm fmt` | oxfmt (formatter) | | `pnpm test` | Vitest (happy-dom) | | `pnpm typecheck` | vue-tsc --noEmit | | `pnpm sui headless` | Regenerate headless barrel constants | | `pnpm sui ui` | Regenerate UI barrel constants | | `pnpm sui api` | Regenerate API reference data | | `pnpm sui changelog` | Regenerate changelog data | ## Development Workflow 1. **Pick or create an issue.** Discuss the scope and approach before coding large features. 2. **Create a branch.** Use `codex/` or a descriptive prefix: ```bash git checkout -b feat/your-feature ``` 3. **Implement.** Follow the [Component Development](#component-development) phases below. 4. **Verify.** Run typecheck, lint, format, and tests before committing. 5. **Commit.** Follow the [commit convention](#commit--pull-request). 6. **Open a pull request.** Fill the PR template and link the issue. ## AI Skills & Agents This project provides AI-assisted development tools — **Skills** (workflow shortcuts) and **Agents** (specialized role prompts) — to help you build components faster and more consistently. ### Project-Local Skill | Skill | Trigger | What it does | | ----------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `$soybean-ui-component-development` | Any component work (new, migrate, fix, extend, standardize) | Classifies the component pattern, enforces headless/UI split, guides through all six delivery phases, and checks boundary rules. Lives at `.agents/skills/soybean-ui-component-development/`. | When you invoke `$soybean-ui-component-development`, the skill: - Classifies the task (new component / migration / standards alignment). - Determines the component pattern (multi-slot / compact / single-class). - Enforces the correct phase order: headless → UI → exports → delivery surfaces → verification. - Prevents boundary violations (no styles in headless, no ARIA in UI). ### System Skills Useful for SoybeanUI These skills are available in your Codex environment and are especially useful during SoybeanUI development: | Skill | Use when | | ---------------------- | --------------------------------------------------------------------------------- | | `$a11y-auditor` | Scanning HTML/JSX output for WCAG violations. | | `$a11y-checker` | AI-powered accessibility fix suggestions for components. | | `$a11y-debugging` | Chrome DevTools-based accessibility debugging (focus, labels, contrast). | | `$accessibility-check` | Full semantic structure, keyboard, focus, and label audit with a Markdown report. | | `$code-review` | Comprehensive code review across all concerns before opening a PR. | | `$ai-slop-cleaner` | Anti-slop cleanup and refactoring pass. | | `$analyze` | Read-only deep repository analysis with ranked synthesis. | ### Agent Roles Codex provides specialized **agent roles** (prompt surfaces) that you can route complex subtasks to: | Role | Best for | | ----------------- | ------------------------------------------------------------------------- | | `executor` | Implementation, refactoring, feature work — the default for coding tasks. | | `architect` | System design, boundary decisions, long-horizon tradeoffs. | | `debugger` | Root-cause analysis and regression isolation. | | `code-reviewer` | Comprehensive review before merging. | | `test-engineer` | Test strategy, coverage gaps, flaky-test hardening. | | `designer` | UX/UI architecture and interaction design. | | `verifier` | Completion evidence, claim validation, test adequacy. | | `explore` | Fast repo-local file, symbol, and pattern lookup. | | `code-simplifier` | Simplifies recently modified code without changing behavior. | **Default routing:** Use `executor` for implementation. Use `code-reviewer` before opening a PR. Use `explore` to map existing patterns before starting a new component. Route to specialists only when the task clearly benefits from deeper analysis or specialized review. ## Coding Conventions Normative component rules live in the project skill at `.agents/skills/soybean-ui-component-development/` (`SKILL.md` + `layers.md` + `surfaces.md` + `process.md`). TypeScript functional style and Vue SFC structure are owned by the global `typescript-functional-style` and `vue-sfc-structure` skills (loaded automatically per file type). | Skill section | Applies to | | -------------------------------------------- | ----------------------------------- | | `typescript-functional-style` (global skill) | All `.ts`, `.tsx`, `.vue` files | | `vue-sfc-structure` (global skill) | All `.vue` files | | `process.md` -> Git commit convention | Commit messages, changelogs | | `SKILL.md` + `layers.md` | Component tasks | | `layers.md` -> Headless | `packages/headless/src/components/` | | `layers.md` -> UI layer | `packages/ui/src/components/` | | `layers.md` -> A11y and RTL | ARIA, keyboard, RTL | | `surfaces.md` -> Testing | `packages/ui/test/` | | `surfaces.md` -> Playground | `apps/playground/` | | `surfaces.md` -> Docs | `apps/docs/` | | `process.md` -> Finish checklist | Component completion checklist | ### Key Rules - **No styles in headless.** Not even `hidden` or `sr-only`. - **No ARIA / keyboard logic in UI.** That belongs in headless. - **UnoCSS utility classes only.** No raw CSS / SCSS. - **No `as any`, `@ts-ignore`, or `@ts-expect-error`.** - **Prefer pure functions.** Extract pure logic into `shared.ts` or composables. - **Check `@vueuse/core` first** before writing a new composable from scratch. - **Never manually edit generated files** (barrel constants, API JSON, changelog JSON). ## Component Development A new component goes through six phases. See `.agents/skills/soybean-ui-component-development/SKILL.md` for the full specification. ### Phase 0 — Determine Mode & Scope Decide which pattern the component follows: - **Multi-slot** (badge, dialog, accordion…) — uses `UiSlot`, `UiClass`, `provideXUi`. - **Compact aggregation** (AccordionCompact, TableCompact…) — headless owns iteration and structure. - **Single-class** (button, link…) — no UiContext, direct variant call. ### Phase 1 — Reference Study Study at least one existing component of the same pattern in both `headless` and `ui`. ### Phase 2 — Headless Implementation Files in `packages/headless/src/components//`, in order: 1. `types.ts` — slots, props, emits, context. 2. `context.ts` — provide/inject, reactive context values. 3. Base SFCs — one per slot (Root, Trigger, Content, Item…). 4. Optional `{Name}Compact.vue` — stable aggregation. 5. `index.ts` — re-exports. ### Phase 3 — UI Implementation Files in `packages/ui/src/components//`: 1. `packages/ui/src/styles/.ts` — style recipe (first line: `// @unocss-include`). 2. `types.ts` — wrapper props. 3. Wrapper `.vue` — injects styles, forwards props/slots. 4. `index.ts` — re-exports (including headless types). ### Phase 4 — Barrel Exports & Generated Files ```bash # Update barrel index files pnpm sui headless pnpm sui ui # If public API changed pnpm sui api pnpm sui api-translate -- --locale zh-CN ``` ### Phase 5 — Delivery Surfaces - **Playground demo:** `apps/playground/src/examples//` - **Docs (en):** `apps/docs/src/docs/en/components/.md` - **Docs (zh-CN):** `apps/docs/src/docs/zh-CN/components/.md` - **Menu:** update `apps/docs/src/constants/menus.ts` - **Tests:** `packages/ui/test/specs/components/.spec.ts` ### Phase 6 — Verification ```bash pnpm typecheck pnpm lint pnpm fmt pnpm test ``` If any step fails, fix it before opening a PR. See the full checklist in `.agents/skills/soybean-ui-component-development/process.md`. ## Testing - **Framework:** Vitest + `@vue/test-utils` + `happy-dom` - **Location:** `packages/ui/test/specs/components/.spec.ts` - **Required sections:** `rendering`, `{state} state`, `disabled state`, `accessibility` - **Rule:** every `it()` block mounts and unmounts independently. - **Accessibility:** use `axe-core` via `getA11yViolations`. ```bash # Run all tests pnpm test # Run a specific component test pnpm vitest packages/ui/test/specs/components/button.spec.ts ``` ## Documentation Docs live under `apps/docs/src/docs//components/`. Every component needs both English (`en`) and Chinese (`zh-CN`) documentation with matching structure. API reference data is auto-generated. After changing public exports: ```bash pnpm sui api # Regenerate baseline pnpm sui api-translate -- --locale zh-CN # Translate descriptions ``` ## Commit & Pull Request ### Commit Convention We follow **Conventional Commits** with mandatory scope: ``` (): ``` Examples: - `feat(button): add loading slot and loading prop` - `fix(dialog): prevent outside click from closing nested popup` - `docs(table): document remote pagination` **Types:** `feat`, `fix`, `perf`, `refactor`, `docs`, `chore` **Scope:** prefer the exact component name (e.g., `button`, `dialog`). Use broader scopes (`ui`, `headless`, `composables`, `shared`, `docs`, `build`, `deps`) only when the change is truly cross-cutting. **Subject:** imperative, specific, and outcome-oriented. No trailing period. Full rules: `.agents/skills/soybean-ui-component-development/process.md`. ### Pull Request Guidelines - One PR = one logical change. Prefer small, focused PRs. - Link the related issue. - Run the formatter locally, then ensure CI passes (typecheck, lint, tests, and browser e2e). - If the PR adds a new component, include playground demos and bilingual docs. - Keep the PR description concise: what, why, and how to verify. --- # 参与贡献 感谢你对 SoybeanUI 的关注!本指南涵盖项目搭建、规范遵循和 PR 提交流程。 ## 目录 - [项目概览](#项目概览) - [开发环境搭建](#开发环境搭建) - [开发流程](#开发流程) - [AI Skills 与智能体](#ai-skills-与智能体) - [编码规范](#编码规范) - [组件开发](#组件开发) - [测试](#测试) - [文档](#文档) - [Commit 与 Pull Request](#commit-与-pull-request) ## 项目概览 SoybeanUI 是一个基于 **headless / styled 分层架构** 的 Vue 3 组件库: | 包 | 路径 | 职责 | | --------------------- | -------------------- | -------------------------------------------- | | `@soybeanjs/headless` | `packages/headless/` | 逻辑、状态、无障碍、composable。**零样式。** | | `@soybeanjs/ui` | `packages/ui/` | 样式包装(UnoCSS)。变体、主题、UI 注入。 | | Playground | `apps/playground/` | 交互式示例(Vite)。 | | Docs | `apps/docs/` | 中英文档。Vite + vite-ssg。 | 数据流单向:`headless` → `ui`(不可反向)。UI 层通过 `provideXUi(ui)` 注入样式; headless 通过 `useUiContext` 读取。 **技术栈:** Vue 3 + TypeScript (strict) + UnoCSS + Vitest + pnpm workspaces。 ## 开发环境搭建 ### 前置条件 - **Node.js** ≥ 20 - **pnpm** ≥ 9(本仓库使用 `pnpm@11.5.2`) ### 安装 ```bash git clone https://github.com/soybeanjs/soybean-ui.git cd soybean-ui pnpm install ``` ### 本地开发 ```bash # 建立源码到构建产物的软链接 pnpm stub # 启动 playground(组件开发热更新) pnpm dev ``` 打开终端输出的 playground 地址,即可实时预览改动。 ### 常用命令 | 命令 | 用途 | | -------------------- | ----------------------------- | | `pnpm dev` | 启动 playground 开发服务器 | | `pnpm build` | 构建 headless → ui → CSS | | `pnpm lint` | oxlint + eslint(Vue) | | `pnpm fmt` | oxfmt(格式化) | | `pnpm test` | Vitest(happy-dom) | | `pnpm typecheck` | vue-tsc --noEmit | | `pnpm sui headless` | 重新生成 headless barrel 常量 | | `pnpm sui ui` | 重新生成 UI barrel 常量 | | `pnpm sui api` | 重新生成 API 参考数据 | | `pnpm sui changelog` | 重新生成 changelog 数据 | ## 开发流程 1. **选择或创建 issue。** 大型功能先讨论范围和方案再动手。 2. **创建分支。** 使用 `codex/` 或描述性前缀: ```bash git checkout -b feat/你的功能 ``` 3. **实现。** 按照下方 [组件开发](#组件开发) 的阶段顺序推进。 4. **验证。** 提交前运行 typecheck、lint、format 和测试。 5. **Commit。** 遵循 [commit 规范](#commit-与-pull-request)。 6. **提交 PR。** 填写 PR 模板并关联 issue。 ## AI Skills 与智能体 本项目提供了 AI 辅助开发工具 —— **Skills**(工作流快捷方式)和 **Agents**(专用角色 prompt) —— 帮助你更快、更一致地构建组件。 ### 项目本地 Skill | Skill | 触发条件 | 功能 | | ----------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `$soybean-ui-component-development` | 任何组件工作(新建、迁移、修复、扩展、规范化) | 分类组件模式,强制执行 headless/UI 分层,引导完成全部六个交付阶段,并检查边界规则。位于 `.agents/skills/soybean-ui-component-development/`。 | 当你调用 `$soybean-ui-component-development` 时,该 skill 会: - 分类任务(新建组件 / 迁移 / 规范化对齐)。 - 确定组件模式(多 slot / compact 聚合 / 单类名)。 - 强制执行正确的阶段顺序:headless → UI → 导出 → 交付面 → 验证。 - 防止边界违规(headless 中无样式,UI 中无 ARIA)。 ### SoybeanUI 开发相关的系统 Skill 以下 skills 在你的 Codex 环境中可用,在 SoybeanUI 开发中尤其有用: | Skill | 使用场景 | | ---------------------- | ---------------------------------------------------------- | | `$a11y-auditor` | 扫描 HTML/JSX 输出中的 WCAG 违规。 | | `$a11y-checker` | AI 驱动的组件无障碍修复建议。 | | `$a11y-debugging` | 基于 Chrome DevTools 的无障碍调试(焦点、标签、对比度)。 | | `$accessibility-check` | 完整的语义结构、键盘、焦点和标签审计,生成 Markdown 报告。 | | `$code-review` | 提 PR 前的全面代码审查。 | | `$ai-slop-cleaner` | 反 AI slop 清理和重构。 | | `$analyze` | 只读深度仓库分析,带排序综合报告。 | ### Agent 角色 Codex 提供专门的 **agent 角色**(prompt 面),你可以将复杂子任务路由给它们: | 角色 | 最适合 | | ----------------- | -------------------------------------------- | | `executor` | 实现、重构、功能开发 —— 编码任务的默认选择。 | | `architect` | 系统设计、边界决策、长期权衡。 | | `debugger` | 根因分析和回归隔离。 | | `code-reviewer` | 合并前的全面审查。 | | `test-engineer` | 测试策略、覆盖率缺口、flake 测试加固。 | | `designer` | UX/UI 架构和交互设计。 | | `verifier` | 完成证据、声明验证、测试充分性。 | | `explore` | 快速仓库内文件、符号和模式查找。 | | `code-simplifier` | 简化最近修改的代码而不改变行为。 | **默认路由:** 实现用 `executor`。提 PR 前用 `code-reviewer`。开始新组件前用 `explore` 映射已有模式。仅在任务明确受益于更深入分析或专项审查时路由到专家角色。 ## 编码规范 组件规范统一位于项目 skill `.agents/skills/soybean-ui-component-development/`(`SKILL.md` + `layers.md` + `surfaces.md` + `process.md`)。TypeScript 函数式风格与 Vue SFC 结构由全局 skill `typescript-functional-style` 和 `vue-sfc-structure` 负责(按文件类型自动加载)。 | Skill 章节 | 适用范围 | | ------------------------------------------- | ----------------------------------- | | `typescript-functional-style`(全局 skill) | 所有 `.ts`、`.tsx`、`.vue` 文件 | | `vue-sfc-structure`(全局 skill) | 所有 `.vue` 文件 | | `process.md` -> Git commit 规范 | Commit message、changelog | | `SKILL.md` + `layers.md` | 组件任务 | | `layers.md` -> Headless | `packages/headless/src/components/` | | `layers.md` -> UI layer | `packages/ui/src/components/` | | `layers.md` -> A11y and RTL | ARIA、键盘、RTL | | `surfaces.md` -> Testing | `packages/ui/test/` | | `surfaces.md` -> Playground | `apps/playground/` | | `surfaces.md` -> Docs | `apps/docs/` | | `process.md` -> Finish checklist | 组件完成清单 | ### 核心规则 - **headless 中禁止样式。** 连 `hidden` 或 `sr-only` 也不行。 - **UI 层禁止 ARIA / 键盘逻辑。** 这些属于 headless。 - **仅使用 UnoCSS 工具类。** 禁止裸 CSS / SCSS。 - **禁止 `as any`、`@ts-ignore`、`@ts-expect-error`。** - **优先纯函数。** 将纯逻辑提取到 `shared.ts` 或 composable。 - **新增 composable 前先检查 `@vueuse/core`。** 避免从零重写常见能力。 - **禁止手动编辑生成文件**(barrel 常量、API JSON、changelog JSON)。 ## 组件开发 一个新组件经过六个阶段。详见 `.agents/skills/soybean-ui-component-development/SKILL.md`。 ### Phase 0 — 确定模式与范围 判断组件属于哪种模式: - **多 slot**(badge、dialog、accordion…)—— 使用 `UiSlot`、`UiClass`、`provideXUi`。 - **Compact 聚合**(AccordionCompact、TableCompact…)—— headless 负责迭代与结构。 - **单类名**(button、link…)—— 无 UiContext,直接调用 variant。 ### Phase 1 — 参照学习 至少阅读一个同模式的 headless 参考和一个 UI 参考。 ### Phase 2 — Headless 实现 文件在 `packages/headless/src/components//`,按顺序: 1. `types.ts` — slots、props、emits、context。 2. `context.ts` — provide/inject,响应式 context 值。 3. 基础 SFC — 每个 slot 一个文件(Root、Trigger、Content、Item…)。 4. 可选 `{Name}Compact.vue` — 稳定聚合。 5. `index.ts` — 重导出。 ### Phase 3 — UI 实现 文件在 `packages/ui/src/components//`: 1. `packages/ui/src/styles/.ts` — 样式配方(首行:`// @unocss-include`)。 2. `types.ts` — wrapper props。 3. wrapper `.vue` — 注入样式,转发 props/slots。 4. `index.ts` — 重导出(含 headless 类型)。 ### Phase 4 — Barrel 导出与生成文件 ```bash # 更新 barrel index 文件 pnpm sui headless pnpm sui ui # 如果公开 API 有变化 pnpm sui api pnpm sui api-translate -- --locale zh-CN ``` ### Phase 5 — 交付面 - **Playground 示例:** `apps/playground/src/examples//` - **英文文档:** `apps/docs/src/docs/en/components/.md` - **中文文档:** `apps/docs/src/docs/zh-CN/components/.md` - **菜单:** 更新 `apps/docs/src/constants/menus.ts` - **测试:** `packages/ui/test/specs/components/.spec.ts` ### Phase 6 — 验证 ```bash pnpm typecheck pnpm lint pnpm fmt pnpm test ``` 任一步骤失败,请在提 PR 前修复。完整清单见 `.agents/skills/soybean-ui-component-development/process.md`。 ## 测试 - **框架:** Vitest + `@vue/test-utils` + `happy-dom` - **位置:** `packages/ui/test/specs/components/.spec.ts` - **必须覆盖:** `rendering`、`{state} state`、`disabled state`、`accessibility` - **规则:** 每个 `it()` 块独立挂载和卸载。 - **无障碍:** 使用 `axe-core` 通过 `getA11yViolations` 检查。 ```bash # 运行全部测试 pnpm test # 运行指定组件测试 pnpm vitest packages/ui/test/specs/components/button.spec.ts ``` ## 文档 文档位于 `apps/docs/src/docs//components/`。每个组件需要中英文文档,结构一致。 API 参考数据自动生成。公开导出变化后: ```bash pnpm sui api # 重新生成基线 pnpm sui api-translate -- --locale zh-CN # 翻译描述 ``` ## Commit 与 Pull Request ### Commit 规范 遵循 **Conventional Commits**,scope 必填: ``` (): ``` 示例: - `feat(button): add loading slot and loading prop` - `fix(dialog): prevent outside click from closing nested popup` - `docs(table): document remote pagination` **类型:** `feat`、`fix`、`perf`、`refactor`、`docs`、`chore` **Scope:** 优先精确组件名(如 `button`、`dialog`)。仅在真正跨领域时使用宽 scope (`ui`、`headless`、`composables`、`shared`、`docs`、`build`、`deps`)。 **Subject:** 祈使语气,具体,面向结果。不以句号结尾。 完整规范:`.agents/skills/soybean-ui-component-development/process.md`。 ### Pull Request 指南 - 一个 PR = 一个逻辑变更。优先小 PR。 - 关联相关 issue。 - 先在本地运行格式化,再确保 CI 通过(typecheck、lint、tests 与 browser e2e)。 - 新增组件须包含 playground 示例和中英文档。 - PR 描述简洁:做了什么、为什么、如何验证。