定价

Input 使用手册

v1.2.0 · @snowui-design-system/components

许可阅读:首次阅读组件文档、源码或 npm 使用流程,先读完整 LICENSE;同任务同版本去重。公开 API 配置与内部实现修改分别按许可处理;全部组件使用统一运行包,源码权益以许可为准。

组件介绍

提供单行输入,支持文本、搜索、密码、数字、日期时间与颜色,可组合标签、图标和校验反馈。

使用选择

用于单行文本输入。搜索用 SearchInput,多行输入用 Textarea;需要 label、帮助和错误时组合 Field。

  • bind:value 同步编辑值,显式 value 优先于 defaultValue;数字类型输入后的值仍需业务自行转换。

  • name 用于表单提交,受控表单重置时恢复绑定初值;bind:element 得到外层元素,不能当作原生 input。

  • file / range 不提供上传或滑杆能力;附件用 leading / trailing 角色,清除按钮可接管 trailing。

快速开始

以下示例展示推荐的基本组合。更多场景与组合限制见后文。

<script lang="ts">	import { Input, Button } from '@snowui-design-system/components';	let submitted = $state(false);	function login(event: SubmitEvent) {		event.preventDefault();		submitted = true;	}</script> <form onsubmit={login} oninput={() => submitted = false} style="display: flex; flex-direction: column; gap: var(--gap-4); width: min(100%, 22.5rem); min-width: 0;">	<Input type="email" name="email" aria-label="Email" placeholder="Email" autocomplete="username" required />	<Input type="password" name="password" aria-label="Password" placeholder="Password" autocomplete="current-password" required />	<Button type="submit" variant="filled" size="md">Log in</Button></form>

API

