Password Input
带显示 / 隐藏键的密码框,键一直有可读名称,并报告自己的状态。
至少 10 位,字母和数字都要有。
两次输入的密码不一样。
password-input-demo.tsx
"use client"
import { Field, FieldControl, FieldGroup } from "@/components/ui/field"
import { PasswordInput } from "@/components/ui/password-input"
export default function PasswordInputDemo() {
return (
<FieldGroup className="w-full max-w-sm">
<Field label="新密码" required hint="至少 10 位,字母和数字都要有。">
<FieldControl>
<PasswordInput autoComplete="new-password" defaultValue="sakura2026" />
</FieldControl>
</Field>
<Field label="再输入一次" required error="两次输入的密码不一样。">
<FieldControl>
<PasswordInput autoComplete="new-password" defaultValue="sakura2025" />
</FieldControl>
</Field>
</FieldGroup>
)
}安装
npx shadcn@latest add @anibt/password-input第一次用之前:在 components.json 里登记 @anibt,再单独运行一次 npx shadcn@latest add @anibt/theme(见快速开始)。只有单独安装主题时,CLI 才会把 shadcn 的标准颜色换成白樱 / 夜樱;随组件带进来的主题只补上 AniBT 自己的变量和配方。 CLI 会一并装好 @anibt/input。
手动安装
- 1. 先装主题组件只读
@anibt/theme的 token 和配方,没有主题就没有样子。npx shadcn@latest add @anibt/theme - 2. 安装依赖
npm install lucide-react - 3. 它还用到
npx shadcn@latest add @anibt/input - 4. 把下面的文件放进项目components/ui/password-input.tsx
"use client" import * as React from "react" import { EyeIcon, EyeOffIcon } from "lucide-react" import { cn } from "@/lib/utils" import { Input } from "@/components/ui/input" /** * PasswordInput — an AniBT 「贴纸手账」 `Input` with the one visibility key. * * The key at the right end is a quiet 24px square (the pink wash under the * pointer) that is always named — `showLabel` / `hideLabel` — and reports * its state with `aria-pressed`, so a keyboard and a screen reader can tell * show from hide. Whether the characters are on screen is this component's * own state: nothing outside a password field needs to know. * * `toggleWhenEmpty={false}` hides the key until something is typed (a * controlled field only). `className` sizes the wrapper (the key sits at its * end); `inputClassName` reaches the `<input>`, and so does every other * prop, `ref` included — pass `autoComplete="current-password"` or * `"new-password"`. */ type PasswordInputProps = Omit<React.ComponentProps<"input">, "type"> & { /** Show the key on an empty field too (default). */ toggleWhenEmpty?: boolean /** Classes for the `<input>`; `className` sizes the wrapper. */ inputClassName?: string showLabel?: string hideLabel?: string } function PasswordInput({ className, inputClassName, toggleWhenEmpty = true, showLabel = "显示密码", hideLabel = "隐藏密码", value, disabled, ...props }: PasswordInputProps) { const [visible, setVisible] = React.useState(false) const hasValue = typeof value === "string" ? value.length > 0 : value !== undefined const showToggle = toggleWhenEmpty || hasValue const label = visible ? hideLabel : showLabel return ( <div data-slot="password-input" className={cn("relative w-full min-w-0", className)}> <Input type={visible ? "text" : "password"} value={value} disabled={disabled} autoCapitalize="none" autoCorrect="off" spellCheck={false} className={cn(showToggle && "pr-9", inputClassName)} {...props} /> {showToggle ? ( <button type="button" onClick={() => setVisible((current) => !current)} disabled={disabled} aria-label={label} aria-pressed={visible} title={label} className="absolute top-1/2 right-1.5 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[6px] text-muted-foreground transition-colors duration-150 hover:bg-accent hover:text-accent-foreground focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-solid disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-muted-foreground" > {visible ? <EyeOffIcon className="size-4" aria-hidden="true" /> : <EyeIcon className="size-4" aria-hidden="true" />} </button> ) : null} </div> ) } export { PasswordInput } export type { PasswordInputProps }
用法
用法
import { PasswordInput } from "@/components/ui/password-input"
<PasswordInput autoComplete="current-password" />显示键
右端是 24px 的安静方块,悬停是粉色淡底。它一直有名字——「显示密码」或「隐藏密码」(showLabel / hideLabel)——并用 aria-pressed 报告状态,键盘和读屏都分得清。字符是否明文显示是这个组件自己的状态,外面不需要知道。
注册和改密码时给 autoComplete="new-password",登录时给 "current-password",密码管理器才认得出。自动大写、自动更正和拼写检查已经关掉。
属性
PasswordInput
toggleWhenEmptyboolean默认 truefalse:受控且为空时不显示显示键
showLabelstring默认 "显示密码"显示键的可读名称
hideLabelstring默认 "隐藏密码"隐藏键的可读名称
classNamestring默认 —外层的类名,管宽度;显示键贴在它的右端
inputClassNamestring默认 —输入框本身的类名
其余属性和 ref 交给里面的 <input>;材质和状态与 Input 相同。
