Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

OTP RS

Edit Component

Y OTP RS Yew Usage

Adding OTP RS to your project is simple:

  1. Make sure your project is set up with Yew. Follow their Getting Started Guide for setup instructions.

  2. Add the OTP RS component to your dependencies by including it in your Cargo.toml file:

    cargo add otprs --features=yew
    
  3. Import the Otp, Group, Separator, and Slot components into your Yew component and start using them in your app.

🛠️ Usage

Basic 6-Digit OTP

use otprs::yew::{Otp, Group, Separator, Slot};
use yew::prelude::*;

#[function_component(BasicOtp)]
pub fn basic_otp() -> Html {
    html! {
        <Otp max_length={6} aria_label="Enter verification code">
            <Group>
                <Slot index={0} />
                <Slot index={1} />
                <Slot index={2} />
            </Group>
            <Separator />
            <Group>
                <Slot index={3} />
                <Slot index={4} />
                <Slot index={5} />
            </Group>
        </Otp>
    }
}

Controlled with on_complete

use otprs::yew::{Otp, Group, Separator, Slot};
use yew::prelude::*;

#[function_component(ControlledOtp)]
pub fn controlled_otp() -> Html {
    let value = use_state(String::new);
    let on_change = {
        let value = value.clone();
        Callback::from(move |v: String| value.set(v))
    };
    let on_complete = Callback::from(|code: String| {
        web_sys::console::log_1(&format!("Complete: {code}").into());
    });
    html! {
        <Otp
            max_length={6}
            value={(*value).clone()}
            on_change={on_change}
            on_complete={on_complete}
            aria_label="Verification code"
        >
            <Group>
                <Slot index={0} />
                <Slot index={1} />
                <Slot index={2} />
            </Group>
            <Separator />
            <Group>
                <Slot index={3} />
                <Slot index={4} />
                <Slot index={5} />
            </Group>
        </Otp>
    }
}

Disabled State

use otprs::yew::{Otp, Group, Slot};
use yew::prelude::*;

#[function_component(DisabledOtp)]
pub fn disabled_otp() -> Html {
    html! {
        <Otp max_length={4} is_disabled={true} aria_label="Disabled PIN">
            <Group>
                <Slot index={0} />
                <Slot index={1} />
                <Slot index={2} />
                <Slot index={3} />
            </Group>
        </Otp>
    }
}

Secondary Variant (for Surface backgrounds)

use otprs::yew::{Otp, Group, Separator, Slot};
use otprs::Variant;
use yew::prelude::*;

#[function_component(SecondaryOtp)]
pub fn secondary_otp() -> Html {
    html! {
        <Otp max_length={6} variant={Variant::Secondary} aria_label="Enter code">
            <Group>
                <Slot index={0} />
                <Slot index={1} />
                <Slot index={2} />
            </Group>
            <Separator />
            <Group>
                <Slot index={3} />
                <Slot index={4} />
                <Slot index={5} />
            </Group>
        </Otp>
    }
}

🔧 Props

Otp

PropertyTypeDescriptionDefault
max_lengthusizeTotal slot count.6
valueStringControlled value.""
on_changeCallback<String>Called on every keystroke.no-op
on_completeCallback<String>Called when all slots filled.no-op
is_disabledboolDisables all slots.false
is_invalidboolShows error state on all slots.false
variantVariantPrimary or Secondary.Primary
pattern&'static strAllowed character regex."[0-9]"
input_modeInputModeMobile keyboard type.Numeric
name&'static strHidden input name for forms.""
auto_focusboolFocus first slot on mount.false
class&'static strExtra CSS class on root.""
style&'static strExtra inline CSS on root.""
id&'static strid on root element.""
aria_label&'static strScreen-reader label."One-time password"
aria_describedby&'static strError description element id.""
container_class&'static strVlass on inner container.""
container_style&'static strInline CSS on inner container.""

Slot

PropertyTypeDescriptionDefault
indexusizeZero-based slot index. Required.-
class&'static strExtra CSS on slot wrapper.""
style&'static strExtra inline CSS on slot.""
id&'static strid on slot wrapper.""

Group

PropertyTypeDescriptionDefault
class&'static strExtra CSS on group.""
style&'static strInline CSS on group.""
id&'static strid on group element.""

Separator

PropertyTypeDescriptionDefault
class&'static strExtra CSS on separator.""
style&'static strInline CSS on separator.""

💡 Notes

  • Slot must be a descendant of Otp, it reads context from the parent.
  • The caret blinks inside the active empty slot for a native feel.
  • Use pattern={otprs::pattern::CHARS_ONLY} for letter-only codes.
  • Use is_invalid={true} together with aria_describedby to surface errors accessibly.

🔗 See Also

  • Input RS: The unstyled <input> abstraction layer powering the invisible focus engine.
  • RFC 4226: HOTP: An HMAC-Based One-Time Password Algorithm.
  • RFC 6238: TOTP: Time-Based One-Time Password Algorithm.
  • totp-rs: The underlying Rust crate used by otprs for TOTP validation.

Usage

CLI Usage

You can import OTP RS directly into your project to customize and modify it using the opensass cli:

os add otprs yew