AgentSkillsCN

react-render-types-composition

使用@renders类型注解构建React组件的组合模式,配合eslint-plugin-react-render-types插件。适用于以下场景:(1) 编写需要@renders JSDoc注解的React组件;(2) 构建强制组件组合的设计系统(例如,Menu组件仅接受MenuItem组件);(3) 决定使用哪种@renders修饰符(必选、可选、多选、未校验);(4) 创建包装组件或透明组件;(5) 为children/header/footer等插槽属性添加注解;(6) 使用@renders与渲染链、联合类型或类型别名结合;(7) 构建消费@renders注解设计系统的应用布局。

SKILL.md
--- frontmatter
name: react-render-types-composition
description: "Composition patterns for building React components with @renders type annotations from eslint-plugin-react-render-types. Use when: (1) writing React components that need @renders JSDoc annotations, (2) building a design system with enforced component composition (e.g., Menu only accepts MenuItem), (3) deciding which @renders modifier to use (required, optional, many, unchecked), (4) creating wrapper or transparent components, (5) annotating slot props like children/header/footer, (6) using render chains, union types, or type aliases with @renders, or (7) building app layouts that consume a @renders-annotated design system."

React Render Types — Composition Patterns

Patterns for building React components with @renders type annotations. Covers design system primitives, app-level composition, and advanced techniques.

Annotation Syntax Quick Reference

code
@renders {X}           Required — must return X
@renders? {X}          Optional — may return X or null
@renders* {X}          Many — zero or more X
@renders! {X}          Unchecked — declares X, skips return validation
@renders {A | B}       Union — must return A or B
@renders {MyAlias}     Type alias — resolves type MyAlias = A | B at lint time
@transparent           Wrapper — plugin looks through to validate children
                       (or use additionalTransparentComponents setting for built-ins)

Pattern Categories

PriorityCategoryWhen to read
1Design System PatternsBuilding constrained component APIs
2Wrapper PatternsCreating transparent or conditional wrappers
3App Composition PatternsConsuming a design system in app layouts
4Advanced PatternsUnions, chains, dynamic rendering, expressions

Design System Patterns

Core patterns for building component libraries with enforced composition.

  • constrained-children — Restrict children to specific component types (Menu → MenuItem)
  • typed-slot-props — Enforce types on named slot props (header, footer, sidebar)
  • component-variants — Create specialized variants that satisfy a base render type

Read detailed examples: references/patterns/design-system.md

Wrapper Patterns

Patterns for components that wrap other content without breaking composition.

  • transparent-wrappers — Mark layout/styling wrappers with @transparent
  • conditional-rendering — Use @renders? and @renders* for optional/repeated content

Read detailed examples: references/patterns/wrappers.md

App Composition Patterns

Patterns for building app-level layouts that consume design system components.

  • page-layouts — Compose pages with typed header/content/footer slots
  • dashboard-composition — Build dashboards with constrained card/widget areas
  • navigation-structure — Typed sidebar/nav with enforced nav item types

Read detailed examples: references/patterns/app-composition.md

Advanced Patterns

Techniques for complex scenarios.

  • union-types — Accept multiple component types in a single slot
  • type-aliases — Define reusable type unions for @renders annotations
  • render-chains — Satisfy render types transitively through intermediate components
  • unchecked-escape-hatch — Use @renders! for dynamic rendering the plugin can't analyze
  • expression-analysis — Ternary, logical AND, and .map() in annotated returns

Read detailed examples: references/patterns/advanced.md

Choosing the Right Modifier

code
Can the slot be empty?
├── No → Must always render something
│   ├── Exactly one component → @renders {X}
│   └── One of several types  → @renders {A | B}
└── Yes
    ├── Zero or one component  → @renders? {X}
    └── Zero or more instances → @renders* {X}

Can the plugin analyze the return?
├── Yes → use the modifier above
└── No (dynamic/registry) → add ! → @renders! {X}, @renders?! {X}, @renders*! {X}