leptos_components/
badge.rs1use components_core::{BASE_CLASS, concat};
2use leptos::prelude::*;
3use leptos::{IntoView, component, view};
4
5const LIMIT_NUMERIC: isize = 9;
6const LIMIT_NUMERIC_NEGATIVE: isize = -9;
7
8#[derive(Default, Debug, PartialEq)]
9pub enum Variant {
10 Completed,
11 Reading,
12 #[default]
13 Pending,
14 Unread,
15}
16
17impl Variant {
18 pub fn text(&self) -> &'static str {
19 match self {
20 Variant::Completed => "Completo",
21 Variant::Reading => "Leyendo",
22 Variant::Pending => "Pendiente",
23 Variant::Unread => "No leido",
24 }
25 }
26}
27
28#[derive(Default, Debug, PartialEq)]
29pub enum Type {
30 #[default]
31 Default,
32 Numeric,
33 Text,
34}
35
36#[component]
37pub fn Badge(
38 #[prop(into)] count: ReadSignal<isize>,
39 #[prop(into, optional)] variant: Variant,
40 #[prop(into, optional)] r#type: Type,
41) -> impl IntoView {
42 let class = crate::tw!(
43 concat!("text-paragraph-2 ", BASE_CLASS, "-badge"),
44 format!("{BASE_CLASS}-badge--variant-{variant:?}"),
45 format!("{BASE_CLASS}-badge--type-{type:?}"),
46 );
47
48 let display_value = move || match r#type {
49 Type::Default => count.get().to_string(),
50 Type::Numeric => {
51 let count = count.get();
52 match count {
53 ..=LIMIT_NUMERIC_NEGATIVE => LIMIT_NUMERIC_NEGATIVE.to_string(),
54 LIMIT_NUMERIC.. => format!("+{LIMIT_NUMERIC}"),
55 _ => count.to_string(),
56 }
57 }
58 Type::Text => variant.text().to_string(),
59 };
60
61 view! {
62 <div
63 class={class}
64 >
65 <div class={concat!(BASE_CLASS, "-badge__dot")} />
66 <span>{display_value}</span>
67 </div>
68 }
69}