Skip to content

Commit 8b5029b

Browse files
make switch input (#1083)
1 parent 42c5d70 commit 8b5029b

File tree

8 files changed

+241
-1
lines changed

8 files changed

+241
-1
lines changed

pgml-dashboard/src/components/inputs/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@ pub use range_group::RangeGroup;
99
pub mod select;
1010
pub use select::Select;
1111

12+
// src/components/inputs/switch
13+
pub mod switch;
14+
pub use switch::Switch;
15+
1216
// src/components/inputs/text
1317
pub mod text;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use crate::components::stimulus::stimulus_action::StimulusAction;
2+
use crate::components::stimulus::stimulus_target::StimulusTarget;
3+
use pgml_components::component;
4+
use sailfish::TemplateOnce;
5+
use std::fmt::{self, Display, Formatter};
6+
7+
pub enum State {
8+
Left,
9+
Right,
10+
}
11+
12+
impl Display for State {
13+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
14+
match self {
15+
State::Left => write!(f, "left"),
16+
State::Right => write!(f, "right"),
17+
}
18+
}
19+
}
20+
21+
#[derive(TemplateOnce)]
22+
#[template(path = "inputs/switch/template.html")]
23+
pub struct Switch {
24+
left_value: String,
25+
left_icon: String,
26+
right_value: String,
27+
right_icon: String,
28+
initial_state: State,
29+
on_toggle: Vec<StimulusAction>,
30+
target: StimulusTarget,
31+
}
32+
33+
impl Switch {
34+
pub fn new() -> Switch {
35+
Switch {
36+
left_value: String::from("left"),
37+
left_icon: String::from(""),
38+
right_value: String::from("right"),
39+
right_icon: String::from(""),
40+
on_toggle: Vec::new(),
41+
initial_state: State::Left,
42+
target: StimulusTarget::new(),
43+
}
44+
}
45+
46+
pub fn left(mut self, value: &str, icon: &str) -> Switch {
47+
self.left_value = value.into();
48+
self.left_icon = icon.into();
49+
self
50+
}
51+
52+
pub fn right(mut self, value: &str, icon: &str) -> Switch {
53+
self.right_value = value.into();
54+
self.right_icon = icon.into();
55+
self
56+
}
57+
58+
pub fn on_toggle(mut self, action: StimulusAction) -> Switch {
59+
self.on_toggle.push(action);
60+
self
61+
}
62+
63+
pub fn start_toggled(mut self) -> Switch {
64+
self.initial_state = State::Right;
65+
self
66+
}
67+
68+
pub fn target(mut self, target: StimulusTarget) -> Switch {
69+
self.target = target;
70+
self
71+
}
72+
}
73+
74+
component!(Switch);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
div[data-controller="inputs-switch"] {
2+
&.switch-container {
3+
background: #{$gray-100};
4+
border-radius: 5rem;
5+
border: 3px solid #{$gray-100};
6+
position: relative;
7+
}
8+
9+
.label {
10+
padding: 8px 20px;
11+
border-radius: 5rem;
12+
text-align: center;
13+
display: flex;
14+
@extend .gap-2;
15+
}
16+
17+
.toggle {
18+
background: #{$neon-shade-100};
19+
position: absolute;
20+
top: 0px;
21+
left: 0px;
22+
}
23+
24+
.choice {
25+
background: #{$gray-100};
26+
color: #{$neon-shade-100};
27+
flex: 1;
28+
29+
* {
30+
color: inherit;
31+
}
32+
}
33+
34+
.left {
35+
left: 0;
36+
transition: all $animation-timer;
37+
}
38+
39+
.right {
40+
left: 50%;
41+
transition: all $animation-timer;
42+
}
43+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Controller } from '@hotwired/stimulus'
2+
3+
export default class extends Controller {
4+
static targets = [
5+
"toggle",
6+
"toggleText",
7+
"toggleIcon",
8+
]
9+
10+
static values = {
11+
"left": String,
12+
"right": String,
13+
"initial": String,
14+
"leftIcon": String,
15+
"rightIcon": String,
16+
}
17+
18+
toggle() {
19+
if (this.toggleTarget.classList.contains('right')) {
20+
this.onToggleLeft()
21+
} else {
22+
this.onToggleRight()
23+
}
24+
}
25+
26+
onToggleLeft() {
27+
this.toggleTarget.classList.remove('right')
28+
this.toggleTarget.classList.add('left')
29+
this.toggleTextTarget.innerHTML = this.leftValue
30+
this.toggleIconTarget.innerHTML = this.leftIconValue
31+
this.element.dispatchEvent(new CustomEvent('toggle', {detail: this.leftValue}))
32+
}
33+
34+
onToggleRight() {
35+
this.toggleTarget.classList.remove('left')
36+
this.toggleTarget.classList.add('right')
37+
this.toggleTextTarget.innerHTML = this.rightValue
38+
this.toggleIconTarget.innerHTML = this.rightIconValue
39+
this.element.dispatchEvent(new CustomEvent('toggle', {detail: this.rightValue}))
40+
}
41+
42+
reset() {
43+
if( this.initialValue == "left" ) {
44+
console.log("toggling left")
45+
this.onToggleLeft()
46+
} else {
47+
console.log("toggling right")
48+
this.onToggleRight()
49+
}
50+
}
51+
52+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<% use crate::components::inputs::switch::State; %>
2+
<div data-controller="inputs-switch"
3+
class="switch-container d-flex flex-row"
4+
data-action='click->inputs-switch#toggle <% for action in on_toggle { %> toggle-><%- action %> <% } %> reset->inputs-switch#reset'
5+
data-inputs-switch-left-value="<%- left_value %>"
6+
data-inputs-switch-left-icon-value="<%- left_icon %>"
7+
data-inputs-switch-right-value="<%- right_value %>"
8+
data-inputs-switch-right-icon-value="<%- right_icon %>"
9+
data-inputs-switch-initial-value="<%- initial_state.to_string() %>"
10+
<%- target %>>
11+
<div class='label toggle w-50 <%- match initial_state {State::Left => "left".to_string(), State::Right => "right".to_string()} %>' data-inputs-switch-target="toggle">
12+
<span class="material-symbols-outlined" data-inputs-switch-target="toggleIcon" >
13+
<%- match initial_state {
14+
State::Left => left_icon.to_string(),
15+
State::Right => right_icon.to_string(),
16+
} %>
17+
</span>
18+
<h5 class="h5 my-0" data-inputs-switch-target="toggleText">
19+
<%- match initial_state {
20+
State::Left => left_value.to_string(),
21+
State::Right => right_value.to_string(),
22+
} %>
23+
</h5>
24+
</div>
25+
<div class="label choice">
26+
<span class="material-symbols-outlined" ><%- left_icon %></span>
27+
<h5 class="h5 my-0">
28+
<%- left_value %>
29+
</h5>
30+
</div>
31+
<div class="label choice">
32+
<span class="material-symbols-outlined"><%- right_icon %></span>
33+
<h5 class="h5 my-0">
34+
<%- right_value %>
35+
</h5>
36+
</div>
37+
</div>

pgml-dashboard/static/css/modules.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@import "../../src/components/dropdown/dropdown.scss";
77
@import "../../src/components/inputs/range_group/range_group.scss";
88
@import "../../src/components/inputs/select/select.scss";
9+
@import "../../src/components/inputs/switch/switch.scss";
910
@import "../../src/components/inputs/text/editable_header/editable_header.scss";
1011
@import "../../src/components/left_nav_menu/left_nav_menu.scss";
1112
@import "../../src/components/modal/modal.scss";

pgml-dashboard/static/js/playground.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Controller } from '@hotwired/stimulus'
22

