Feedback Components
Components for user feedback: alerts, badges, progress indicators, and toasts.
Alert
Display important messages:
#![allow(unused)]
fn main() {
use blinc_cn::prelude::*;
alert()
.child(alert_title("Heads up!"))
.child(alert_description("This is an important message."))
}
Alert Variants
#![allow(unused)]
fn main() {
// Default
alert()
.child(alert_title("Note"))
.child(alert_description("This is a note."))
// Destructive (error/warning)
alert()
.variant(AlertVariant::Destructive)
.child(alert_title("Error"))
.child(alert_description("Something went wrong."))
}
With Icon
#![allow(unused)]
fn main() {
alert()
.child(icon(icons::INFO).size(16.0))
.child(alert_title("Information"))
.child(alert_description("Here's some useful info."))
}
Badge
Small labels for status or counts:
#![allow(unused)]
fn main() {
badge("New")
badge("3").variant(BadgeVariant::Secondary)
badge("Error").variant(BadgeVariant::Destructive)
badge("Beta").variant(BadgeVariant::Outline)
}
Badge Variants
#![allow(unused)]
fn main() {
// Default - primary color
badge("Default")
// Secondary - muted color
badge("Secondary").variant(BadgeVariant::Secondary)
// Destructive - error/warning
badge("Destructive").variant(BadgeVariant::Destructive)
// Outline - bordered
badge("Outline").variant(BadgeVariant::Outline)
}
With Icon
#![allow(unused)]
fn main() {
badge("")
.variant(BadgeVariant::Outline)
.child(icon(icons::CHECK).size(12.0))
.child(text("Verified"))
}
Progress
Progress bar:
#![allow(unused)]
fn main() {
progress()
.value(75.0) // 0-100
}
Indeterminate
#![allow(unused)]
fn main() {
progress()
.indeterminate(true)
}
With Label
#![allow(unused)]
fn main() {
div()
.flex_col()
.gap(4.0)
.child(
div().flex_row().justify_between()
.child(text("Uploading..."))
.child(text(format!("{}%", progress_value)))
)
.child(progress().value(progress_value))
}
Spinner
Loading indicator:
#![allow(unused)]
fn main() {
spinner()
}
Spinner Sizes
#![allow(unused)]
fn main() {
spinner().size(SpinnerSize::Sm) // Small
spinner().size(SpinnerSize::Md) // Medium (default)
spinner().size(SpinnerSize::Lg) // Large
}
In Button
#![allow(unused)]
fn main() {
button(if is_loading { "" } else { "Save" })
.loading(is_loading)
.disabled(is_loading)
}
Skeleton
Placeholder for loading content:
#![allow(unused)]
fn main() {
skeleton().w(200.0).h(20.0)
}
Card Skeleton
#![allow(unused)]
fn main() {
card()
.child(card_header()
.child(skeleton().w(150.0).h(24.0)) // Title placeholder
.child(skeleton().w(200.0).h(16.0))) // Description placeholder
.child(card_content()
.child(skeleton().w_full().h(100.0))) // Content placeholder
}
List Skeleton
#![allow(unused)]
fn main() {
div()
.flex_col()
.gap(12.0)
.child(
div().flex_row().gap(12.0)
.child(skeleton().w(48.0).h(48.0).rounded_full()) // Avatar
.child(
div().flex_col().gap(4.0)
.child(skeleton().w(150.0).h(16.0)) // Name
.child(skeleton().w(100.0).h(14.0))) // Subtitle
)
// Repeat for more items...
}
Toast
Temporary notifications:
#![allow(unused)]
fn main() {
// Show a toast
show_toast(
toast()
.title("Success")
.description("Your changes have been saved.")
);
// With variant
show_toast(
toast()
.variant(ToastVariant::Destructive)
.title("Error")
.description("Failed to save changes.")
);
}
Toast Variants
#![allow(unused)]
fn main() {
// Default
toast().title("Notification")
// Success
toast()
.variant(ToastVariant::Success)
.title("Success")
// Destructive/Error
toast()
.variant(ToastVariant::Destructive)
.title("Error")
}
With Action
#![allow(unused)]
fn main() {
toast()
.title("Event created")
.description("Friday, February 10, 2024")
.action(
toast_action()
.child(button("Undo").size(ButtonSize::Sm))
.on_click(|| undo_action())
)
}
Toast Position
#![allow(unused)]
fn main() {
// Configure toast container position
toaster()
.position(ToasterPosition::TopRight) // TopLeft, TopRight, BottomLeft, BottomRight
}
Examples
Loading State
#![allow(unused)]
fn main() {
let is_loading = use_state(true);
if is_loading {
div()
.flex_col()
.items_center()
.gap(16.0)
.child(spinner().size(SpinnerSize::Lg))
.child(text("Loading..."))
} else {
// Actual content
}
}
Form Submission Feedback
#![allow(unused)]
fn main() {
let status = use_state(FormStatus::Idle);
div()
.flex_col()
.gap(16.0)
.child(/* form fields */)
.child(
match status {
FormStatus::Idle => button("Submit").on_click(|| submit()),
FormStatus::Submitting => button("").loading(true).disabled(true),
FormStatus::Success => alert()
.child(alert_title("Success"))
.child(alert_description("Form submitted successfully!")),
FormStatus::Error(msg) => alert()
.variant(AlertVariant::Destructive)
.child(alert_title("Error"))
.child(alert_description(msg)),
}
)
}
Notification Center
#![allow(unused)]
fn main() {
fn notify_success(message: &str) {
show_toast(
toast()
.variant(ToastVariant::Success)
.title("Success")
.description(message)
.duration(Duration::from_secs(5))
);
}
fn notify_error(message: &str) {
show_toast(
toast()
.variant(ToastVariant::Destructive)
.title("Error")
.description(message)
.duration(Duration::from_secs(10))
);
}
}