soybean-ui-component-development
GitHubSoybeanUI组件开发规范,涵盖新建、迁移、扩展、标准化及审计流程。指导Headless与UI分离架构下的组件实现、模式分类及交付标准。
Trigger Scenarios
Install
npx skills add soybeanjs/soybean-ui --skill soybean-ui-component-development -g -y
SKILL.md
Frontmatter
{
"name": "soybean-ui-component-development",
"description": "Builds, updates, and audits SoybeanUI components with headless\/UI split, delivery phases, and generation workflow. Invoke when adding, migrating, extending, standardizing, fixing, or auditing components, or when work touches packages\/headless\/src\/components, packages\/ui\/src\/components, apps\/playground\/src\/examples, apps\/docs\/src\/docs, or packages\/ui\/test\/specs\/components."
}
SoybeanUI Component Development
This skill is the single, self-contained source of truth for SoybeanUI component work. It owns pattern classification, phase order, layer rules, delivery surfaces, generation workflow, and the finish-stage checklist. Load it for any task that creates, migrates, extends, standardizes, fixes, or audits a SoybeanUI component.
For detailed rules, see layers.md (implementation layers), surfaces.md (delivery surfaces), e2e.md (browser e2e testing), process.md (finish checklist and commit convention), and audit.md (assessment methodology, seven check dimensions, and regression flows for already-shipped components). For request shapes that trigger this skill, see EXAMPLES.md. TypeScript functional style and Vue SFC structure are owned by the global typescript-functional-style and vue-sfc-structure skills — load them directly; this skill does not restate their content.
Repository context
- Monorepo: pnpm workspaces (private root + 9 child workspaces)
- Stack: Vue 3 + TypeScript (strict) + UnoCSS +
@soybeanjs/cva - Architecture: headless / styled separation. Compile-time dependency is
packages/ui->packages/headless; headless never imports UI. @soybeanjs/headless(packages/headless/): Logic, state, a11y, structure. Zero styles.@soybeanjs/ui(packages/ui/): Styled wrappers. UnoCSS +cv()/scv().S-prefixed components.@soybeanjs/ui-docs(apps/docs/): Vite + vite-ssg + unplugin-vue-markdown + markdown-exit. NOT VitePress.
Quick start
- Classify the task before editing.
- Component pattern: multi-slot base, compact aggregation, or single-class.
- Scenario: new component, migration or normalization, standards alignment, or audit and evaluation.
- Delivery scope: headless only, UI only, or full surface.
- Find concrete local references.
- Inspect at least one neighboring same-pattern headless implementation and one UI implementation before editing.
- For migration, preserve behavior, state, accessibility, slots, and public API before restructuring.
- Reuse existing building blocks first.
- Prefer
packages/headless/src/composables/,packages/headless/src/shared/, andpackages/headless/src/types/. - If the repository has no suitable composable, check
@vueuse/core. - Only add a new composable, helper, or type when both are insufficient, and state that reason in the result.
- Prefer
Example: "migrate a compound widget into SoybeanUI" usually means migration scenario + multi-slot or compact pattern + full delivery surface.
Example: "audit the dialog component against industry baselines" means audit scenario + follow audit.md for the assessment flow, seven check dimensions, and regression rules.
Component patterns
Multi-slot base component
- Headless exposes multiple slot primitives.
- Uses
UiSlotandUiClass<UiSlot>. - UI injects classes through
provide{Name}Ui(ui). - Examples: badge, accordion, dialog.
Compact aggregation
- Use when structure is stable and data-driven.
- Headless owns iteration, default content, structure, and non-style orchestration via
{Name}Compact. - UI wrappers stay thin: only variants, class injection, prop/listener forwarding, and slot forwarding.
- Exposes
{Name}CompactProps/{Name}CompactEmits/{Name}CompactSlots. - Current examples: accordion, card, date-field, dialog, editable, hover-card, layout, navigation-menu, pagination, popover, stepper, table flows.
Single-class component
- No UiContext.
- UI composes classes directly from variants and
props.classvia{name}Variants({...}, props.class). - Examples: button, link.
Workflows
New or migrated component
- Build headless first.
types.ts->context.ts-> base slot SFCs -> optional{Name}Compact->index.ts.
- Build UI second.
packages/ui/src/styles/{name}.ts->types.ts-> wrapper.vue->index.ts.
- Complete exports and generated surfaces.
- Update
packages/headless/src/index.tsandpackages/ui/src/index.ts. - Run
pnpm sui headlessandpnpm sui ui. - Do not hand-edit generated files.
- Update
- Complete delivery surfaces unless the user explicitly narrows scope.
apps/playground/src/examples/ui/{component}/apps/docs/src/docs/en/ui/components/{component}.mdapps/docs/src/docs/zh-CN/ui/components/{component}.mdapps/docs/src/constants/menus.tspackages/ui/test/specs/components/{component}.spec.ts- Run
pnpm sui apiwhen public API changes; for non-English locales runpnpm sui api-translate -- --locale <locale>. - Run
pnpm sui changelogandpnpm sui changelog-translate -- --locale <locale>when changelog mapping or release-facing surfaces change.
Existing component fix or extension
- Decide whether the change belongs to headless logic or UI wrapping.
- Preserve the boundary:
- No styles in headless (not even
hidden,sr-only). - No ARIA,
role,tabindex, or keyboard semantics in UI. - No reverse dependency from
packages/headlesstopackages/ui.
- No styles in headless (not even
- Check whether playground, docs, tests, exports, or generated API data must move with the change.
- If a new composable, helper, or type is introduced, explain why existing repository utilities and
@vueuse/corewere insufficient.
Audit and evaluation of shipped components
- Load audit.md for the full assessment methodology, seven check dimensions (D1–D7, 105 items), severity levels, acceptance states, and regression rules.
- Run the eight-step assessment flow from audit.md -> Assessment flow. Grade every finding by severity; do not start the next component while a Blocker is open.
- For D2 industry benchmarking, follow audit.md -> Industry benchmarking (six libraries) and record concrete findings.
- Apply the audit.md -> Single-component acceptance checklist before marking the component passed.
- After each category, run the cross-component consistency regression from audit.md -> Cross-component consistency regression. After all components, run the full regression.
Phase order
Execute in this order. Do not skip ahead until the current phase is done.
Phase 0: Classify pattern, scenario, and scope
- Determine component pattern, task scenario, and whether this is full delivery.
- Do not write code first and reverse-engineer the pattern.
Phase 1: Find reference implementations
- Inspect at least one same-pattern headless reference and one UI reference.
- Migration (scenario B): catalog behavior, state, a11y, slots, and public API that must be preserved.
- Standards alignment (scenario C): list the gap inventory.
- Audit and evaluation (scenario D): the gap inventory is the assessment itself — follow audit.md instead of the implementation phases below.
Phase 2: Implement headless
- Default order:
types.ts->context.ts-> base slot SFCs -> optional{Name}Compact->index.ts. - See layers.md -> Headless for layer rules.
Phase 3: Implement UI
- Default order:
packages/ui/src/styles/{name}.ts->types.ts-> wrapper.vue->index.ts. - See layers.md -> UI layer for layer rules.
Phase 4: Wire exports and generated files
- Update
packages/headless/src/index.tsandpackages/ui/src/index.ts. - Run
pnpm sui headlessandpnpm sui ui. - Do not hand-edit generated files.
Phase 5: Complete delivery surfaces
- Playground: see surfaces.md -> Playground.
- Docs: see surfaces.md -> Docs.
- Tests: see surfaces.md -> Testing. For interactive components, also add a browser e2e spec — see e2e.md.
- If public API changed, run
pnpm sui api; for non-English locales runpnpm sui api-translate -- --locale <locale>. - If changelog mapping or release surfaces changed, run
pnpm sui changelog; for non-English locales runpnpm sui changelog-translate -- --locale <locale>.
Phase 6: Validate and finish
- Run
pnpm typecheck,pnpm lint,pnpm fmt, and the narrowest relevant test:pnpm vitest packages/ui/test/specs/components/{component}.spec.ts. - If a command cannot run, state the blocker explicitly.
- Apply process.md -> Finish checklist only now.
Boundary rules
- Compile-time dependency must remain
packages/ui->packages/headless. Never import@soybeanjs/uifrompackages/headless. - Headless owns logic, state, accessibility, structure aggregation, and default semantics.
- UI owns variants, UnoCSS classes,
uiinjection, and wrapper composition. - Do not add styles or visual classes in headless (not even
hidden,sr-only). - Do not put ARIA,
role,tabindex, keyboard interaction, or state semantics inpackages/ui/src/components. - Do not hand-edit generated files; update source exports and rerun scripts.
- Avoid adding new helpers before checking existing repository utilities and
@vueuse/core.
Guardrails
- Use
UiClass<UiSlot>(frompackages/headless/src/types), notRecord<UiSlot, ClassValue>. - Props always
extends /** @vue-ignore */ HTMLAttributesto suppress IDE noise; if based onPrimitive,extends PrimitiveWithBaseProps. - Context values must be reactive:
ComputedReforShallowRef. UsetransformPropsToContext(props, keys)for prop-derived fields. use{Name}Ui('root')->ComputedRef<ClassValue>(single slot);use{Name}Ui()-> full map.- For multi-slot wrappers, pass
props.uiand{ root: props.class }directly into thescv()recipe call. - Multi-slot: only export
provide{Name}Uifrom headless barrel; never exportuse{Name}Ui. packages/ui/src/styles/{name}.tsfirst line must be// @unocss-include.slotskeys in style recipe must match headless{Name}UiSlotexactly.useOmitPropsmust includeclassto avoid double-binding.- UI component names use
Sprefix (SButton,SDialog); headless names do not (Button,Dialog). - Never use
as any/@ts-ignore/@ts-expect-error. - Never modify
typed-router.d.ts(auto-generated).
Full delivery surface
New components check every entry; existing component changes sync affected entries:
packages/headless/src/components/{component}/packages/ui/src/components/{component}/packages/headless/src/index.tspackages/ui/src/index.tsapps/playground/src/examples/ui/{component}/apps/docs/src/docs/en/ui/components/{component}.mdapps/docs/src/docs/zh-CN/ui/components/{component}.mdapps/docs/src/constants/menus.tspackages/ui/test/specs/components/{component}.spec.ts
Generated surfaces
Run these after the corresponding source changes. Never hand-edit generated outputs.
pnpm sui headless— regeneratespackages/headless/src/constants/components.tsandpackages/headless/src/namespaced/index.tsfrompackages/headless/src/index.ts.pnpm sui ui— regeneratespackages/ui/src/constants/components.tsfrompackages/ui/src/index.ts.pnpm sui api— regeneratesapps/docs/src/generated/api/*.jsonandapps/docs/src/generated/api-locales/*.jsonbase data.pnpm sui api-locales— regenerates API i18n locale template data without re-running type extraction.pnpm sui api-translate -- --locale <locale>— translates generated English API descriptions into a non-English locale.pnpm sui changelog— regeneratesapps/docs/src/generated/changelog/*.jsonandapps/docs/src/generated/changelog-locales/*.jsonbase data.pnpm sui changelog-translate -- --locale <locale>— translates generated English changelog summaries into a non-English locale.
Build and validation commands
pnpm dev:playground # Playground (Vite)
pnpm dev:docs # Documentation site (Vite SSG)
pnpm build # headless -> ui -> sbean via Vite Plus pack
pnpm build:libs # theme -> ui-uno
pnpm lint # vp lint --fix && package Vue lint
pnpm fmt # vp fmt
pnpm test # recursive UI/headless and sbean tests
pnpm test:e2e # Vitest Browser Mode + Playwright Chromium
pnpm typecheck # recursive workspace type checks
pnpm release # Publish packages (soy release)
pnpm stub # switch headless exports to src (`--reset` restores dist)
- Pre-commit hook (Vite Plus,
.vite-hooks/pre-commit):vp staged. - CI: PR/push typecheck, lint, unit tests, and browser e2e; tag-triggered build/release.
- Formatter: Vite Plus
vp fmt.
Result reporting
In the final handoff, make the following explicit when relevant:
- Component pattern, scenario, and scope.
- Which delivery surfaces were changed or intentionally left unchanged.
- Which generation and validation commands were run.
- Any blocker that prevented validation or full delivery.
- Why a new composable, shared helper, or type was introduced instead of reusing repository utilities or
@vueuse/core.
Version History
-
bf1a724
Current 2026-08-19 21:20
重构技能文档结构,移除旧版指令文件;更新审计维度统计至105项;完善组件开发工作流、模式分类及交付检查清单。
- 96a66f1 2026-07-24 20:28


