rustyclaw_tui/components/
auth_dialog.rs1use crate::theme;
4use iocraft::prelude::*;
5
6#[derive(Default, Props)]
7pub struct AuthDialogProps {
8 pub code: String,
10 pub error: String,
12}
13
14#[component]
15pub fn AuthDialog(props: &AuthDialogProps) -> impl Into<AnyElement<'static>> {
16 let typed = &props.code;
18 let remaining = 6usize.saturating_sub(typed.len());
19 let display = format!("{}{}", typed, "·".repeat(remaining),);
20
21 let has_error = !props.error.is_empty();
22
23 element! {
24 View(
26 width: 100pct,
27 height: 100pct,
28 justify_content: JustifyContent::Center,
29 align_items: AlignItems::Center,
30 ) {
31 View(
33 width: 48,
34 flex_direction: FlexDirection::Column,
35 border_style: BorderStyle::Round,
36 border_color: theme::ACCENT_BRIGHT,
37 background_color: theme::BG_SURFACE,
38 padding_left: 2,
39 padding_right: 2,
40 padding_top: 1,
41 padding_bottom: 1,
42 ) {
43 Text(
45 content: "🔑 Gateway Authentication",
46 color: theme::ACCENT_BRIGHT,
47 weight: Weight::Bold,
48 )
49
50 View(height: 1)
52
53 Text(
55 content: "Enter your 6-digit TOTP code:",
56 color: theme::TEXT,
57 )
58
59 View(height: 1)
61
62 View(
64 flex_direction: FlexDirection::Row,
65 justify_content: JustifyContent::Center,
66 ) {
67 Text(
68 content: format!(" {} ", display),
69 color: theme::ACCENT_BRIGHT,
70 weight: Weight::Bold,
71 )
72 }
73
74 #(if has_error {
76 element! {
77 View(margin_top: 1) {
78 Text(content: props.error.clone(), color: theme::ERROR)
79 }
80 }.into_any()
81 } else {
82 element! {
83 View()
84 }.into_any()
85 })
86
87 View(height: 1)
89
90 Text(
92 content: "Enter ↩ submit · Esc cancel",
93 color: theme::MUTED,
94 )
95 }
96 }
97 }
98}