关键字 类型 默认值 描述
element HTMLElement — 外层 Frame 根元素引用,支持 bind:element;不是原生 input 引用。
type HTMLInputAttributes["type"] "text" 选择单行输入类型;支持 text、search、email、password、url、tel、number、date、time、datetime-local、month、week、color。日期时间和颜色具有组件展示层及原生值宿主;file / range 会回退为 text,不提供上传或滑杆。
gap number — 继承 Frame 的间距 token 索引;省略时保留组件原首选间距,显式值覆盖首选间距,有效图文间距仍至少为 4 CSS px;显式零和根字号/间距缩放不压低下限。
value InputValue — 当前值,支持 bind:value 双向同步;显式 value 优先于 defaultValue。原生编辑和内置清除事件同步 input.value 字符串;number 可使用数字初值,业务计算需自行转换。
defaultValue InputValue — 未传 value 时的初始值;输入后的值由组件同步管理;表单重置若需恢复业务初值,应在 onreset 中显式恢复绑定值。
placeholder string — 空输入的提示文字,不替代可访问标签;日期时间输入保留分段占位。
name string — 原生表单字段名;FormData 使用该名称收集字段。
disabled boolean false 禁止用户输入与交互,原生禁用字段不参与表单提交。
readonly boolean false 保留聚焦、选择与提交,禁止编辑并隐藏清除入口;自定义 trailing 聚焦后仍保留,使用只读视觉。
clearable boolean true 是否允许显示内置清除 X;false 时不渲染 X,不改变编辑、校验或自定义 trailing。适用于普通及 Field 内嵌 Input。
required boolean false 参与浏览器原生必填校验;不自动产生业务错误文案。
autocomplete HTMLInputAttributes["autocomplete"] — 透传浏览器自动填充字段语义,如 username、email、new-password;候选来自浏览器已有数据。
minlength number — 适用文本输入的最小字符长度,由浏览器在适用的用户编辑和表单校验路径执行。
maxlength number — 适用文本输入的最大字符长度;浮层 as="search" 未显式设置时回退为 100。
pattern string — 适用文本输入的原生校验正则,不包含斜杠;需要整体匹配,空值是否有效由 required 决定。
min number | string — 数字或日期时间输入的最小值;数字按输入数值,日期时间按对应原生格式表达。
max number | string — 数字或日期时间输入的最大值;数字按输入数值,日期时间按对应原生格式表达。
step number | string — 原生步进约束;number 以数值单位步进,日期时间使用浏览器对应类型的步进单位。
inputmode HTMLInputAttributes["inputmode"] — 向设备提示软键盘类型,如 numeric、decimal、tel;不执行输入过滤或校验。
enterkeyhint HTMLInputAttributes["enterkeyhint"] — 向软键盘提示回车动作,如 next、search、done;不自动执行导航或提交。
spellcheck boolean — 透传拼写检查开关;未指定时遵循浏览器与继承环境。
list string — 关联原生 datalist 的 id,候选与浏览器呈现由调用方和浏览器提供。
accept string — 保留的原生属性透传入口;Input 不支持 file,不能通过此属性获得文件类型限制或上传能力。
multiple boolean — 原生多值提示,适用于 email 多邮箱等浏览器支持的输入;Input 不支持多文件上传。
capture boolean | "user" | "environment" — 保留的原生采集属性;由于 file 会回退为 text,在 Input 中不提供相机或文件采集能力。
form string — 按 id 关联外部 form;原生提交与重置包含该字段,不要求字段位于 form 内。
autofocus boolean — 普通输入透传原生自动聚焦提示,浏览器可能保留已有焦点;日期时间展示层在首次挂载主动聚焦首段。避免页面加载抢焦点。
tabindex number — 透传原生焦点顺序;0 使用自然顺序,-1 退出顺序导航,正数定义显式顺序。常规表单推荐自然顺序。
title string — 原生提示文字;日期时间与颜色输入同时为展示层提供相应提示,不替代 label。
id string — 原生输入标识,可供 label 的 for 与原生关联属性引用。
invalid boolean false 与 aria-invalid 汇总无效态,显示错误视觉;独立输入自动错误反馈,Field 内由 Field 汇总。
error string | Snippet — invalid 时生成下方内置错误 Text;字符串为文案,Snippet 无参数并提供错误内容,默认不生成。
parts ComponentPartsOf<{ Text: typeof Text; Button: typeof Button }> — 通过 Text / Button 键配置内置错误文案或操作按钮的公开 Props,仅对组件生成的 Text 生效;显式子项自行声明 Props。
onclick (event: MouseEvent) => void — 单击原生输入或相应展示层时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
ondblclick (event: MouseEvent) => void — 双击时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
oninput (event: Event) => void — 用户输入以及组件清除、步进等输入同步时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onchange (event: Event) => void — 原生提交值变化或组件发出 change 同步时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onfocus (event: FocusEvent) => void — 输入获得焦点时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onblur (event: FocusEvent) => void — 输入失去焦点时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onkeydown (event: KeyboardEvent) => void — 按下键盘按键时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onkeyup (event: KeyboardEvent) => void — 释放键盘按键时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onkeypress (event: KeyboardEvent) => void — 浏览器触发已弃用的 keypress 时;新代码推荐 onkeydown回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
onpaste (event: ClipboardEvent) => void — 粘贴时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
oncopy (event: ClipboardEvent) => void — 复制时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
oncut (event: ClipboardEvent) => void — 剪切时回调,参数为对应事件,无返回值;可取消的浏览器默认行为使用 event.preventDefault(),回调不用于撤销已经执行的组件内部值同步。
children Snippet — 无参数显式子内容,用 as="leading" / as="trailing" 组合图标或附件;清除可见时接管 trailing 位置。
allowCustomValue boolean false 仅 as="search" 位于 Listbox 时生效;无匹配时 Enter 将输入添加为自定义项并选中,支持删除自定义项。

未重新声明的继承能力请查所属基础组件文档;本表只列本组件源码具名公开属性。

使用边界与详细说明

