Input OTP
A segmented one-time-password input.
1use herogpui::components::input_otp::{InputOTP, OtpState};Usage
Custom slot content inherits 14px/20px text; the built-in digits use 18px/24px text.
1use herogpui::prelude::{InputOTP, Label, Link, OtpState};
2use gpui::prelude::*;
3use gpui::px;
4
5gpui::div()
6 .flex()
7 .flex_col()
8 .items_start()
9 .gap(px(12.))
10 .children(vec![
11 Label::new("Verify account").into_any_element(),
12 muted_para("We've sent a code to a****@gmail.com", cx),
13 InputOTP::new(self.otp.clone())
14 .separator()
15 .on_complete(cx.listener(|this, code: &str, _, cx| {
16 this.otp_done = code.to_owned();
17 cx.notify();
18 }))
19 .into_any_element(),
20 gpui::div()
21 .flex()
22 .items_center()
23 .gap(px(5.))
24 .child(muted_para(
25 &if done.is_empty() {
26 "Didn't receive a code?".to_owned()
27 } else {
28 format!("Complete: {done}")
29 },
30 cx,
31 ))
32 .child(Link::new("input-otp-resend").label("Resend").href("#"))
33 .into_any_element(),
34 ])Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.
Anatomy
Rust types
InputOTP
Input OTP is assembled from these builders. The API reference lists each one.
Customization
Appearance builders and theme tokens Input OTP uses.
Styling
| Style | Description |
|---|---|
text_size + line_height | Custom slot content inherits 14px/20px text; the built-in digits use 18px/24px text. |
flex + items_center + gap(px(8.)) | Root container geometry. |
flat row; no distinct group wrapper | Slot group geometry. |
h(px(40.)) + w(px(38.)) + alignment match | Slot dimensions and alignment. |
field/default background + field shadow + field_radius + 14px semibold | Default slot chrome and typography. |
instant hover/focus/invalid swaps | Animated slot-state interpolation. |
hover(default.hover background) | Hovered slot chrome. |
with_focus_ring on the cursor slot | Active slot chrome. |
value drawn without a distinct filled background | Filled slot background. |
whole-row disabled opacity | Disabled slot treatment. |
danger border on non-active slots | Invalid slot treatment. |
18px/24px text; no tracking or entrance animation | Filled character typography and entrance motion. |
2x16px hairline + anim::caret_blink | Fake caret geometry and motion. |
6x2px shrink-0 hairline radius + separator color | Separator geometry and color. |
FieldVariant::Secondary default background without field shadow | Secondary slot variant. |
API reference
Builders
| Builder | Type | Default | Description |
|---|---|---|---|
with_length( | cx, | — ( | Number of input slots. |
value( | code, | — | Controlled value. |
on_change( | Fn( | — | Handler called whenever the value changes. |
on_complete( | Fn( | — | Handler called when all slots are filled. |
variant( | FieldVariant | FieldVariant:: | Visual treatment of the slots. |
slot( | AnyElement | — | Composition of Group, Slot and Separator parts. |
is_disabled( | bool | false | Whether the input is disabled. |
is_invalid( | bool | false | Whether the input is invalid. |
validation_errors( | errors | — | Server-side or custom validation errors. |
pattern( | OtpPattern | — | Regular expression for accepted characters. |
text_align( | OtpTextAlign | OtpTextAlign:: | Text alignment within each slot. |
placeholder( | impl Into< | — | Placeholder text for empty slots. |
paste_transformer( | Fn( | — | Transforms pasted text before filling the slots. |
name( | string | — | Name used by form_field(); explicit Form registration is required. |
auto_focus( | bool | — | Focuses the first slot on mount. |
Parts
| Part | Description |
|---|---|
InputOTP | Root field and editing surface. |
InputOTP | Group of slots; implicit in the flat GPUI row. |
InputOTP | One indexed character slot. |
InputOTP | Optional separator bar after each three slots. |
States
| Builder | State | Description |
|---|---|---|
cell.hover(background) | Hovered | Hovered slot surface. |
focused && i == cursor + with_focus_ring | Active | Focused slot carrying the fake caret. |
cell_ch != ' ' value branch | Filled | Slot containing a character. |
is_disabled focus/key gates + row opacity | Disabled | Disabled root and slots. |
validation::resolve + danger border + ErrorMessage | Invalid | Invalid field treatment. |