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