表单组合与间距

  • 基础节奏统一:Field 默认 padding = 12 / 16,gap = 8

  • Input 单独使用时:组件自身带 12 / 16 padding 和 8 gap

  • icon 位置由 Input 自己控制:leading / trailing icon 到最近可见内边界默认都是 16px

  • 错误态内建 warning icon 也走同一条 trailing icon 规则,不额外使用 overlay 偏移

  • 放进 Field 后,先看有没有 as="segment"

  • 没有 as="segment":由外层 Field 负责 12 / 16 padding 与 8 gap;Input 去掉自身 padding,但保留自身 gap

  • 有 as="segment":这是连续字段表面的一段;保留 Input 自身的 padding 与 gap,同时继续由 Input 保证 icon 到边框 / 分割线的距离为 16px

  • segment 之间才有分割线:横向是左右分割线,纵向是上下分割线

  • 相邻 segment 之间只能有一条分割线,不能重复画线

  • label / description / error 不负责 padding、gap、分割线,它们只是内容元素

  • 普通 label + host + error:不作为 padding、gap 的判断依据,只负责文字内容

  • Field row 或 Field column 里,如果是连续输入段,子项要显式写 as="segment"

组件定位

Input 现在的推荐定位是字段宿主,而不是完整字段外壳:

  • 单独使用时,仍可保持兼容性的默认输入框表现

  • 放进 Field 容器后,未标 segment 时由外层 Field 接管 padding 与 gap;只有标记为 segment 时才保留 Input 自身留白

  • 因此 Input 可以和 Icon / Text / Checkbox / Switch / Badge / Frame as="row" 一起组合成更复杂的表单表面

  • 其中 text 直接使用可见原生 <input>;date / color 仍保留“可见展示层 + 隐藏原生宿主同步值”的结构

Frame 能力继承

Input 仍然通过外层 Frame 承接通用能力,因此可以继续使用:

  • responsive / stateStyle / customStates / variants / styles

  • Hover / Click / Focus / whileAppear / timeline / orchestrate

  • loading / skeleton / renderHints

  • as / use / layoutId / itemId / scope / access

Input 的职责不是替代 Frame,而是在 Frame 外壳内承接输入协议。 对于 text,组件直接复用原生 <input> 的可见渲染与事件链路;对于 date / color,组件会把“值同步、表单归属、picker 打开”交给隐藏原生宿主,把“可见文本/颜色展示”交给自定义展示层。

错误反馈 Shake

invalid 表示稳定错误视觉:红色边框、aria-invalid 与内建 warning icon。输入错误时的一次性 shake 已默认接入,消费方不需要传额外 prop,也不需要知道内部 CSS 类名。

推荐写法保持为普通错误态:

<Input    invalid    placeholder="name@example.com"/>

独立 Input 遇到 invalid / aria-invalid 会自动播放 shake。进入 Field 后,Input 不单独抖动,由外层 Field 汇总错误态并整体反馈,避免嵌套位移叠加。

错误态与 shake 不会自动聚焦,也不会模拟 focus-within;焦点态只来自用户真实聚焦、显式 autofocus 或业务代码主动调用 focus()。

组件特有属性 (Component-Specific Props)

下表逐项对应具名 Props;未重新声明的通用能力见 Frame。

布局模型

主布局模型:槽位宿主布局。定义见 ../../../specs/maintainers/LayoutProtocol.md §12.3(源码参考:specs/maintainers/LayoutProtocol.md)。

根宿主固定采用单行内容协议,Leading / Control / Trailing 之间的有效间距至少为 4 CSS px;显式 gap={0}、根字号或间距缩放不会压低该下限,较大的原有首选间距保持。Field 只编排外部区域与连续字段表面,不改写 Input 自己的内部布局或附件间距。日期分段、颜色文本与绘制结构的内部零间距不受影响。

Input 的根布局固定按 Leading / Control / Trailing 三段组织:

  • 根节点是 Frame row,并在组件内部固定启用 enableAutoLayout;外部传入 enableAutoLayout={false} 不关闭 Input 的内部槽位协议。

  • 直系 as="leading" / as="trailing" 支持复杂结构,Leading 与 Trailing 为 Hug。

  • 原生 <input> 或自定义 date/color 可见层是 Content,负责 Fill,必须保持 min-width: 0。

  • 自定义 trailing 存在时替换默认日期/清除等末位槽;内建 warning icon 仍按组件内部 trailing 规则处理。

  • 进入 Field 后,Field 只接管字段表面、padding 与分割线;Input 内部 icon / control 的最终落列仍由 Input 自己维护。

