【免费下载链接】open-slide
A slide framework built for agents.
本指南基于 open-slide 仓库内置的.agents/skills/vercel-composition-patterns/技能目录(Skill),系统讲解 React 组合模式(Composition Patterns)的核心规则:如何用复合组件(Compound Components)、状态提升(State Lifting)与内部组合(Internal Composition)替代布尔属性泛滥(Boolean Prop Proliferation),并覆盖 React 19 的ref as prop与use()API 变化。读完你将掌握一套可直接落地的组件 API 设计规范,以及该规则库在仓库源码(如 design-provider.tsx)中的真实印证。
规则库总览:结构化、可扩展的组件规范组织方式
本仓库将这套 React 组合规范组织为一个结构化规则库,位于.agents/skills/vercel-composition-patterns/,其主要用途是让 AI Agent 与 LLM 在维护、生成或重构 React 代码时遵循统一的组合模式,同时人类开发者也可直接阅读参考。目录结构如下:
rules/——单条规则文件(每条规则一个文件)_sections.md——章节元数据(标题、影响等级、描述),见 _sections.md_template.md——创建新规则的模板,见 _template.md- 各规则文件,如
area-description.md形式的命名
metadata.json——文档元数据(版本、组织、摘要),见 metadata.jsonAGENTS.md——编译后的完整文档(由各规则汇总生成),见 AGENTS.mdREADME.md——索引入口,见 README.mdSKILL.md——技能描述与触发条件,见 SKILL.md
根据 SKILL.md 的定义,这套规则适用于以下场景:重构带有大量布尔属性的组件、构建可复用的组件库、设计灵活的组件 API、评审组件架构,以及处理复合组件或 Context Provider 相关的任务。规则按优先级分为四个类别:
| 优先级 | 类别 | 影响等级 | 文件名前缀 |
|---|---|---|---|
| 1 | Component Architecture(组件架构) | HIGH | architecture- |
| 2 | State Management(状态管理) | MEDIUM | state- |
| 3 | Implementation Patterns(实现模式) | MEDIUM | patterns- |
| 4 | React 19 APIs | MEDIUM | react19- |
每条规则文件统一包含四部分内容:为什么重要(Why it matters)、错误代码示例与说明(Incorrect)、正确代码示例与说明(Correct)、补充上下文与参考(Additional context and references)。
四大核心原则
规则库在 README.md 中提炼了四条核心原则,所有规则都围绕它们展开:
- 组合优于配置(Composition over configuration)——与其不断添加 props,不如让使用者自行组合;
- 提升你的状态(Lift your state)——状态放在 Provider 中,而不是困在组件内部;
- 组合你的内部实现(Compose your internals)——子组件通过 context 访问共享状态,而不是通过 props 层层透传;
- 显式变体(Explicit variants)——创建
ThreadComposer、EditComposer,而不是带isThread开关的单个Composer。
这套规则的目标很明确:让代码库在规模增长时,对人(人类开发者)和 AI Agent 都更容易维护。下面按四个类别逐一展开。
1. 组件架构(Component Architecture)——HIGH
本类别提供结构化组件的基础模式,用于避免属性泛滥并支持灵活组合。
1.1 避免布尔属性泛滥(CRITICAL)
影响等级:CRITICAL(防止出现不可维护的组件变体)
不要用isThread、isEditing、isDMThread这类布尔属性来定制组件行为。每增加一个布尔属性,组件的可能状态数量就会翻倍,条件逻辑随之指数级膨胀,最终变得不可维护。详细规则见 architecture-avoid-boolean-props.md。
错误示例:布尔属性造成指数级复杂度
function Composer({ onSubmit, isThread, channelId, isDMThread, dmId, isEditing, isForwarding, }: Props) { return ( <form> <Header /> <Input /> {isDMThread ? ( <AlsoSendToDMField id={dmId} /> ) : isThread ? ( <AlsoSendToChannelField id={channelId} /> ) : null} {isEditing ? ( <EditActions /> ) : isForwarding ? ( <ForwardActions /> ) : ( <DefaultActions /> )} <Footer onSubmit={onSubmit} /> </form> ) }正确示例:组合消除条件分支
// Channel composer(频道消息编辑器) function ChannelComposer() { return ( <Composer.Frame> <Composer.Header /> <Composer.Input /> <Composer.Footer> <Composer.Attachments /> <Composer.Formatting /> <Composer.Emojis /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> ) } // Thread composer(话题编辑器)- 额外加入"同时发送到频道"字段 function ThreadComposer({ channelId }: { channelId: string }) { return ( <Composer.Frame> <Composer.Header /> <Composer.Input /> <AlsoSendToChannelField id={channelId} /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> ) } // Edit composer(编辑模式)- 不同的底部操作区 function EditComposer() { return ( <Composer.Frame> <Composer.Input /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.CancelEdit /> <Composer.SaveEdit /> </Composer.Footer> </Composer.Frame> ) }每个变体都显式声明了自己渲染什么。我们可以在不共享一个巨型单体父组件的前提下,共享内部子组件。
1.2 使用复合组件(Compound Components)
影响等级:HIGH(实现无需 prop drilling 的灵活组合)
将复杂组件结构化为"复合组件 + 共享 context"。每个子组件通过 context 而非 props 访问共享状态,使用方按需拼装所需部件。详细规则见 architecture-compound-components.md。
错误示例:带 render props 的单体组件
function Composer({ renderHeader, renderFooter, renderActions, showAttachments, showFormatting, showEmojis, }: Props) { return ( <form> {renderHeader?.()} <Input /> {showAttachments && <Attachments />} {renderFooter ? ( renderFooter() ) : ( <Footer> {showFormatting && <Formatting />} {showEmojis && <Emojis />} {renderActions?.()} </Footer> )} </form> ) }正确示例:带共享 context 的复合组件
const ComposerContext = createContext<ComposerContextValue | null>(null) function ComposerProvider({ children, state, actions, meta }: ProviderProps) { return ( <ComposerContext value={{ state, actions, meta }}> {children} </ComposerContext> ) } function ComposerFrame({ children }: { children: React.ReactNode }) { return <form>{children}</form> } function ComposerInput() { const { state, actions: { update }, meta: { inputRef }, } = use(ComposerContext) return ( <TextInput ref={inputRef} value={state.input} onChangeText={(text) => update((s) => ({ ...s, input: text }))} /> ) } function ComposerSubmit() { const { actions: { submit }, } = use(ComposerContext) return <Button onPress={submit}>Send</Button> } // 以复合组件形式导出 const Composer = { Provider: ComposerProvider, Frame: ComposerFrame, Input: ComposerInput, Submit: ComposerSubmit, Header: ComposerHeader, Footer: ComposerFooter, Attachments: ComposerAttachments, Formatting: ComposerFormatting, Emojis: ComposerEmojis, }使用方式:
<Composer.Provider state={state} actions={actions} meta={meta}> <Composer.Frame> <Composer.Header /> <Composer.Input /> <Composer.Footer> <Composer.Formatting /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> </Composer.Provider>使用方显式组合自己需要的部分,没有隐藏的条件分支;state、actions、meta由父级 Provider 依赖注入,同一组件结构可以被多处复用。
2. 状态管理(State Management)——MEDIUM
本类别提供状态提升与跨复合组件共享 context 的模式。
2.1 将状态管理与 UI 解耦
影响等级:MEDIUM(可在不修改 UI 的前提下替换状态实现)
Provider 组件应当是唯一知晓"状态如何被管理"的地方。UI 组件只消费 context 接口——它们不关心状态来自useState、Zustand 还是服务端同步。详细规则见 state-decouple-implementation.md。
错误示例:UI 耦合状态实现
function ChannelComposer({ channelId }: { channelId: string }) { // UI 组件竟然知道全局状态实现 const state = useGlobalChannelState(channelId) const { submit, updateInput } = useChannelSync(channelId) return ( <Composer.Frame> <Composer.Input value={state.input} onChange={(text) => sync.updateInput(text)} /> <Composer.Submit onPress={() => sync.submit()} /> </Composer.Frame> ) }正确示例:状态管理隔离在 Provider 中
// Provider 处理全部状态管理细节 function ChannelProvider({ channelId, children, }: { channelId: string children: React.ReactNode }) { const { state, update, submit } = useGlobalChannel(channelId) const inputRef = useRef(null) return ( <Composer.Provider state={state} actions={{ update, submit }} meta={{ inputRef }} > {children} </Composer.Provider> ) } // UI 组件只认识 context 接口 function ChannelComposer() { return ( <Composer.Frame> <Composer.Header /> <Composer.Input /> <Composer.Footer> <Composer.Submit /> </Composer.Footer> </Composer.Frame> ) } // 使用 function Channel({ channelId }: { channelId: string }) { return ( <ChannelProvider channelId={channelId}> <ChannelComposer /> </ChannelProvider> ) }不同 Provider、同一套 UI:
// 临时表单使用本地状态 function ForwardMessageProvider({ children }) { const [state, setState] = useState(initialState) const forwardMessage = useForwardMessage() return ( <Composer.Provider state={state} actions={{ update: setState, submit: forwardMessage }} > {children} </Composer.Provider> ) } // 频道使用全局同步状态 function ChannelProvider({ channelId, children }) { const { state, update, submit } = useGlobalChannel(channelId) return ( <Composer.Provider state={state} actions={{ update, submit }}> {children} </Composer.Provider> ) }同一个Composer.Input组件在两个 Provider 下都能正常工作,因为它只依赖 context 接口而非具体实现。
2.2 为依赖注入定义通用 Context 接口(HIGH)
影响等级:HIGH(让状态可跨用例依赖注入)
为组件 context 定义一个通用接口,包含三个部分:state、actions、meta。该接口是任何 Provider 都可以实现的契约——从而使同一套 UI 组件能与完全不同的状态实现协作。核心原则是:提升状态、组合内部实现、让状态可依赖注入。详细规则见 state-context-interface.md。
错误示例:UI 耦合特定状态实现
function ComposerInput() { // 与某个特定 hook 强耦合 const { input, setInput } = useChannelComposerState() return <TextInput value={input} onChangeText={setInput} /> }正确示例:通用接口开启依赖注入
// 定义一个任何 Provider 都能实现的 GENERIC 接口 interface ComposerState { input: string attachments: Attachment[] isSubmitting: boolean } interface ComposerActions { update: (updater: (state: ComposerState) => ComposerState) => void submit: () => void } interface ComposerMeta { inputRef: React.RefObject<TextInput> } interface ComposerContextValue { state: ComposerState actions: ComposerActions meta: ComposerMeta } const ComposerContext = createContext<ComposerContextValue | null>(null)UI 组件消费接口,而非实现:
function ComposerInput() { const { state, actions: { update }, meta, } = use(ComposerContext) // 该组件可配合任何实现此接口的 Provider 工作 return ( <TextInput ref={meta.inputRef} value={state.input} onChangeText={(text) => update((s) => ({ ...s, input: text }))} /> ) }不同 Provider 实现同一接口:
// Provider A:临时表单的本地状态 function ForwardMessageProvider({ children }: { children: React.ReactNode }) { const [state, setState] = useState(initialState) const inputRef = useRef(null) const submit = useForwardMessage() return ( <ComposerContext value={{ state, actions: { update: setState, submit }, meta: { inputRef }, }} > {children} </ComposerContext> ) } // Provider B:频道的全局同步状态 function ChannelProvider({ channelId, children }: Props) { const { state, update, submit } = useGlobalChannel(channelId) const inputRef = useRef(null) return ( <ComposerContext value={{ state, actions: { update, submit }, meta: { inputRef }, }} > {children} </ComposerContext> ) }同一套组合 UI 兼容两者:
// 配合 ForwardMessageProvider(本地状态) <ForwardMessageProvider> <Composer.Frame> <Composer.Input /> <Composer.Submit /> </Composer.Frame> </ForwardMessageProvider> // 配合 ChannelProvider(全局同步状态) <ChannelProvider channelId="abc"> <Composer.Frame> <Composer.Input /> <Composer.Submit /> </Composer.Frame> </ChannelProvider>组件之外的定制 UI 也可以访问状态与动作:
决定边界的是 Provider 的包裹范围,而不是视觉嵌套关系。需要共享状态的组件不一定要位于Composer.Frame内部,只要在 Provider 范围内即可。
function ForwardMessageDialog() { return ( <ForwardMessageProvider> <Dialog> {/* 编辑器主体 UI */} <Composer.Frame> <Composer.Input placeholder="Add a message, if you'd like." /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> </Composer.Footer> </Composer.Frame> {/* 位于编辑器之外、但仍在 Provider 之内的定制 UI */} <MessagePreview /> {/* 对话框底部的操作区 */} <DialogActions> <CancelButton /> <ForwardButton /> </DialogActions> </Dialog> </ForwardMessageProvider> ) } // 这个按钮位于 Composer.Frame 之外,却仍能基于 context 提交! function ForwardButton() { const { actions: { submit }, } = use(ComposerContext) return <Button onPress={submit}>Forward</Button> } // 这个预览位于 Composer.Frame 之外,却仍能读取编辑器的状态! function MessagePreview() { const { state } = use(ComposerContext) return <Preview message={state.input} attachments={state.attachments} /> }ForwardButton与MessagePreview在视觉上并不位于编辑器框体内,但依然能访问其状态与动作——这正是"把状态提升进 Provider"的力量。UI 是被组合的可复用零件,状态由 Provider 依赖注入:换 Provider,留 UI。
2.3 把状态提升进 Provider 组件(HIGH)
影响等级:HIGH(允许状态跨越组件边界共享)
将状态管理移入独立的 Provider 组件,让主 UI 之外的兄弟组件无需 prop drilling 或别扭的 ref 即可访问、修改状态。详细规则见 state-lift-state.md。
错误示例一:状态被困在组件内部
function ForwardMessageComposer() { const [state, setState] = useState(initialState) const forwardMessage = useForwardMessage() return ( <Composer.Frame> <Composer.Input /> <Composer.Footer /> </Composer.Frame> ) } // 问题:这个按钮如何访问编辑器状态? function ForwardMessageDialog() { return ( <Dialog> <ForwardMessageComposer /> <MessagePreview /> {/* 需要编辑器状态 */} <DialogActions> <CancelButton /> <ForwardButton /> {/* 需要调用 submit */} </DialogActions> </Dialog> ) }错误示例二:用 useEffect 把状态同步上去
function ForwardMessageDialog() { const [input, setInput] = useState('') return ( <Dialog> <ForwardMessageComposer onInputChange={setInput} /> <MessagePreview input={input} /> </Dialog> ) } function ForwardMessageComposer({ onInputChange }) { const [state, setState] = useState(initialState) useEffect(() => { onInputChange(state.input) // 每次变更都同步 😬 }, [state.input]) }错误示例三:提交时才从 ref 读状态
function ForwardMessageDialog() { const stateRef = useRef(null) return ( <Dialog> <ForwardMessageComposer stateRef={stateRef} /> <ForwardButton onPress={() => submit(stateRef.current)} /> </Dialog> ) }正确示例:状态提升到 Provider
function ForwardMessageProvider({ children }: { children: React.ReactNode }) { const [state, setState] = useState(initialState) const forwardMessage = useForwardMessage() const inputRef = useRef(null) return ( <Composer.Provider state={state} actions={{ update: setState, submit: forwardMessage }} meta={{ inputRef }} > {children} </Composer.Provider> ) } function ForwardMessageDialog() { return ( <ForwardMessageProvider> <Dialog> <ForwardMessageComposer /> <MessagePreview /> {/* 定制组件可访问状态与动作 */} <DialogActions> <CancelButton /> <ForwardButton /> {/* 定制组件可访问状态与动作 */} </DialogActions> </Dialog> </ForwardMessageProvider> ) } function ForwardButton() { const { actions } = use(Composer.Context) return <Button onPress={actions.submit}>Forward</Button> }ForwardButton位于Composer.Frame之外,却因为处于 Provider 范围内而依然拥有submit动作的访问权。即便它是一个一次性组件,也能从 UI 外部访问编辑器的状态与动作。
关键洞察:需要共享状态的组件不必在视觉上互相嵌套——它们只需要处于同一个 Provider 之内。
3. 实现模式(Implementation Patterns)——MEDIUM
本类别提供复合组件与 context provider 的具体实现技巧。
3.1 创建显式组件变体(MEDIUM)
影响等级:MEDIUM(代码自文档化,无隐藏条件分支)
与其用一个带大量布尔属性的组件,不如创建显式变体组件。每个变体组合自己需要的零件,代码本身即文档。详细规则见 patterns-explicit-variants.md。
错误示例:一个组件、多种模式
// 这个组件到底渲染了什么? <Composer isThread isEditing={false} channelId='abc' showAttachments showFormatting={false} />正确示例:显式变体
// 立刻清楚它渲染什么 <ThreadComposer channelId="abc" /> // 或者 <EditMessageComposer messageId="xyz" /> // 或者 <ForwardMessageComposer messageId="123" />每个实现都是独特、显式且自包含的,同时又能共享公共零件。
实现方式:
function ThreadComposer({ channelId }: { channelId: string }) { return ( <ThreadProvider channelId={channelId}> <Composer.Frame> <Composer.Input /> <AlsoSendToChannelField channelId={channelId} /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> </ThreadProvider> ) } function EditMessageComposer({ messageId }: { messageId: string }) { return ( <EditMessageProvider messageId={messageId}> <Composer.Frame> <Composer.Input /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.CancelEdit /> <Composer.SaveEdit /> </Composer.Footer> </Composer.Frame> </EditMessageProvider> ) } function ForwardMessageComposer({ messageId }: { messageId: string }) { return ( <ForwardMessageProvider messageId={messageId}> <Composer.Frame> <Composer.Input placeholder="Add a message, if you'd like." /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.Mentions /> </Composer.Footer> </Composer.Frame> </ForwardMessageProvider> ) }每个变体都显式声明了三件事:使用哪个 Provider/状态、包含哪些 UI 元素、暴露哪些动作。不需要推理布尔属性的组合,也不存在"不可能的状态"。
3.2 优先组合 children 而非 render props(MEDIUM)
影响等级:MEDIUM(组合更干净、可读性更好)
使用children进行组合,而不是renderX属性。children更易读、天然支持嵌套组合,也无需理解回调签名。详细规则见 patterns-children-over-render-props.md。
错误示例:render props
function Composer({ renderHeader, renderFooter, renderActions, }: { renderHeader?: () => React.ReactNode renderFooter?: () => React.ReactNode renderActions?: () => React.ReactNode }) { return ( <form> {renderHeader?.()} <Input /> {renderFooter ? renderFooter() : <DefaultFooter />} {renderActions?.()} </form> ) } // 用法笨拙且不灵活 return ( <Composer renderHeader={() => <CustomHeader />} renderFooter={() => ( <> <Formatting /> <Emojis /> </> )} renderActions={() => <SubmitButton />} /> )正确示例:带 children 的复合组件
function ComposerFrame({ children }: { children: React.ReactNode }) { return <form>{children}</form> } function ComposerFooter({ children }: { children: React.ReactNode }) { return <footer className='flex'>{children}</footer> } // 用法灵活 return ( <Composer.Frame> <CustomHeader /> <Composer.Input /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <SubmitButton /> </Composer.Footer> </Composer.Frame> )render props 何时适用:
// 当需要把数据回传给父级时,render props 效果很好 <List data={items} renderItem={({ item, index }) => <Item item={item} index={index} />} />判据很清晰:当父级需要向子级提供数据或状态时用 render props;当组合静态结构时用children。
4. React 19 API 变化(MEDIUM)
⚠️ 仅限 React 19+。使用 React 18 或更早版本时请跳过本节。详细规则见 react19-no-forwardref.md。
在 React 19 中,ref成为普通 prop(不再需要forwardRef包裹),且use()取代了useContext()。这两项变化让组件定义与 context 消费都更简洁。
错误示例:React 19 里仍用 forwardRef
const ComposerInput = forwardRef<TextInput, Props>((props, ref) => { return <TextInput ref={ref} {...props} /> })正确示例:ref 作为普通 prop
function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) { return <TextInput ref={ref} {...props} /> }错误示例:React 19 里仍用 useContext
const value = useContext(MyContext)正确示例:用 use 取代 useContext
const value = use(MyContext)此外,use()还可以在条件分支中调用,这是useContext()做不到的——这也使得它在复合组件内部的组合使用更加灵活(前述所有示例中的use(ComposerContext)正是该 API 的落地用法)。
5. 如何创建一条新规则
规则库设计为可持续扩展的规范集合。新增一条规则的流程(见 README.md 与 _template.md):
- 复制
rules/_template.md为rules/area-description.md; - 选择合适的分区前缀:
architecture-用于 Component Architecture(组件架构)state-用于 State Management(状态管理)patterns-用于 Implementation Patterns(实现模式)react19-用于 React 19 APIs(见 _sections.md 中定义的分区 ID)
- 填写 frontmatter 与正文内容;
- 确保包含带解释的清晰示例。
模板的 frontmatter 结构如下:
--- title: Rule Title Here impact: MEDIUM impactDescription: brief description of impact tags: composition, components ---正文结构则固定为:规则标题与简介 →Incorrect(坏代码示例)→Correct(好代码示例)→ 参考链接。这种"错误/正确对照 + 影响等级 + 标签"的格式,正是为了让 Agent 与 LLM 能以可预测的方式消费每条规则。
6. 影响等级体系
规则库用三档影响等级标注每条规则的重要性(见 README.md 与 _sections.md):
CRITICAL——基础性模式,防止产生不可维护的代码(如避免布尔属性泛滥);HIGH——显著的可维护性提升(如复合组件、通用 context 接口、状态提升);MEDIUM——让代码更干净的良好实践(如显式变体、children 优先、React 19 API)。
在 metadata.json 中,该规则库的版本为 1.0.0,归属 Engineering 组织,日期为 2026 年 1 月,其摘要强调"避免布尔属性泛滥,通过复合组件、状态提升与内部组合构建灵活且可维护的 React 组件",并指出这些模式让代码库在规模化时对人类和 AI Agent 都更易协作。
7. 仓库源码中的真实印证
这套规则并非纸上谈兵——open-slide 仓库自身的源码中就大量实践了"context 接口 + Provider 隔离"的组合模式:
design-provider.tsx 是典型的"接口契约 + Provider 守卫"实现:先定义
DesignCtx接口(包含design/draft/dirty等状态、update/commit/discard/shuffle等动作),再用createContext<DesignCtx | null>(null)创建 context;其消费函数useDesignPanelState()在未处于 Provider 内时抛出useDesignPanelState must be used inside <DesignProvider>的错误——这正是规则 2.2(通用 context 接口)与 2.3(状态提升进 Provider)所强调的"UI 组件只消费接口、状态由 Provider 注入"的实际落地。page-context.tsx 与 step-context.tsx 展示了另一种 context 组织方式:将 context 挂到全局对象键(如
g[GLOBAL_KEY] = createContext<SlidePageContextValue | null>(null)),以规避模块重复实例化带来的 context 不匹配问题。这印证了"复合组件 + 共享 context"在真实框架代码中的常见形态——context 对象本身也值得被当作架构资产来管理。在 step-context.tsx 中,
useContext(StepHostContext)被多个子组件消费,子组件通过 context 而非 props 透传获得宿主状态(如isActivePage),与规则 1.2"子组件通过 context 而非 props 访问共享状态"完全一致。
结语
从 README.md 的规则索引,到 AGENTS.md 的完整编译文档,这套 React 组合模式规则库给出了一个自洽、可执行的组件架构方法论:组合优于配置、状态提升、内部组合、显式变体,并在 React 19 下以ref as prop与use()精简代码。对于正在构建组件库、或打算重构"布尔属性越来越多"的组件的团队而言,可以直接把上述规则文件当作评审清单:每条规则都自带"错误示例 → 正确示例 → 影响等级",既适合人类开发者阅读,也适合作为 Agent 生成与重构代码时的行为约束。下一步,你可以按"如何创建新规则"一节把团队自己的组合约束(例如architecture-、state-、patterns-、react19-前缀体系)沉淀进同一套结构,让规范随代码一起演进。
【免费下载链接】open-slide
A slide framework built for agents.
相关推荐
用显式变体组件替代布尔 props:open-slide 组合式组件开发中的架构规则
用显式变体组件替代布尔 props:open slide 组合式组件开发中的架构规则 导读 当组件被 isThread 、 isEditing 、 isForw
open-slide 中的 React 组件架构:用组合替代布尔属性,根治组件变体爆炸
open slide 中的 React 组件架构:用组合替代布尔属性,根治组件变体爆炸 导读 本指南讲解 open slide 仓库中 vercel compo
深入解析 Ant Design 的 AGENTS.md:一份面向 AI 编程助手的大规模 React 组件库开发规范
深入解析 Ant Design 的 AGENTS.md:一份面向 AI 编程助手的大规模 React 组件库开发规范 Ant Design 在仓库根目录维护了一
前端UI组件设计系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考