use maud::{html, Markup};
#[derive(Debug, Clone)]
pub struct Props {
pub length: usize,
pub group_size: usize,
pub name: String,
pub id: String,
pub disabled: bool,
}
impl Default for Props {
fn default() -> Self {
Self {
length: 6,
group_size: 3,
name: "otp".to_string(),
id: "otp".to_string(),
disabled: false,
}
}
}
pub fn render(props: Props) -> Markup {
html! {
div class="mui-input-otp" data-mui="input-otp" role="group" aria-label="One-time password" {
@for i in 0..props.length {
@if i > 0 && props.group_size > 0 && i % props.group_size == 0 {
div class="mui-input-otp__separator" role="separator" {
div class="mui-input-otp__separator-dash" {}
}
}
input
type="text"
class="mui-input-otp__slot"
maxlength="1"
inputmode="numeric"
pattern="[0-9]"
autocomplete="one-time-code"
aria-label=(format!("Digit {}", i + 1))
name=(format!("{}-{}", props.name, i))
id=(format!("{}-{}", props.id, i))
disabled[props.disabled]
;
}
input
type="hidden"
name=(props.name.clone())
class="mui-input-otp__value"
;
}
}
}
pub fn showcase() -> Markup {
html! {
div.mui-showcase__grid {
section {
h2 { "Verify your email" }
p.mui-showcase__caption { "We sent a code to sofia@example.com" }
div style="display:flex;flex-direction:column;gap:0.75rem;max-width:22rem;" {
(render(Props {
length: 6,
group_size: 3,
name: "verify-email-code".to_string(),
id: "verify-email-code".to_string(),
disabled: false,
}))
div style="display:flex;justify-content:space-between;align-items:center;font-size:0.8125rem;" {
span style="color:var(--mui-text-muted);" { "Code expires in 9:42" }
button type="button" style="background:transparent;border:0;padding:0;color:var(--mui-text);font-weight:500;cursor:pointer;text-decoration:underline;font-size:0.8125rem;" {
"Resend"
}
}
}
}
section {
h2 { "Enter PIN" }
p.mui-showcase__caption { "Your transaction PIN" }
div style="display:flex;flex-direction:column;gap:0.5rem;max-width:18rem;" {
(render(Props {
length: 4,
group_size: 0,
name: "transaction-pin".to_string(),
id: "transaction-pin".to_string(),
disabled: false,
}))
p style="font-size:0.75rem;color:var(--mui-text-muted);margin:0;" {
"Confirms payments over $100. Never share this PIN."
}
}
}
section {
h2 { "2FA locked" }
p.mui-showcase__caption { "Too many failed attempts. Try again in 15 minutes." }
div style="max-width:22rem;" {
(render(Props {
length: 6,
group_size: 3,
name: "two-fa-locked".to_string(),
id: "two-fa-locked".to_string(),
disabled: true,
}))
}
}
}
}
}