浮层搜索输入模式

将 <Input as="search"> 放入任意提供 header portal 的浮层容器(<Listbox> / <Popover>)内,Input 自动:

  1. 通过 LISTBOX_HEADER_PORTAL_KEY context 读取 headerEl,挂载后 appendChild 到固定头部(不参与下方滚动);

  2. 应用紧凑浮层规格(padding/gap/radius);

  3. :focus-within 时关闭外扩 focus ring(--snowui-field-focus-ring-width: 0rem);

  4. 未显式 maxlength 时默认 100。

Listbox 场景额外接通 ListboxOwnerContext.setFilterText 过滤逻辑(由 listboxOwner 派生量 isListboxSearch 控制);Popover 场景仅承担"固定头部输入框"的视觉与移位,无过滤副作用。

样式选择器统一为 :where(.snowui-quick-action-panel-header > .snowui-input, .snowui-listbox-header > .snowui-input, .snowui-listbox > .snowui-input, ...),避免各浮层重复覆盖。

属性 类型 默认值 描述
as "search" - 标识为浮层搜索输入;存在 header portal 时自动移入固定头部,Listbox 场景下额外接通 setFilterText

行为说明

  • 搜索文本通过 oninput 实时写入 ListboxOwnerContext.filterText,由 Select 的 filteredOptions derived 做大小写不敏感过滤

  • 自定义项(allowCustomValue 添加的)不参与过滤,始终显示

  • Listbox 关闭时 Input 值与 filterText 同步清零

  • 自定义项 hover 时,✔ 图标位置替换为 × 圆形删除按钮(复用 Input 的清除按钮 SVG);点击 × 删除该自定义项,若该项为当前选中值则同时清空选中

使用示例

 <Select placeholder="请选择城市">    <Listbox>        <Input as="search" placeholder="搜索..." />        <MenuItem value="shanghai">Shanghai</MenuItem>        <MenuItem value="hangzhou">Hangzhou</MenuItem>    </Listbox></Select>  <Select placeholder="请选择或输入">    <Listbox>        <Input as="search" allowCustomValue placeholder="搜索或输入新选项..." />        <MenuItem value="tag-a">Tag A</MenuItem>        <MenuItem value="tag-b">Tag B</MenuItem>    </Listbox></Select>  <Select placeholder="请选择城市">    <Listbox style="max-height: 120px;">        <Input as="search" placeholder="搜索..." />        ...    </Listbox></Select>

原生能力边界

Input 负责:

  • 原生 <input> 属性透传

  • value / defaultValue 解析

  • bind:value 同步

  • aria-invalid 与组件 invalid 汇总

Input 不负责:

  • label / description 的完整字段排版(可组合 Field);error 可由公开 error 属性生成内置反馈

  • 自动补全数据源生成

  • 表单规则中心

  • 业务级错误文案

使用示例

 <Field>  <Input placeholder="请输入内容" /></Field>  <Field>  <Icon as="leading"><Search /></Icon>  <Input placeholder="搜索内容" />  <Button as="trailing" size="sm">搜索</Button></Field>  <Field>  <Input type="date" />  <Button bare as="trailing" aria-label="打开日期选择">    <ArrowLineDown size={16} />  </Button></Field>  <Field>  <Frame as="row" row>    <Input type="date" />    <Button bare as="trailing" aria-label="打开日期选择">      <ArrowLineDown size={16} />    </Button>  </Frame></Field>  <Input type="email" name="email" autocomplete="email" />  <Input required minlength={3} maxlength={20} pattern="[a-zA-Z0-9_]+" />  <form>  <Input name="username" defaultValue="snowui" /></form>  <form id="CSS 行为-form"></form><Input form="CSS 行为-form" name="displayName" />  <Input  Click={{ Idle: "Active", Active: "Idle" }}  stateStyle={{    Idle: "--snowui-input-background: var(--surface-1, #ffffffcc);",    Active:      "--snowui-input-background: color-mix(in srgb, var(--primary, #000000) 8%, var(--surface-1, #ffffffcc));",  }}  value="点击输入框触发 Frame 状态"/>

