跳到主要内容

密码输入

PasswordInput 是带显隐按钮的原生密码框:保持光标位置、对接密码管理器、提交时自动隐藏。

PasswordInput(密码输入)是一个原生密码输入加上显示、隐藏按钮。切换显隐时光标与选区留在原处,密码管理器能识别该填哪种密码,表单提交时会自动把明文重新遮罩。只需要普通文本时用输入框;短验证码用验证码输入。

组合

PasswordInput
├── PasswordInputControl
└── PasswordInputToggle

PasswordInput 持有值与显隐状态;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 指向输入。

相关组件

输入关键词搜索…

↑↓ 移动↵ 选择Esc 关闭