
Astryx TextArea 组件契约解析多行输入域的解剖学所有权与主题化表面【免费下载链接】astryxAn open source design system thats fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx导读本文基于 Astryx 设计系统仓库中的packages/core/src/TextArea/TextArea.spec.md组件契约文档深入解析 TextArea多行文本输入域的消费者解剖结构、组件所有权边界以及各部分与公共主题化 API 之间的映射关系。你将理解 Astryx 如何用「Theming anatomy」机制把哪个可见部件归谁画用机器可读的结构固化下来学会如何依据 FR1–FR4 不变式、delegatesTo/inherits/none四种处置来审计一个组件的主题化表面并掌握对应源码、文档与测试文件的验证路径。一、组件契约Component Contract是什么Astryx 的每个核心组件都配有.spec.md知识文档它记录的不是消费者如何用组件那属于TextArea.doc.mjs而是组件在系统中的解剖学契约组件渲染了哪些可见部件、每个部件分别由谁拥有其外观语义、这些部件与公共主题化 target 的映射关系以及维持这些关系的可验证不变式。TextArea 契约当前处于draft草案状态它记录的是现状事实TextArea 通过 Field、FieldStatus、Icon、Spinner 等共享组件组合出带标签的多行输入域并对text-area、text-area-control、text-area-counter三个主题 target 拥有所有权。该草案不改变任何运行时行为或公共 API——这一点在兼容性与迁移一节被明确声明发布默认保持yes兼容性类别仅增量文档运行时、DOM、样式、target、别名与公共 API 均不变受控/非受控行为不变TextArea 保持受控组件迁移决策无消费者侧的迁移指引属于消费者文档与发布说明的职责不写入本契约。二、所有权边界TextArea 画什么、不画什么契约通过「Owns / Does not own」清单精确划定职责这是整个主题化表面正确性的前提。TextArea 拥有Owns绘制出的输入容器painted input container原生文本域native text area字符计数器character counter三者分别对应现有text-area、text-area-control、text-area-counter主题 target。从实现看TextArea.tsx 中这三处themeProps()调用themeProps(text-area, {...})、themeProps(text-area-control)、themeProps(text-area-counter)正是契约所述结构的落地。TextArea 不拥有Does not own / non-goals部件归属标签、附加/分离式校验消息的呈现component:Field、component:FieldStatus工具提示变体的状态表面component:Tooltip标准起始图标与共享的场内状态图标component:Icon、component:Field加载指示器呈现component:Spinner调用方提供的自定义起始内容不在 TextArea 公共主题化所有权内已废弃的textarea别名仅作为兼容性证据不视为独立解剖部件源码印证TextArea 渲染时外层使用Field承载 label/status/widthTextArea.tsx忙态时在 end slot 中渲染Spinner sizesm /与状态图标TextArea.tsx起始图标通过renderIconSlot(startIcon, {size: sm, color: secondary})渲染TextArea.tsx状态图标经useInputStatusIcon取得——该 hook 也被 DateInput、DateRangeInput、DateTimeInput 等输入族成员复用。三、行为与布局契约FR1–FR4契约以候选不变式表格的形式固化了四条必须维持的行为事实ID候选不变式依据草案评审状态FR1当前渲染将原生文本域置于其绘制输入容器内部当前源码、文档与聚焦测试已验证当前行为无新行为决策FR2输入容器、原生控件与条件性字符计数器携带三个当前本地 target当前源码与公共文档已验证当前行为无 target 变更FR3标签、标准起始图标、加载指示器、状态图标与状态表面继续使用其共享的 Field、Icon、Spinner、FieldStatus、Tooltip 所有者当前源码已验证条件组合边界FR4占位文本仍属于原生控件超限字形仍属于字符计数器当前源码、文档与聚焦测试已验证当前分组这些不变式在 TextArea.test.tsx 中有对应断言FR1/FR4 的 DOM 结构renders the counter inside the input container断言 counter 与 textarea 具有相同父级同为容器内兄弟覆盖层placeholder与rows系列用例验证占位与行数属于原生控件FR2 的 target 输出TextArea theme target names用例断言根元素同时携带当前类astryx-text-area与兼容类astryx-textareaTextArea.test.tsxdisabled theme state与readonly theme state用例验证根 target 以data-disabled/data-readonly反映状态TextArea.test.tsxFR3 的组合边界status prop系列与statusVariant forwarding系列验证附加/分离变体是否渲染场内状态图标、是否预留尾部空间TextArea.test.tsx。此外themingTargets.test.tsthemingTargets.test.ts作为源码/元数据守门人核对themeProps()真实调用点与.doc.mjs中声明的theming.targets是否漂移。允许变化Allowed variationvalue、placeholder、行数rows、尺寸size、状态status、禁用/只读状态与可选插槽仍是现有能力而非独立的 target 名称起始图标内容可以是 Icon 支持的值也可以是调用方提供的 ReactNode。代表性状态状态必需不变式允许变化默认可编辑标签、输入容器、原生文本域渲染value、placeholder、rows、size带字符限制字符计数器渲染在输入容器内计数与超限状态忙态或状态共享 Spinner 或状态呈现渲染在当前位置状态变体与消息存在性转换与优先级顺序未引入新的 value、布局、状态或样式优先级规则。性能与资源未引入新的性能或资源规则。值得注意的是源码中字符计数的分段characterCount仅在有maxLength时才执行并通过useMemo缓存TextArea.tsx这印证了不引入新规则且对无计数器场景零额外开销的实现选择。四、无障碍契约该草案不改变或扩展 TextArea 现有的标签、描述、状态、计数器、忙态、禁用/只读状态或播报行为。但实现细节值得一提当disabledMessage存在时textarea 以aria-disabledreadOnly替代原生disabled保持键盘可聚焦以便发现禁用原因TextArea.tsx字符计数区段under/near/over只在跨区时通过useAnnounce播报超限用 assertive、接近上限用 politeTextArea.tsx。测试announces remaining characters politely与announces over-limit assertively直接验证了这一行为TextArea.test.tsx。五、设计关系与 Theming Anatomy 映射解剖学-需求对照解剖部件或状态设计要求呈现权威层级角色组件契约输入容器呈现当前绘制字段边界当前源码与公共文档支撑FR1, FR2文本域呈现并编辑当前多行值当前源码与公共文档突出FR1, FR2字符计数器呈现当前与最大字符数当前源码与公共文档支撑FR2, FR4共享字段反馈呈现当前标签、标准图标、状态与加载内容共享组件源码支撑FR3Theming anatomy 机器可读映射原文档核心数据这是契约文档的核心资产——每个消费者可见解剖部件到主题化处置的精确映射。必须原样保留{ Label: { delegatesTo: {owner: component:Field, target: field-label} }, Description: { none: { reason: unsettled: No current public target reaches the stable Description; future exposure still needs an owner decision } }, Input container: {target: text-area}, Text area: {target: text-area-control}, Placeholder: {inherits: text-area-control}, Start icon: { delegatesTo: {owner: component:Icon, target: icon} }, Custom start content: { none: { reason: intentional: Custom start content is caller-provided ReactNode content outside TextAreas public theming ownership } }, Spinner: { delegatesTo: {owner: component:Spinner, target: spinner} }, Status icon: { delegatesTo: { owner: component:Field, target: input-status-icon } }, Character counter: {target: text-area-counter}, Field status message: { delegatesTo: { owner: component:FieldStatus, target: field-status } }, Tooltip status message: { delegatesTo: {owner: component:Tooltip, target: tooltip} } }如何读懂这张映射依据 component-theming-surface.md 定义的系统模型每条解剖条目对应四种处置之一target—— 本组件为可见部件承诺一个稳定公共 target如text-area、text-area-control、text-area-counterinherits—— 部件无独立 target继承父 target 的样式如 Placeholder 继承text-area-controldelegatesTo—— 由其他 Astryx 组件拥有该部件及其 target如 Label 委托给Field/field-label、Status icon 委托给Field/input-status-icon、Field status message 委托给FieldStatus/field-status、Tooltip status message 委托给Tooltip/tooltipnone 分类原因—— 当前无公共 target 可达该部件原因必须精确分类intentional:刻意边界、reachability-gap:应达未达、unsettled:待决策。TextArea 映射中的两处none正是分类用法的范例Custom start content是调用方自带的 ReactNode属于刻意排除intentionalDescription虽然语义稳定但尚无公共 target 可达属待决策unsettled。契约明确指出已废弃的textarea别名仅是兼容性证据不进入映射——它与text-area的迁移关系见 component-theming-surface.md 的 0.7.0 废弃表面移除窗口表格textarea → text-area。对应的.doc.mjs元数据TextArea.doc.mjs声明了四个 targetastryx-text-areavisualProps: size/statusstates: disabled/readonly、astryx-text-area-control、astryx-text-area-counter以及保留的兼容类astryx-textareadeprecatedFor: text-area同时声明了私有变量--_textarea-inline-padding默认var(--spacing-2)private: true及其 derived 展开paddingInline替换。实现中该私有变量用于让文本内边距、起始图标、状态/Spinner 与字符计数器对齐TextArea.tsx。六、家族与系统关系architecture:component-theming-surface拥有解剖学资质、事实性none处置、保持组合的所有权与别名排除规则Field、FieldStatus、Icon、Spinner、Tooltip 在被 TextArea 组合时保留各自现有的公共 target 契约。TextArea 是family:input-fields输入字段家族的成员之一input-fields.md。家族契约记录TextArea 采用 Field、FormLayout、size、width、isLoading、changeAction、status 与 disabled reason并支持块轴增长不兼容 InputGroupinput-fields.md。家族不变式对 TextArea 的具体约束包括FR1普通状态切换占位变值、忙态/状态出现不得改变外部可用行内尺寸FR2已渲染的端部控件Spinner、状态控件必须拥有不重叠的空间且不存在的控件不得留下陈旧预留FR6changeAction路径必须先onChange、乐观呈现受控值、在 transition 中执行 Action 并共享同一忙态呈现——TextArea 中useOptimistic(value)startTransition正是此规则的实现TextArea.tsx。七、验证映射契约如何被守住契约的verified_by元数据声明了三类验证锚点TextArea.test.tsx、themingTargets.test.ts、check-knowledge.mjs。逐条不变式的验证策略契约验证方式代表性状态变异或失败预期FR1, FR4TextArea.test.tsx结构与计数器套件默认、占位、计数、超限移除或重组稳定部件会破坏现有 role、content 或 DOM 断言FR2TextArea.test.tsx根 target 套件与themingTargets.test.ts当前与废弃根名当前 target移除根兼容类会失败聚焦覆盖源码/文档漂移会触发 target 守门人FR3TextArea.test.tsx、useInputStatusIcon.test.tsx与renderIconSlot源码检查标准/自定义起始内容Spinner附加/分离/工具提示状态移除或改道组合内容会破坏现有 icon、spinner、tooltip、message 或关联断言Theming anatomy 映射scripts/check-knowledge.mjs规范解剖与当前本地 target规范键漂移、非法处置或 target 拼写、别名支撑的本地声明、未认领的当前本地 target 均验证失败契约同时诚实记录了验证空白TextArea 聚焦套件钉住了当前与废弃根类但未单独断言text-area-control或text-area-counter的精确类放置——该覆盖由源码/元数据 target 守门人承担且当前仓库没有检查会解析delegatesTo的 owner/target 配对本草案中的配对是手工核验的语义委托漂移仍是验证空白。八、决策日志、开放问题与内容边界决策日志无。本草案仅记录现状事实未引入组件本地设计或 API 决策。开放问题无。内容边界本文件不重复消费者 prop 表、示例、实现步骤或共享组件契约而是链接到其所有者——prop 与 usage 详见 TextArea.doc.mjs实现详见 TextArea.tsx行为验证详见 TextArea.test.tsx。结语TextArea 组件契约是 Astryx可主题化表面治理的最小但完整范例它用一张机器可读的解剖映射把输入容器归本组件、标签归 Field、消息归 FieldStatus、占位继承控件这类所有权事实固化为可校验的规范再以 FR1–FR4 不变式、themingTargets.test.ts与check-knowledge.mjs形成源码-元数据-测试的三方守门。理解这份契约等于掌握了阅读 Astryx 任意核心组件 spec 的方法先读解剖清单再看处置映射最后对照验证映射确认每一项都有可执行证据——这也是为组件编写新主题或扩展目标前必须完成的前置审计。【免费下载链接】astryxAn open source design system thats fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考