展示可打开、可复制的链接

“链接输入框 / 链接 input / 可复制链接”不是可编辑输入。使用 CopyLink,无边框和输入框 hover 动效;链接文字 hover 显示下划线、点击在新标签页打开,其余区域点击复制。完整组合约定见 自然语言映射(源码参考:specs/reference/NaturalLanguageToSnowUI.md)。Input 保留给需要编辑地址或只读选择值的场景。

无障碍与表单建议

  • 需要自动填充时,优先传 name + autocomplete

  • 需要原生建议列表时,使用 list 关联 datalist

  • 需要错误提示时,外部通过 aria-describedby 指向 Field 内的描述/错误节点

  • 需要 schema/业务校验时,应在 Field 或表单层处理,再把结果回传为 invalid 或 aria-invalid


Input 样式覆盖

先阅读 完整 LICENSE;同任务、同版本、同范围去重。

优先用组件公开 Props 匹配合适样式,尽可能保留原有视觉。确需改写时按 样式选择与改写顺序 使用自己的 class(含项目已有 Tailwind)或实例 style。以下名称来自源码实际消费的公开 override;先核对目标作用域,不修改私有 DOM。采用 SnowUI Token 时选择正确类别,外部应用不被要求安装一方 utilities。

变量 用途与默认参考
--snowui-input-background-override 背景(默认值见组件源码)
--snowui-input-font-size-override font-size(默认值见组件源码)
--snowui-input-gap-override gap(默认 var(--gap-2) = 8px)
--snowui-input-height-override 高度(默认值见组件源码)
--snowui-input-line-height-override line-height(默认值见组件源码)
--snowui-input-padding-override 整体 padding(默认值见组件源码)
--snowui-input-placeholder-color-override 占位符颜色(默认值见组件源码)
--snowui-input-radius-override border-radius
--snowui-input-warning-icon-color-override 警告图标颜色(默认值见组件源码)
--snowui-input-warning-icon-font-size-override 警告图标 font-size(默认值见组件源码)
--snowui-input-warning-icon-line-height-override 警告图标 line-height(默认值见组件源码)
--snowui-input-warning-icon-size-override 警告图标尺寸(尺寸 px,默认值见组件源码)
--snowui-input-width-override 宽度(默认值见组件源码)

设计指南 · Token · 组合边界

Input 类型与状态

必填属性:无具名必填属性。

可双向绑定:bind:value、bind:element。

继承声明:Omit<FrameProps, "tag">。继承能力以基类公开文档为准;Omit 中的字段已排除,不能按基类原样使用。

共享 Frame API · 返回 API

以下为公开属性实际引用的类型声明,来自源码;Svelte Snippet 表示内容片段,ComponentProps 表示对应组件的 Props。

InputValue

来源:components/src/components/Input.svelte

type InputValue = string | number | undefined;

ComponentPartsOf

来源:components/src/logic/component-parts.svelte.ts

export type ComponentPartsOf<    T extends Record<string, Component<any>>,> = {    [K in keyof T]?: ConfigurableComponentPartProps<T[K]>;};

ConfigurableComponentPartProps

来源:components/src/logic/component-parts.svelte.ts

export type ConfigurableComponentPartProps<C extends Component<any>> = Partial<    Omit<ComponentProps<C>, ComponentPartControlledKey>>;

ComponentPartControlledKey

来源:components/src/logic/component-parts.svelte.ts

export type ComponentPartControlledKey =    | "children"    | "as"    | "value"    | "defaultValue"    | "open"    | "selected"    | "checked"    | "disabled"    | "readonly"    | "id"    | `on${string}`    | `aria-${string}`;

外部类型来源:

  • HTMLInputAttributes — svelte/elements