33
export default class extends Controller {
4-
static targets = ["test"]
4+
static targets = ["test", "switch"]
55

66
initialize() {
77
this.errorH3 = new CustomEvent("error", { detail: "message passed through event h3" })
@@ -31,4 +31,12 @@ export default class extends Controller {
3131
document.getElementById("header-2").dispatchEvent(this.clearH2)
3232
}
3333

34+
testOnToggleSwitch(e) {
35+
console.log("run from switch on toggle: ", e.detail)
36+
}
37+
38+
resetSwitch() {
39+
this.switchTarget.dispatchEvent(new Event("reset"))
40+
}
41+
3442
}

pgml-dashboard/templates/content/playground.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
use crate::components::inputs::range_group::RangeGroup;
55
use crate::components::inputs::text::editable_header::{EditableHeader, Headers};
66
use crate::components::stimulus::stimulus_target::StimulusTarget;
7+
use crate::components::stimulus::stimulus_action::StimulusAction;
8+
use crate::components::stimulus::stimulus_action::StimulusEvents;
79
use crate::components::inputs::select::Select;
10+
use crate::components::inputs::switch::Switch;
811
%>
912

1013
<div class="min-height: 100vh;" data-controller="playground">
@@ -155,6 +158,24 @@ <h3 class="h3">Inputs</h3>
155158
<button data-action="playground#clearError">Clear Error</button>
156159
</div>
157160
</div>
161+
<div class="d-flex flex-row justify-content-between">
162+
<div style="width: 30%">
163+
<%+ Switch::new()
164+
.on_toggle(
165+
StimulusAction::new()
166+
.controller("playground")
167+
.method("testOnToggleSwitch"))
168+
.target(StimulusTarget::new()
169+
.controller("playground")
170+
.name("switch"))
171+
.left("CPU", "memory")
172+
.right("GPU", "mode_fan")
173+
.start_toggled() %>
174+
</div>
175+
<div>
176+
<button data-action="click->playground#resetSwitch">Reset Switch</button>
177+
</div>
178+
</div>
158179
</div>
159180

160181
</div>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy