dioxus_tw_components/components/
tabs.rs1use dioxus::prelude::*;
2
3struct TabsState(String);
4
5#[derive(Clone, PartialEq, Props)]
6pub struct TabsProps {
7 #[props(optional)]
8 default_tab: ReadSignal<String>,
9
10 #[props(extends = div, extends = GlobalAttributes)]
11 attributes: Vec<Attribute>,
12
13 children: Element,
14}
15
16#[component]
17pub fn Tabs(props: TabsProps) -> Element {
18 use_context_provider(|| Signal::new(TabsState(props.default_tab.read().clone())));
19
20 rsx! {
21 div { ..props.attributes, {props.children} }
22 }
23}
24
25#[derive(Clone, PartialEq, Props)]
26pub struct TabsListProps {
27 #[props(extends = div, extends = GlobalAttributes)]
28 attributes: Vec<Attribute>,
29
30 children: Element,
31}
32
33#[component]
34pub fn TabsList(mut props: TabsListProps) -> Element {
35 let default_classes = "tabs-list";
36 crate::setup_class_attribute(&mut props.attributes, default_classes);
37
38 rsx! {
39 div { ..props.attributes, {props.children} }
40 }
41}
42
43#[derive(Clone, PartialEq, Props)]
44pub struct TabsTriggerProps {
45 #[props(extends = button, extends = GlobalAttributes)]
46 attributes: Vec<Attribute>,
47
48 #[props(optional)]
49 id: ReadSignal<String>,
50
51 children: Element,
52}
53
54#[component]
55pub fn TabsTrigger(mut props: TabsTriggerProps) -> Element {
56 let mut state = use_context::<Signal<TabsState>>();
57
58 let default_classes = "tabs-trigger";
59 crate::setup_class_attribute(&mut props.attributes, default_classes);
60
61 let is_active = state.read().0 == *props.id.read();
62
63 let onclick = move |_: MouseEvent| {
64 state.write().0 = props.id.read().clone();
65 };
66
67 rsx! {
68 button {
69 "data-state": if is_active { "active" } else { "inactive" },
70 onclick,
71 ..props.attributes,
72 {props.children}
73 }
74 }
75}
76
77#[derive(Clone, PartialEq, Props)]
78pub struct TabsContentProps {
79 #[props(extends = div, extends = GlobalAttributes)]
80 attributes: Vec<Attribute>,
81
82 #[props(optional)]
83 id: ReadSignal<String>,
84
85 children: Element,
86}
87
88#[component]
89pub fn TabsContent(mut props: TabsContentProps) -> Element {
90 let state = use_context::<Signal<TabsState>>();
91
92 let default_classes = "tabs-content";
93 crate::setup_class_attribute(&mut props.attributes, default_classes);
94
95 let is_active = state.read().0 == *props.id.read();
96
97 rsx! {
98 div {
99 "data-state": if is_active { "active" } else { "inactive" },
100 ..props.attributes,
101 {props.children}
102 }
103 }
104}