yew_bootstrap/component/list_group.rs
1use yew::prelude::*;
2use crate::util::Color;
3use super::*;
4
5/// The variant style of a [ListGroup]
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7pub enum ListGroupVariant {
8 /// Default style, with rounded corners and outer borders.
9 Default,
10 /// Flush style, removes rounding and border.
11 Flush,
12}
13
14impl Default for ListGroupVariant {
15 fn default() -> Self {
16 ListGroupVariant::Default
17 }
18}
19
20/// A size threshold to trigger a property at
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub enum SizeTrigger {
23 /// Trigger at the given size boundary
24 AtSize(ContainerSize),
25 /// Always active
26 Always,
27 /// Never active
28 Never,
29}
30
31/// # Properties of [ListGroup]
32#[derive(Properties, Clone, PartialEq)]
33pub struct ListGroupProps {
34 /// Inner items (displayed in the [ListGroup]).
35 #[prop_or_default]
36 pub children: ChildrenWithProps<ListGroupItem>,
37 /// Extra CSS classes to include, in addition to the defaults.
38 #[prop_or_default]
39 pub class: Classes,
40 /// Display variant to use, see [ListGroupVariant] for all options.
41 #[prop_or_default]
42 pub variant: ListGroupVariant,
43 /// Whether to number the list.
44 #[prop_or_default]
45 pub numbered: bool,
46 /// Control when the list is displayed horizontally. Always, or at a certain container size.
47 #[prop_or(SizeTrigger::Never)]
48 pub horizontal: SizeTrigger,
49}
50
51/// # ListGroup component
52/// A list of items with various properties, including support for numbering, actions, and item
53/// colors.
54///
55/// Items are expected to be instances of [ListGroupItem]
56///
57/// See [ListGroupProps] for a list of properties.
58///
59/// ## Example
60/// Example of a simple list group:
61///
62/// ```rust
63/// use yew::prelude::*;
64/// use yew_bootstrap::component::{ListGroup, ListGroupItem};
65/// fn test() -> Html {
66/// html! {
67/// <ListGroup>
68/// <ListGroupItem>{"First"}</ListGroupItem>
69/// <ListGroupItem active=true>{"Second"}</ListGroupItem>
70/// <ListGroupItem>{"Third"}</ListGroupItem>
71/// </ListGroup>
72/// }
73/// }
74///
75#[function_component]
76pub fn ListGroup(props: &ListGroupProps) -> Html {
77 let mut classes = Classes::from("list-group");
78
79 classes.extend(&props.class);
80
81 match props.variant {
82 ListGroupVariant::Default => (),
83 ListGroupVariant::Flush => classes.push("list-group-flush"),
84 };
85
86 match &props.horizontal {
87 SizeTrigger::Never => (),
88 SizeTrigger::Always => classes.push("list-group-horizontal"),
89 SizeTrigger::AtSize(size) => classes.push(format!("list-group-horizontal-{}", size.to_string())),
90 }
91
92 if props.numbered {
93 classes.push("list-group-numbered")
94 }
95
96 html! {
97 <div class={classes}>
98 { for props.children.iter() }
99 </div>
100 }
101}
102
103/// # Properties for [ListGroupItem]
104#[derive(Properties, Clone, PartialEq)]
105pub struct ListGroupItemProps {
106 /// Inner components (displayed in the [ListGroupItem]).
107 #[prop_or_default]
108 pub children: Children,
109 /// Extra CSS classes to include, in addition to the defaults.
110 #[prop_or_default]
111 pub class: Classes,
112 /// Optional color to use for the background and border of this item.
113 #[prop_or_default]
114 pub style: Option<Color>,
115 /// Whether this item is the currently active one
116 #[prop_or_default]
117 pub active: bool,
118 /// Whether this item is disabled
119 #[prop_or_default]
120 pub disabled: bool,
121 /// Whether this item is actionable, enables hover and click reactivity.
122 #[prop_or_default]
123 pub action: bool,
124 /// URL to direct to when the list item is clicked
125 #[prop_or_default]
126 pub url: Option<AttrValue>,
127 /// Event called when the list item is clicked
128 #[prop_or_default]
129 pub onclick: Callback<MouseEvent>,
130}
131
132/// # ListGroupItem
133/// Used with [ListGroup] to create grouped lists of items.
134///
135/// See [ListGroupItemProps] for a list of properties.
136///
137/// ## Example
138/// Example of a simple list group:
139///
140/// ```rust
141/// use yew::prelude::*;
142/// use yew_bootstrap::component::{ListGroup, ListGroupItem};
143/// use yew_bootstrap::util::Color;
144/// fn test() -> Html {
145/// html! {
146/// <ListGroup>
147/// <ListGroupItem style={Color::Light}>{"First"}</ListGroupItem>
148/// <ListGroupItem active=true>{"Second"}</ListGroupItem>
149/// <ListGroupItem disabled=true>{"Third"}</ListGroupItem>
150/// </ListGroup>
151/// }
152/// }
153///
154#[function_component]
155pub fn ListGroupItem(props: &ListGroupItemProps) -> Html {
156 let mut classes = Classes::from("list-group-item");
157
158 classes.extend(&props.class);
159
160 if props.active {
161 classes.push("active");
162 }
163 if props.disabled {
164 classes.push("disabled");
165 }
166 if let Some(style) = &props.style {
167 classes.push(format!("list-group-item-{}", style));
168 }
169
170 if props.action && props.url.is_some() {
171 classes.push("list-group-item-action");
172 html! {
173 <a class={classes} href={&props.url} onclick={props.onclick.clone()}>
174 {props.children.clone()}
175 </a>
176 }
177 } else if props.action {
178 classes.push("list-group-item-action");
179 html! {
180 <button class={classes} onclick={props.onclick.clone()}>
181 {props.children.clone()}
182 </button>
183 }
184 } else {
185 html! {
186 <div class={classes}>
187 {props.children.clone()}
188 </div>
189 }
190 }
191}