AniBTUI
✦ 组件@anibt/password-inputregistry JSON

Password Input

带显示 / 隐藏键的密码框,键一直有可读名称,并报告自己的状态。

至少 10 位,字母和数字都要有。

两次输入的密码不一样。

安装

npx shadcn@latest add @anibt/password-input

第一次用之前:在 components.json 里登记 @anibt,再单独运行一次 npx shadcn@latest add @anibt/theme(见快速开始)。只有单独安装主题时,CLI 才会把 shadcn 的标准颜色换成白樱 / 夜樱;随组件带进来的主题只补上 AniBT 自己的变量和配方。 CLI 会一并装好 @anibt/input。

手动安装
  1. 1. 先装主题组件只读 @anibt/theme 的 token 和配方,没有主题就没有样子。
    npx shadcn@latest add @anibt/theme
  2. 2. 安装依赖
    npm install lucide-react
  3. 3. 它还用到
    npx shadcn@latest add @anibt/input
  4. 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 相同。