Skip to content

Commit

Permalink
feat: working radio buttons and styling
Browse files Browse the repository at this point in the history
  • Loading branch information
rhaskia authored and nicoburns committed Jan 6, 2025
1 parent 475b5b0 commit f67aeae
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 44 deletions.
60 changes: 52 additions & 8 deletions examples/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,57 @@ fn app() -> Element {
"Checkbox 1 (controlled)"
}
}
div {
label {
input {
type: "checkbox",
name: "check2",
value: "check2",
div {
label {
input {
type: "checkbox",
name: "check2",
value: "check2",
}
"Checkbox 2 (uncontrolled)"
}
}
div {
label {
r#for: "radio1",
id: "radio1label",
input {
type: "radio",
name: "radiobuttons",
id: "radio1",
value: "radiovalue1",
checked: true,
}
"Radio Button 1"
}
}
div {
label {
r#for: "radio2",
id: "radio2label",
input {
type: "radio",
name: "radiobuttons",
id: "radio2",
value: "radiovalue2",
}
"Radio Button 2"
}
}
div {
label {
r#for: "radio3",
id: "radio3label",
input {
type: "radio",
name: "radiobuttons",
id: "radio3",
value: "radiovalue3",
}
"Radio Button 3"
}
"Checkbox 2 (uncontrolled)"
}
}
}
div { "Checkbox 1 checked: {checkbox_checked}" }
}
}
Expand Down Expand Up @@ -76,4 +116,8 @@ input {
color: #0000cc;
}
input[type=radio]:checked {
border-color: #0000cc;
}
"#;
9 changes: 8 additions & 1 deletion packages/blitz-dom/assets/default.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ input[type="checkbox"] {
margin: 3px 3px 3px 4px;
}

input[type="radio"] {
width: 14px;
height: 14px;
border-radius: 14px;
margin: 3px 3px 3px 4px;
}

input, textarea {
border: 1px solid #999;
padding: 2px;
Expand Down Expand Up @@ -1039,4 +1046,4 @@ slot {
pointer-events: none !important;
background-color: transparent;
}
}
}
16 changes: 16 additions & 0 deletions packages/blitz-dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,22 @@ impl BaseDocument {
*is_checked = !*is_checked;
}

pub fn toggle_radio(&mut self, radio_set_name: String, target_radio_id: usize) {
for i in 0..self.nodes.len() {
let node = &mut self.nodes[i];
if let Some(node_data) = node.raw_dom_data.downcast_element_mut() {
if node_data.attr(local_name!("name")) == Some(&radio_set_name) {
let was_clicked = i == target_radio_id;
let Some(is_checked) = node_data.checkbox_input_checked_mut() else {
continue;
};
*is_checked = was_clicked;
println!("{was_clicked}");
}
}
}
}

pub fn root_node(&self) -> &Node {
&self.nodes[0]
}
Expand Down
7 changes: 7 additions & 0 deletions packages/blitz-dom/src/events/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ pub(crate) fn handle_click(doc: &mut BaseDocument, target: usize, x: f32, y: f32
{
BaseDocument::toggle_checkbox(el);
doc.set_focus_to(hit.node_id);
} else if el.name.local == local_name!("input")
&& matches!(el.attr(local_name!("type")), Some("radio"))
{
let node_id = node.id;
let radio_set = el.attr(local_name!("name")).unwrap().to_string();
self.toggle_radio(radio_set, node_id);
self.set_focus_to(hit.node_id);
}
// Clicking labels triggers click, and possibly input event, of associated input
else if el.name.local == local_name!("label") {
Expand Down
2 changes: 1 addition & 1 deletion packages/blitz-dom/src/layout/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(crate) fn collect_layout_children(
) {
create_text_editor(doc, container_node_id, false);
return;
} else if type_attr == Some("checkbox") {
} else if matches!(type_attr, Some("checkbox" | "radio")) {
create_checkbox_input(doc, container_node_id);
return;
}
Expand Down
82 changes: 48 additions & 34 deletions packages/blitz-renderer-vello/src/renderer/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use style::values::generics::image::{
};
use style::values::specified::percentage::ToPercentage;
use taffy::Layout;
use vello::kurbo::{self, BezPath, Cap, Join};
use vello::kurbo::{self, BezPath, Cap, Join, Circle};
use vello::peniko::Gradient;
use vello::{
kurbo::{Affine, Point, Rect, Shape, Stroke, Vec2},
Expand Down Expand Up @@ -1770,9 +1770,7 @@ impl ElementCx<'_> {
}

fn draw_input(&self, scene: &mut Scene) {
if self.node.local_name() == "input"
&& matches!(self.node.attr(local_name!("type")), Some("checkbox"))
{
if self.node.local_name() == "input" {
let Some(checked) = self.element.checkbox_input_checked() else {
return;
};
Expand Down Expand Up @@ -1801,37 +1799,53 @@ impl ElementCx<'_> {

let frame = self.frame.outer_rect.to_rounded_rect(scale * 2.0);

if checked {
scene.fill(Fill::NonZero, self.transform, accent_color, None, &frame);

//Tick code derived from masonry
let mut path = BezPath::new();
path.move_to((2.0, 9.0));
path.line_to((6.0, 13.0));
path.line_to((14.0, 2.0));

path.apply_affine(Affine::translate(Vec2 { x: 2.0, y: 1.0 }).then_scale(scale));

let style = Stroke {
width: 2.0 * scale,
join: Join::Round,
miter_limit: 10.0,
start_cap: Cap::Round,
end_cap: Cap::Round,
dash_pattern: Default::default(),
dash_offset: 0.0,
};
let attr_type = self.node.attr(local_name!("type"));

if attr_type == Some("checkbox") {
if checked {
scene.fill(Fill::NonZero, self.transform, accent_color, None, &frame);
//Tick code derived from masonry
let mut path = BezPath::new();
path.move_to((2.0, 9.0));
path.line_to((6.0, 13.0));
path.line_to((14.0, 2.0));

path.apply_affine(Affine::translate(Vec2 { x: 2.0, y: 1.0 }).then_scale(scale));

let style = Stroke {
width: 2.0 * scale,
join: Join::Round,
miter_limit: 10.0,
start_cap: Cap::Round,
end_cap: Cap::Round,
dash_pattern: Default::default(),
dash_offset: 0.0,
};

scene.stroke(&style, self.transform, Color::WHITE, None, &path);
} else {
scene.fill(Fill::NonZero, self.transform, Color::WHITE, None, &frame);
scene.stroke(
&Stroke::default(),
self.transform,
accent_color,
None,
&frame,
);
scene.stroke(&style, self.transform, Color::WHITE, None, &path);
} else {
scene.fill(Fill::NonZero, self.transform, Color::WHITE, None, &frame);
scene.stroke(
&Stroke::default(),
self.transform,
accent_color,
None,
&frame,
);
}
} else if attr_type == Some("radio") {
let outer_ring = Circle::new((10.0, 10.0), 12.0);
let gap = Circle::new((10.0, 10.0), 8.0);
let inner_circle = Circle::new((10.0, 10.0), 6.0);

if checked {
scene.fill(Fill::NonZero, self.transform, accent_color, None, &outer_ring);
scene.fill(Fill::NonZero, self.transform, Color::WHITE, None, &gap);
scene.fill(Fill::NonZero, self.transform, accent_color, None, &inner_circle);
} else {
scene.fill(Fill::NonZero, self.transform, Color::GRAY, None, &outer_ring);
scene.fill(Fill::NonZero, self.transform, Color::WHITE, None, &gap);
}
}
}
}
Expand Down

0 comments on commit f67aeae

Please sign in to comment.