Skip to main content

dioxus_bootstrap/
list_group.rs

1use dioxus::prelude::*;
2use dioxus_router::navigation::NavigationTarget;
3use dioxus_router::components::Link;
4
5#[derive(Clone, Props, PartialEq)]
6pub struct ListGroupProps {
7    #[props(optional)]
8    id: String,
9    #[props(optional, default = "".to_string())]
10    class: String,
11    #[props(optional, default = false)]
12    flush: bool,
13    #[props(optional, default = false)]
14    horizontal: bool,
15    #[props(optional, default = false)]
16    numbered: bool,
17    children: Element,
18}
19
20#[component]
21pub fn ListGroup(props: ListGroupProps) -> Element {
22    let mut class_list = vec!["list-group".to_string()];
23    
24    if props.flush {
25        class_list.push("list-group-flush".to_string());
26    }
27    
28    if props.horizontal {
29        class_list.push("list-group-horizontal".to_string());
30    }
31    
32    if props.numbered {
33        class_list.push("list-group-numbered".to_string());
34    }
35    
36    if !props.class.is_empty() {
37        class_list.push(props.class.clone());
38    }
39    
40    let class_list = class_list.join(" ");
41    
42    if props.numbered {
43        rsx! {
44            ol {
45                id: props.id,
46                class: class_list,
47                {props.children}
48            }
49        }
50    } else {
51        rsx! {
52            ul {
53                id: props.id,
54                class: class_list,
55                {props.children}
56            }
57        }
58    }
59}
60
61#[derive(Clone, Copy, PartialEq)]
62pub enum ListGroupItemVariant {
63    Primary,
64    Secondary,
65    Success,
66    Danger,
67    Warning,
68    Info,
69    Light,
70    Dark,
71}
72
73impl Into<&'static str> for ListGroupItemVariant {
74    fn into(self) -> &'static str {
75        match self {
76            ListGroupItemVariant::Primary => "list-group-item-primary",
77            ListGroupItemVariant::Secondary => "list-group-item-secondary",
78            ListGroupItemVariant::Success => "list-group-item-success",
79            ListGroupItemVariant::Danger => "list-group-item-danger",
80            ListGroupItemVariant::Warning => "list-group-item-warning",
81            ListGroupItemVariant::Info => "list-group-item-info",
82            ListGroupItemVariant::Light => "list-group-item-light",
83            ListGroupItemVariant::Dark => "list-group-item-dark",
84        }
85    }
86}
87
88#[derive(Clone, Props, PartialEq)]
89pub struct ListGroupItemProps {
90    #[props(optional)]
91    id: String,
92    #[props(optional, default = "".to_string())]
93    class: String,
94    #[props(optional, default = false)]
95    active: bool,
96    #[props(optional, default = false)]
97    disabled: bool,
98    #[props(optional, default = None)]
99    variant: Option<ListGroupItemVariant>,
100    #[props(optional)]
101    href: Option<String>,
102    #[props(optional)]
103    link_to: Option<NavigationTarget>,
104    #[props(optional)]
105    onclick: EventHandler<MouseEvent>,
106    children: Element,
107}
108
109#[component]
110pub fn ListGroupItem(props: ListGroupItemProps) -> Element {
111    let mut class_list = vec!["list-group-item".to_string()];
112    
113    if props.active {
114        class_list.push("active".to_string());
115    }
116    
117    if props.disabled {
118        class_list.push("disabled".to_string());
119    }
120    
121    if let Some(variant) = props.variant {
122        let variant_class: &str = variant.into();
123        class_list.push(variant_class.to_string());
124    }
125    
126    // Add action class if it's clickable
127    if props.href.is_some() || props.link_to.is_some() {
128        class_list.push("list-group-item-action".to_string());
129    }
130    
131    if !props.class.is_empty() {
132        class_list.push(props.class.clone());
133    }
134    
135    let class_list = class_list.join(" ");
136    
137    match (props.link_to, props.href) {
138        (Some(to), _) if !props.disabled => rsx! {
139            Link {
140                id: props.id,
141                class: class_list,
142                to: to,
143                onclick: props.onclick,
144                {props.children}
145            }
146        },
147        (None, Some(href)) if !props.disabled => rsx! {
148            a {
149                id: props.id,
150                class: class_list,
151                href: href,
152                onclick: props.onclick,
153                {props.children}
154            }
155        },
156        _ => rsx! {
157            li {
158                id: props.id,
159                class: class_list,
160                onclick: props.onclick,
161                {props.children}
162            }
163        }
164    }
165}