Docs
输入 OTP

输入 OTP

具有复制粘贴功能的可访问一次性密码组件。

关于

¥About

输入 OTP 由 @guilherme_rodzinput-otp 之上构建。

¥Input OTP is built on top of input-otp by @guilherme_rodz.

安装

¥Installation

Run the following command:

pnpm dlx shadcn@latest add input-otp

Update tailwind.config.js

将以下动画添加到你的 tailwind.config.js 文件:

¥Add the following animations to your tailwind.config.js file:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      keyframes: {
        "caret-blink": {
          "0%,70%,100%": { opacity: "1" },
          "20%,50%": { opacity: "0" },
        },
      },
      animation: {
        "caret-blink": "caret-blink 1.25s ease-out infinite",
      },
    },
  },
}

用法

¥Usage

import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from "@/components/ui/input-otp"
<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>

示例

¥Examples

模式

¥Pattern

使用 pattern 属性为 OTP 输入定义自定义模式。

¥Use the pattern prop to define a custom pattern for the OTP input.

import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
 
...
 
<InputOTP
  maxLength={6}
  pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    {/* ... */}
  </InputOTPGroup>
</InputOTP>

分隔符

¥Separator

你可以使用 <InputOTPSeparator /> 组件在输入组之间添加分隔符。

¥You can use the <InputOTPSeparator /> component to add a separator between the input groups.

import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from "@/components/ui/input-otp"
 
...
 
<InputOTP maxLength={4}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
  </InputOTPGroup>
</InputOTP>

受控

¥Controlled

你可以使用 valueonChange 属性来控制输入值。

¥You can use the value and onChange props to control the input value.

Enter your one-time password.

表单

¥Form

Please enter the one-time password sent to your phone.

更新日志

¥Changelog

2024-03-19 组合

¥2024-03-19 Composition

我们进行了一些更新,并用合成替换了渲染属性模式。如果你更喜欢组合模式,以下是如何更新你的代码。

¥We've made some updates and replaced the render props pattern with composition. Here's how to update your code if you prefer the composition pattern.

Update to the latest version of input-otp.

pnpm add input-otp@latest

Update input-otp.tsx

input-otp.tsx
- import { OTPInput, SlotProps } from "input-otp"
+ import { OTPInput, OTPInputContext } from "input-otp"
 
 const InputOTPSlot = React.forwardRef<
   React.ElementRef<"div">,
-   SlotProps & React.ComponentPropsWithoutRef<"div">
-  >(({ char, hasFakeCaret, isActive, className, ...props }, ref) => {
+   React.ComponentPropsWithoutRef<"div"> & { index: number }
+  >(({ index, className, ...props }, ref) => {
+   const inputOTPContext = React.useContext(OTPInputContext)
+   const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]

Then replace the render prop in your code.

<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>

2024-03-19 已禁用

¥2024-03-19 Disabled

要向输入添加禁用状态,请按如下方式更新 <InputOTP />

¥To add a disabled state to the input, update <InputOTP /> as follows:

input-otp.tsx
const InputOTP = React.forwardRef<
  React.ElementRef<typeof OTPInput>,
  React.ComponentPropsWithoutRef<typeof OTPInput>
>(({ className, containerClassName, ...props }, ref) => (
  <OTPInput
    ref={ref}
    containerClassName={cn(
      "flex items-center gap-2 has-[:disabled]:opacity-50",
      containerClassName
    )}
    className={cn("disabled:cursor-not-allowed", className)}
    {...props}
  />
))
InputOTP.displayName = "InputOTP"