Input OTP
InputOtp - Phlex implementation
Examples
Default
Accessible one-time password component with auto-advance and copy-paste functionality.
<%= render "ui/input_otp", length: 6 do %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 0 %>
<%= render "ui/input_otp/slot", index: 1 %>
<%= render "ui/input_otp/slot", index: 2 %>
<% end %>
<%= render "ui/input_otp/separator" %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 3 %>
<%= render "ui/input_otp/slot", index: 4 %>
<%= render "ui/input_otp/slot", index: 5 %>
<% end %>
<% end %><%= render UI::InputOtp.new(length: 6) do %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 0) %>
<%= render UI::InputOtpSlot.new(index: 1) %>
<%= render UI::InputOtpSlot.new(index: 2) %>
<% end %>
<%= render UI::InputOtpSeparator.new %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 3) %>
<%= render UI::InputOtpSlot.new(index: 4) %>
<%= render UI::InputOtpSlot.new(index: 5) %>
<% end %>
<% end %><%= render UI::InputOtpComponent.new(length: 6) do %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 0) %>
<%= render UI::InputOtpSlotComponent.new(index: 1) %>
<%= render UI::InputOtpSlotComponent.new(index: 2) %>
<% end %>
<%= render UI::InputOtpSeparatorComponent.new %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 3) %>
<%= render UI::InputOtpSlotComponent.new(index: 4) %>
<%= render UI::InputOtpSlotComponent.new(index: 5) %>
<% end %>
<% end %>Four Digits
Shorter PIN-style input without separator.
<%= render "ui/input_otp", length: 4 do %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 0 %>
<%= render "ui/input_otp/slot", index: 1 %>
<%= render "ui/input_otp/slot", index: 2 %>
<%= render "ui/input_otp/slot", index: 3 %>
<% end %>
<% end %><%= render UI::InputOtp.new(length: 4) do %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 0) %>
<%= render UI::InputOtpSlot.new(index: 1) %>
<%= render UI::InputOtpSlot.new(index: 2) %>
<%= render UI::InputOtpSlot.new(index: 3) %>
<% end %>
<% end %><%= render UI::InputOtpComponent.new(length: 4) do %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 0) %>
<%= render UI::InputOtpSlotComponent.new(index: 1) %>
<%= render UI::InputOtpSlotComponent.new(index: 2) %>
<%= render UI::InputOtpSlotComponent.new(index: 3) %>
<% end %>
<% end %>Pattern
Use the pattern prop to restrict input to specific characters.
<%= render "ui/input_otp", length: 6, pattern: "^[a-zA-Z0-9]+$" do %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 0 %>
<%= render "ui/input_otp/slot", index: 1 %>
<%= render "ui/input_otp/slot", index: 2 %>
<%= render "ui/input_otp/slot", index: 3 %>
<%= render "ui/input_otp/slot", index: 4 %>
<%= render "ui/input_otp/slot", index: 5 %>
<% end %>
<% end %><%= render UI::InputOtp.new(length: 6, pattern: "^[a-zA-Z0-9]+$") do %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 0) %>
<%= render UI::InputOtpSlot.new(index: 1) %>
<%= render UI::InputOtpSlot.new(index: 2) %>
<%= render UI::InputOtpSlot.new(index: 3) %>
<%= render UI::InputOtpSlot.new(index: 4) %>
<%= render UI::InputOtpSlot.new(index: 5) %>
<% end %>
<% end %><%= render UI::InputOtpComponent.new(length: 6, pattern: "^[a-zA-Z0-9]+$") do %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 0) %>
<%= render UI::InputOtpSlotComponent.new(index: 1) %>
<%= render UI::InputOtpSlotComponent.new(index: 2) %>
<%= render UI::InputOtpSlotComponent.new(index: 3) %>
<%= render UI::InputOtpSlotComponent.new(index: 4) %>
<%= render UI::InputOtpSlotComponent.new(index: 5) %>
<% end %>
<% end %>Separator
Use the separator component to visually separate groups of slots.
<%= render "ui/input_otp", length: 6 do %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 0 %>
<%= render "ui/input_otp/slot", index: 1 %>
<% end %>
<%= render "ui/input_otp/separator" %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 2 %>
<%= render "ui/input_otp/slot", index: 3 %>
<% end %>
<%= render "ui/input_otp/separator" %>
<%= render "ui/input_otp/group" do %>
<%= render "ui/input_otp/slot", index: 4 %>
<%= render "ui/input_otp/slot", index: 5 %>
<% end %>
<% end %><%= render UI::InputOtp.new(length: 6) do %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 0) %>
<%= render UI::InputOtpSlot.new(index: 1) %>
<% end %>
<%= render UI::InputOtpSeparator.new %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 2) %>
<%= render UI::InputOtpSlot.new(index: 3) %>
<% end %>
<%= render UI::InputOtpSeparator.new %>
<%= render UI::InputOtpGroup.new do %>
<%= render UI::InputOtpSlot.new(index: 4) %>
<%= render UI::InputOtpSlot.new(index: 5) %>
<% end %>
<% end %><%= render UI::InputOtpComponent.new(length: 6) do %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 0) %>
<%= render UI::InputOtpSlotComponent.new(index: 1) %>
<% end %>
<%= render UI::InputOtpSeparatorComponent.new %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 2) %>
<%= render UI::InputOtpSlotComponent.new(index: 3) %>
<% end %>
<%= render UI::InputOtpSeparatorComponent.new %>
<%= render UI::InputOtpGroupComponent.new do %>
<%= render UI::InputOtpSlotComponent.new(index: 4) %>
<%= render UI::InputOtpSlotComponent.new(index: 5) %>
<% end %>
<% end %>Features
- Custom styling with Tailwind classes
- Disabled state support
API Reference
Input OTP
Accessible one-time password container component.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| length | Integer | 6 | The length |
| pattern | String | \\d | The pattern |
| name | String | nil | Form field name |
| id | String | nil | HTML id attribute |
| disabled | Boolean | false | Whether the element is disabled |
Group
Container for grouping OTP input slots together visually.
Separator
Visual divider between OTP input groups.
Keyboard Shortcuts
| Key | Description |
|---|---|
| ArrowLeft | Moves focus left or decreases value |
| ArrowRight | Moves focus right or increases value |
| Home | Moves focus to first item |
| End | Moves focus to last item |
JavaScript
Stimulus Controller
ui--input-otpValues
| Name | Type | Description |
|---|---|---|
| length | Number | The length |
Actions
inputkeydownpastecheckCompleteclearEvents
| Event | Description | Detail |
|---|---|---|
| inputotp:complete | Fired when inputotp complete | - |