orbital_base_components/data/list/
base.rs1use leptos::prelude::*;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum ListNavigationMode {
5 Selectable,
6 Nav,
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum ListSelectionMode {
11 Single,
12 Multiselect,
13}
14
15#[component]
16pub fn BaseList(
17 #[prop(optional, into)] class: MaybeProp<String>,
18 #[prop(optional, into)] navigation_mode: Signal<Option<ListNavigationMode>>,
19 #[prop(optional, into)] selection_mode: Signal<Option<ListSelectionMode>>,
20 children: Children,
21) -> impl IntoView {
22 let role = move || {
23 if selection_mode.get().is_some() {
24 "listbox"
25 } else {
26 "list"
27 }
28 };
29
30 view! {
31 <ul
32 class=move || {
33 let mut parts = vec!["orbital-list".to_string()];
34 if let Some(mode) = navigation_mode.get() {
35 parts.push(format!("orbital-list--nav-{}", mode_as_str(mode)));
36 }
37 if let Some(mode) = selection_mode.get() {
38 parts.push(format!("orbital-list--select-{}", select_mode_as_str(mode)));
39 }
40 if let Some(extra) = class.get() {
41 if !extra.is_empty() {
42 parts.push(extra);
43 }
44 }
45 parts.join(" ")
46 }
47 role=role
48 >
49 {children()}
50 </ul>
51 }
52}
53
54fn mode_as_str(mode: ListNavigationMode) -> &'static str {
55 match mode {
56 ListNavigationMode::Selectable => "selectable",
57 ListNavigationMode::Nav => "nav",
58 }
59}
60
61fn select_mode_as_str(mode: ListSelectionMode) -> &'static str {
62 match mode {
63 ListSelectionMode::Single => "single",
64 ListSelectionMode::Multiselect => "multiselect",
65 }
66}
67
68#[component]
69pub fn BaseListItem(
70 #[prop(optional, into)] class: MaybeProp<String>,
71 #[prop(optional, into)] selected: Signal<bool>,
72 #[prop(optional)] on_click: Option<Callback<()>>,
73 children: Children,
74) -> impl IntoView {
75 view! {
76 <li
77 class=move || {
78 let mut parts = vec!["orbital-list__item".to_string()];
79 if selected.get() {
80 parts.push("orbital-list__item--selected".to_string());
81 }
82 if let Some(extra) = class.get() {
83 if !extra.is_empty() {
84 parts.push(extra);
85 }
86 }
87 parts.join(" ")
88 }
89 role="listitem"
90 aria-selected=move || selected.get().then_some("true")
91 tabindex=move || if selected.get() { "0" } else { "-1" }
92 on:click=move |_| {
93 if let Some(cb) = on_click {
94 cb.run(());
95 }
96 }
97 >
98 {children()}
99 </li>
100 }
101}