PasswordInput(密码输入)是一个原生密码输入加上显示、隐藏按钮。切换显隐时光标与选区留在原处,密码管理器能识别该填哪种密码,表单提交时会自动把明文重新遮罩。只需要普通文本时用输入框;短验证码用验证码输入。
组合
PasswordInput
├── PasswordInputControl
└── PasswordInputTogglePasswordInput 持有值与显隐状态;PasswordInputControl 渲染原生输入;PasswordInputToggle 渲染切换按钮,它在 password 与 text 两种类型之间切换,自身是 type="button",所以在输入里按 Enter 仍然提交表单。
表单相关属性(name、form、required、disabled、readOnly)放在 PasswordInput 上;其余原生输入属性(placeholder、id 等)放在 PasswordInputControl 上。
用法
import { Field, FieldLabel } from "@ui-sdk/react/field";
import { PasswordInput, PasswordInputControl, PasswordInputToggle } from "@ui-sdk/react/password-input";
<Field name="password">
<FieldLabel>密码</FieldLabel>
<PasswordInput>
<PasswordInputControl />
<PasswordInputToggle aria-label="显示密码">
{(state) => (state.visible ? "隐藏" : "显示")}
</PasswordInputToggle>
</PasswordInput>
</Field>;部件的 children 可以是函数,收到该部件的状态;这里用 state.visible 切换按钮内容。放进字段后,FieldLabel 为输入命名,FieldDescription 作为说明被一起朗读。
显隐状态
defaultVisible 让密码一开始就是明文,适合需要被读出或复制的场景,例如展示给访客的 Wi-Fi 密码。要完全受控就传 visible 与 onVisibleChange:
const [visible, setVisible] = React.useState(false);
<PasswordInput visible={visible} onVisibleChange={setVisible}>
<PasswordInputControl aria-label="密码" />
<PasswordInputToggle aria-label="显示密码">
{(state) => (state.visible ? "隐藏" : "显示")}
</PasswordInputToggle>
</PasswordInput>;details.reason 区分 toggle-press、form-submit、reset、page-hide 与 imperative。表单提交与页面被隐藏(例如跳转离开)时组件会主动隐藏明文,前者让浏览器正常提示保存密码,后者避免明文被浏览器缓存进页面快照。details.cancel() 可以拒绝显隐变更,但提交过程中浏览器读取表单的那一刻,输入仍会临时回到密码类型。
自动填充与密码管理器
autoComplete 默认是 "current-password",用于登录;注册或修改密码时改成 "new-password",浏览器与密码管理器才会提供生成、保存新密码的流程,也可以设 "off"。
<PasswordInput name="new-password" autoComplete="new-password">
<PasswordInputControl placeholder="至少 8 个字符" />
<PasswordInputToggle aria-label="显示密码">
{(state) => (state.visible ? "隐藏" : "显示")}
</PasswordInputToggle>
</PasswordInput>组件本身不施加任何密码强度策略。要做强度清单,用受控值 value + onValueChange 自己推导规则并渲染,自动填充与密码管理器填入的值同样以 input-change 报告。
大写锁定提示
聚焦期间按键事件会更新大写锁定状态,用 data-capslock 写样式,或读根的 capsLock 状态渲染提示:
<PasswordInput>
{(state) => (
<>
<PasswordInputControl aria-label="密码" />
<span aria-hidden="true">{state.capsLock ? "!" : ""}</span>
<PasswordInputToggle aria-label="显示密码">
{(toggle) => (toggle.visible ? "隐藏" : "显示")}
</PasswordInputToggle>
</>
)}
</PasswordInput>给图标与提示预留固定位置,状态切换时布局才不会跳动。失焦或关闭大写锁定后提示消失。
控制器与表单
用 createPasswordInputController() 创建控制器传给根,可在字段之外读写:getValue / setValue / clear / isVisible / setVisible / toggleVisible / focus。写入方法接受 { reason, event },像用户输入或按下按钮一样触发变更回调,被取消时返回 false,默认原因是 imperative。参见控制器。
const password = createPasswordInputController();
password.setValue("plum-kettle-orbit-42");
password.setVisible(true);原生输入参与 FormData、校验与重置:name 决定提交字段名(在字段内可用 Field 的 name),form 关联页面中其他表单的 id,required 阻止空值提交,重置回到 defaultValue。disabled 同时禁用输入与按钮且不提交;readOnly 只锁住文本,显隐按钮仍然可用。disabled 也会从 Field 或外层 <fieldset disabled> 继承。参见表单。
样式与状态
把根当作字段的盒子来画,原生输入与按钮排在里面。三个部件共享同一套状态属性:
data-visible:当前是明文(输入为文本类型)。data-filled:已有文本。data-capslock:聚焦且大写锁定开启。data-disabled、data-readonly、data-required。- 在字段内,原生输入还会收到
data-invalid等校验属性。
[data-slot="password-input"] {
display: flex;
align-items: center;
gap: 0.5rem;
border: 1px solid var(--color-border);
border-radius: 8px;
padding-inline: 0.75rem;
}
[data-slot="password-input"][data-visible] { border-color: var(--color-warning); }
[data-slot="password-input-toggle"][aria-pressed="true"] { color: var(--color-brand); }间距用逻辑属性写,字段与按钮才能跟随书写方向。详见样式与动画。
API
PasswordInput 常用属性:
| 属性 | 类型 | 说明 |
|---|---|---|
value / defaultValue |
string |
受控值与非受控初始值,重置回到后者。 |
onValueChange |
(value, details) => void |
值变化时触发,可 details.cancel()。 |
visible / defaultVisible |
boolean |
是否显示明文,受控与非受控。 |
onVisibleChange |
(visible, details) => void |
显隐将要变化时触发,可取消。 |
autoComplete |
"current-password" | "new-password" | "off" | string |
自动填充语义。 |
name / form |
string |
提交字段名与关联表单 id。 |
required / disabled / readOnly |
boolean |
必填、禁用、只读。 |
controller |
object |
createPasswordInputController() 创建的控制器。 |
所有部件的状态里都有 visible、capsLock、filled、disabled、readOnly、required,可用于渲染函数与按状态取类名。
键盘与无障碍
密码框没有对应的 WAI-ARIA 模式:输入保持原生密码输入,由 FieldLabel 或 aria-label 命名;切换按钮遵循 WAI-ARIA 按钮模式中的切换按钮。
Tab从输入移动到按钮,按钮上Space或Enter切换显隐。- 在输入里按
Enter提交表单,绝不会误触按钮。 - 指针点击按钮后焦点留在输入,光标与选区保持原位;从别处点击按钮同样把焦点带回输入;键盘按下按钮时焦点留在按钮上。
按钮的名字按它的作用命名(例如「显示密码」)并保持不变,当前状态由 aria-pressed 表达,aria-controls 指向输入。