ui_storybook/stories/
controls.rs1use leptos::prelude::*;
4
5use crate::components::primitives::{
6 ColorSwatch, IconButton, IconButtonVariant, Meter, Segment, SegmentedControl, SelectPill,
7 Slider, ToggleSwitch,
8};
9
10use super::{Story, StoryViewport, render};
11
12#[must_use]
14pub fn stories() -> Vec<Story> {
15 vec![
16 Story {
17 id: "controls-buttons-icon-buttons",
18 category: "Primitives",
19 title: "Controls — icon buttons",
20 viewport: StoryViewport::Auto,
21 render: render_icon_buttons,
22 },
23 Story {
24 id: "controls-toggle-states",
25 category: "Primitives",
26 title: "Controls — toggle switch states",
27 viewport: StoryViewport::Auto,
28 render: render_toggle_states,
29 },
30 Story {
31 id: "controls-segmented-record-mode",
32 category: "Primitives",
33 title: "Controls — segmented record mode",
34 viewport: StoryViewport::Auto,
35 render: render_segmented,
36 },
37 Story {
38 id: "controls-slider-values",
39 category: "Primitives",
40 title: "Controls — slider matrix",
41 viewport: StoryViewport::Auto,
42 render: render_sliders,
43 },
44 Story {
45 id: "controls-color-swatches",
46 category: "Primitives",
47 title: "Controls — color swatches",
48 viewport: StoryViewport::Auto,
49 render: render_color_swatches,
50 },
51 Story {
52 id: "controls-meters",
53 category: "Primitives",
54 title: "Controls — audio level meters",
55 viewport: StoryViewport::Auto,
56 render: render_meters,
57 },
58 ]
59}
60
61fn render_icon_buttons() -> String {
62 render(view! {
63 <div class="story-row" style="padding:14px;gap:14px">
64 <IconButton glyph="●" label="Record" variant=IconButtonVariant::Danger />
65 <IconButton glyph="◼" label="Stop" variant=IconButtonVariant::Filled />
66 <IconButton glyph="↻" label="Reset" variant=IconButtonVariant::Ghost />
67 <IconButton glyph="✱" label="Pinned" variant=IconButtonVariant::Ghost pressed=true />
68 <IconButton glyph="⌫" label="Delete" variant=IconButtonVariant::Ghost disabled=true />
69 </div>
70 })
71}
72
73fn render_toggle_states() -> String {
74 render(view! {
75 <div class="story-row" style="padding:14px;gap:20px">
76 <div class="story-row" style="flex-direction:column;align-items:center;gap:6px">
77 <ToggleSwitch checked=false label="off" />
78 <span style="font-size:11px;color:var(--text-tertiary)">"Off"</span>
79 </div>
80 <div class="story-row" style="flex-direction:column;align-items:center;gap:6px">
81 <ToggleSwitch checked=true label="on" />
82 <span style="font-size:11px;color:var(--text-tertiary)">"On"</span>
83 </div>
84 <div class="story-row" style="flex-direction:column;align-items:center;gap:6px">
85 <ToggleSwitch checked=false disabled=true label="disabled off" />
86 <span style="font-size:11px;color:var(--text-tertiary)">"Disabled off"</span>
87 </div>
88 <div class="story-row" style="flex-direction:column;align-items:center;gap:6px">
89 <ToggleSwitch checked=true disabled=true label="disabled on" />
90 <span style="font-size:11px;color:var(--text-tertiary)">"Disabled on"</span>
91 </div>
92 </div>
93 })
94}
95
96fn render_segmented() -> String {
97 let segments = vec![
98 Segment {
99 id: "screen",
100 label: "Screen",
101 icon: Some("▢"),
102 disabled: false,
103 },
104 Segment {
105 id: "window",
106 label: "Window",
107 icon: Some("◫"),
108 disabled: false,
109 },
110 Segment {
111 id: "area",
112 label: "Area",
113 icon: Some("⊞"),
114 disabled: false,
115 },
116 ];
117 render(view! {
118 <div style="padding:14px;display:flex;flex-direction:column;gap:14px;align-items:flex-start">
119 <SegmentedControl segments=segments.clone() active="screen" label="Capture mode" />
120 <SegmentedControl segments=segments.clone() active="window" label="Capture mode (window)" />
121 <SegmentedControl segments=segments active="area" label="Capture mode (area)" />
122 </div>
123 })
124}
125
126fn render_sliders() -> String {
127 render(view! {
128 <div style="padding:14px;display:flex;flex-direction:column;gap:14px;width:360px">
129 <Slider value=0.0 label="Min".to_string() readout="0%".to_string() />
130 <Slider value=0.42 label="Volume".to_string() readout="42%".to_string() />
131 <Slider value=1.0 label="Max".to_string() readout="100%".to_string() />
132 <Slider value=0.5 min=0.0 max=10.0 label="Disabled".to_string() readout="5.0".to_string() disabled=true />
133 </div>
134 })
135}
136
137fn render_color_swatches() -> String {
138 render(view! {
139 <div class="story-row" style="padding:14px;gap:10px">
140 <ColorSwatch color="#fafafa".to_string() label="White".to_string() selected=true />
141 <ColorSwatch color="#ef4444".to_string() label="Red".to_string() />
142 <ColorSwatch color="#f59e0b".to_string() label="Amber".to_string() />
143 <ColorSwatch color="#10b981".to_string() label="Emerald".to_string() />
144 <ColorSwatch color="#38bdf8".to_string() label="Sky".to_string() />
145 <ColorSwatch color="#a78bfa".to_string() label="Violet".to_string() />
146 <ColorSwatch color="#18181b".to_string() label="Zinc".to_string() />
147 </div>
148 })
149}
150
151fn render_meters() -> String {
152 render(view! {
153 <div style="padding:14px;display:flex;flex-direction:column;gap:10px;width:280px">
154 <div class="story-row" style="gap:10px">
155 <span style="width:60px;font-size:11px;color:var(--text-secondary)">"Silent"</span>
156 <Meter level=0.0 />
157 </div>
158 <div class="story-row" style="gap:10px">
159 <span style="width:60px;font-size:11px;color:var(--text-secondary)">"Low"</span>
160 <Meter level=0.25 />
161 </div>
162 <div class="story-row" style="gap:10px">
163 <span style="width:60px;font-size:11px;color:var(--text-secondary)">"Mid"</span>
164 <Meter level=0.6 />
165 </div>
166 <div class="story-row" style="gap:10px">
167 <span style="width:60px;font-size:11px;color:var(--text-secondary)">"Loud"</span>
168 <Meter level=0.85 />
169 </div>
170 <div class="story-row" style="gap:10px">
171 <span style="width:60px;font-size:11px;color:var(--text-secondary)">"Clipping"</span>
172 <Meter level=1.0 danger=true />
173 </div>
174 <SelectPill icon="🎙".to_string() label="Built-in microphone".to_string() />
175 </div>
176 })
177}