From 133be4bcba47eb6ccb013070e3d3da51bdc91660 Mon Sep 17 00:00:00 2001 From: Vera Gonzalez Date: Tue, 22 Sep 2026 15:21:50 -0400 Subject: [PATCH 1/4] first attempt --- assets/main.css | 62 +++++++++++++++++++++++++++++++++++++----- src/components/menu.rs | 54 +++++++++++++++++++++++++++++------- 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/assets/main.css b/assets/main.css index 12d9529..ae72267 100644 --- a/assets/main.css +++ b/assets/main.css @@ -24,6 +24,13 @@ body { .menu-group { position: relative; + z-index: 3; +} + +.menu-backdrop { + position: fixed; + inset: 0; + z-index: 2; } .menu-group.top-right { @@ -42,8 +49,10 @@ body { cursor: pointer; } -.menu-btn:hover { - background: #4b5563; +@media (hover: hover) { + .menu-btn:hover { + background: #4b5563; + } } .dropdown { @@ -56,7 +65,7 @@ body { display: none; } -.menu-group:hover .dropdown { +.dropdown.open { display: block; } @@ -66,8 +75,10 @@ body { position: relative; } -.item:hover { - background: #4b5563; +@media (hover: hover) { + .item:hover { + background: #4b5563; + } } .shortcut { @@ -85,8 +96,10 @@ body { display: none; } -.item:hover .submenu { - display: block; +@media (hover: hover) { + .item:hover .submenu { + display: block; + } } .has-sub::after { @@ -118,6 +131,7 @@ canvas, .main-div { margin: 0; height: 100vh; + height: 100dvh; display: flex; flex-direction: column; } @@ -136,3 +150,37 @@ canvas, flex: 1; touch-action: none; } + +/* On phones the open dropdown becomes a bottom sheet and submenus flatten inline. */ +@media (max-width: 640px) { + .menu-group .dropdown, + .menu-group.top-right .dropdown { + position: fixed; + left: 0; + right: 0; + top: auto; + bottom: 0; + max-height: 45vh; + overflow-y: auto; + min-width: 0; + } + + .submenu { + position: static; + display: block; + min-width: 0; + padding-left: 16px; + } + + .has-sub::after { + content: "▾"; + } + + .shortcut { + display: none; + } + + .item { + padding: 12px 16px; + } +} diff --git a/src/components/menu.rs b/src/components/menu.rs index af14d15..a5caf29 100644 --- a/src/components/menu.rs +++ b/src/components/menu.rs @@ -56,7 +56,7 @@ fn SizedPresetMenu(name: String, make: Callback) -> Elemen /// Polls the backend-published Schlegel face-type options, rendering one button per type. /// Only rendered when Schlegel mode is on. #[component] -fn SchlegelFaceMenu() -> Element { +fn SchlegelFaceMenu(open: Signal>) -> Element { let mut options = use_signal(Vec::::new); use_future(move || async move { @@ -77,8 +77,13 @@ fn SchlegelFaceMenu() -> Element { rsx! { div { class: "menu-group top-right", - div { class: "menu-btn", "Schlegel Face" } - div { class: "dropdown", + div { + class: "menu-btn", + onclick: move |_| toggle(open, "schlegel"), + "Schlegel Face" + } + div { + class: if open() == Some("schlegel") { "dropdown open" } else { "dropdown" }, for option in options() { div { class: "item", @@ -98,12 +103,31 @@ fn SchlegelFaceMenu() -> Element { } } +/// Toggles which top-level menu is open, closing it if already open. +fn toggle(mut open: Signal>, id: &'static str) { + let next = if *open.peek() == Some(id) { + None + } else { + Some(id) + }; + open.set(next); +} + #[component] pub fn MenuBar(mut schlegel: Signal) -> Element { + let mut open = use_signal(|| None::<&'static str>); rsx! { + if open().is_some() { + div { class: "menu-backdrop", onclick: move |_| open.set(None) } + } div { class: "menu-group", - div { class: "menu-btn", "Preset" } - div { class: "dropdown", + div { + class: "menu-btn", + onclick: move |_| toggle(open, "preset"), + "Preset" + } + div { + class: if open() == Some("preset") { "dropdown open" } else { "dropdown" }, div { class: "item has-sub", "Platonic solids" div { class: "submenu", @@ -123,8 +147,13 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { } } div { class: "menu-group", - div { class: "menu-btn", "Conway" } - div { class: "dropdown", + div { + class: "menu-btn", + onclick: move |_| toggle(open, "conway"), + "Conway" + } + div { + class: if open() == Some("conway") { "dropdown open" } else { "dropdown" }, for op in ConwayMessage::iter() { div { class: "item", @@ -138,8 +167,13 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { } } div { class: "menu-group", - div { class: "menu-btn", "Render" } - div { class: "dropdown", + div { + class: "menu-btn", + onclick: move |_| toggle(open, "render"), + "Render" + } + div { + class: if open() == Some("render") { "dropdown open" } else { "dropdown" }, div { class: "item", onclick: move |_| { @@ -153,7 +187,7 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { } } if schlegel() { - SchlegelFaceMenu {} + SchlegelFaceMenu { open } } } } From 8ff0f84ccc27fcb7fa4a1959f840009c46dd1f87 Mon Sep 17 00:00:00 2001 From: Vera Gonzalez Date: Tue, 22 Sep 2026 15:35:30 -0400 Subject: [PATCH 2/4] testing tranparency --- assets/main.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/main.css b/assets/main.css index ae72267..7895b35 100644 --- a/assets/main.css +++ b/assets/main.css @@ -163,6 +163,9 @@ canvas, max-height: 45vh; overflow-y: auto; min-width: 0; + background: rgb(55 65 81 / 0.65); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); } .submenu { @@ -170,6 +173,7 @@ canvas, display: block; min-width: 0; padding-left: 16px; + background: none; } .has-sub::after { From f49942fa8ba30fa1232eb6b9a46d79220d51e8af Mon Sep 17 00:00:00 2001 From: Vera Gonzalez Date: Tue, 22 Sep 2026 15:43:46 -0400 Subject: [PATCH 3/4] cleanups --- assets/main.css | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/assets/main.css b/assets/main.css index 7895b35..11c3b2d 100644 --- a/assets/main.css +++ b/assets/main.css @@ -1,17 +1,8 @@ -body { - background-color: #0f1116; - color: #ffffff; - font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; - margin: 20px; -} - -#header { - max-width: 1200px; -} - body { background: #0f172a; color: #d1d5db; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + margin: 0; } .menu-bar { @@ -117,7 +108,6 @@ canvas, position: absolute; left: 0; top: 0; - background_color: #ff00ff; } #wgpu-canvas { From d261a51517e9384342b37c83afaebbbf7a34b85b Mon Sep 17 00:00:00 2001 From: Vera Gonzalez Date: Tue, 29 Sep 2026 10:45:48 -0400 Subject: [PATCH 4/4] fix CI --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/components/menu.rs | 36 ++++++++---------------------------- 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efbd764..70e9652 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5029,7 +5029,7 @@ checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" [[package]] name = "polyblade" -version = "0.4.2" +version = "0.4.3" dependencies = [ "bytemuck", "cfg-if", @@ -5601,9 +5601,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ "once_cell", "ring", @@ -6476,7 +6476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", diff --git a/Cargo.toml b/Cargo.toml index c27e388..41d3216 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polyblade" -version = "0.4.2" +version = "0.4.3" edition = "2024" description = "Make shapes dance." readme = "README.md" diff --git a/src/components/menu.rs b/src/components/menu.rs index a5caf29..4057ef1 100644 --- a/src/components/menu.rs +++ b/src/components/menu.rs @@ -77,13 +77,8 @@ fn SchlegelFaceMenu(open: Signal>) -> Element { rsx! { div { class: "menu-group top-right", - div { - class: "menu-btn", - onclick: move |_| toggle(open, "schlegel"), - "Schlegel Face" - } - div { - class: if open() == Some("schlegel") { "dropdown open" } else { "dropdown" }, + div { class: "menu-btn", onclick: move |_| toggle(open, "schlegel"), "Schlegel Face" } + div { class: if open() == Some("schlegel") { "dropdown open" } else { "dropdown" }, for option in options() { div { class: "item", @@ -121,13 +116,8 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { div { class: "menu-backdrop", onclick: move |_| open.set(None) } } div { class: "menu-group", - div { - class: "menu-btn", - onclick: move |_| toggle(open, "preset"), - "Preset" - } - div { - class: if open() == Some("preset") { "dropdown open" } else { "dropdown" }, + div { class: "menu-btn", onclick: move |_| toggle(open, "preset"), "Preset" } + div { class: if open() == Some("preset") { "dropdown open" } else { "dropdown" }, div { class: "item has-sub", "Platonic solids" div { class: "submenu", @@ -147,13 +137,8 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { } } div { class: "menu-group", - div { - class: "menu-btn", - onclick: move |_| toggle(open, "conway"), - "Conway" - } - div { - class: if open() == Some("conway") { "dropdown open" } else { "dropdown" }, + div { class: "menu-btn", onclick: move |_| toggle(open, "conway"), "Conway" } + div { class: if open() == Some("conway") { "dropdown open" } else { "dropdown" }, for op in ConwayMessage::iter() { div { class: "item", @@ -167,13 +152,8 @@ pub fn MenuBar(mut schlegel: Signal) -> Element { } } div { class: "menu-group", - div { - class: "menu-btn", - onclick: move |_| toggle(open, "render"), - "Render" - } - div { - class: if open() == Some("render") { "dropdown open" } else { "dropdown" }, + div { class: "menu-btn", onclick: move |_| toggle(open, "render"), "Render" } + div { class: if open() == Some("render") { "dropdown open" } else { "dropdown" }, div { class: "item", onclick: move |_| {