Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "polyblade"
version = "0.4.2"
version = "0.4.3"
edition = "2024"
description = "Make shapes dance."
readme = "README.md"
Expand Down
80 changes: 61 additions & 19 deletions assets/main.css
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -24,6 +15,13 @@ body {

.menu-group {
position: relative;
z-index: 3;
}

.menu-backdrop {
position: fixed;
inset: 0;
z-index: 2;
}

.menu-group.top-right {
Expand All @@ -42,8 +40,10 @@ body {
cursor: pointer;
}

.menu-btn:hover {
background: #4b5563;
@media (hover: hover) {
.menu-btn:hover {
background: #4b5563;
}
}

.dropdown {
Expand All @@ -56,7 +56,7 @@ body {
display: none;
}

.menu-group:hover .dropdown {
.dropdown.open {
display: block;
}

Expand All @@ -66,8 +66,10 @@ body {
position: relative;
}

.item:hover {
background: #4b5563;
@media (hover: hover) {
.item:hover {
background: #4b5563;
}
}

.shortcut {
Expand All @@ -85,8 +87,10 @@ body {
display: none;
}

.item:hover .submenu {
display: block;
@media (hover: hover) {
.item:hover .submenu {
display: block;
}
}

.has-sub::after {
Expand All @@ -104,7 +108,6 @@ canvas,
position: absolute;
left: 0;
top: 0;
background_color: #ff00ff;
}

#wgpu-canvas {
Expand All @@ -118,6 +121,7 @@ canvas,
.main-div {
margin: 0;
height: 100vh;
height: 100dvh;
display: flex;
flex-direction: column;
}
Expand All @@ -136,3 +140,41 @@ 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;
background: rgb(55 65 81 / 0.65);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
}

.submenu {
position: static;
display: block;
min-width: 0;
padding-left: 16px;
background: none;
}

.has-sub::after {
content: "▾";
}

.shortcut {
display: none;
}

.item {
padding: 12px 16px;
}
}
34 changes: 24 additions & 10 deletions src/components/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn SizedPresetMenu(name: String, make: Callback<usize, PresetMessage>) -> 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<Option<&'static str>>) -> Element {
let mut options = use_signal(Vec::<FaceTypeOption>::new);

use_future(move || async move {
Expand All @@ -77,8 +77,8 @@ 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",
Expand All @@ -98,12 +98,26 @@ fn SchlegelFaceMenu() -> Element {
}
}

/// Toggles which top-level menu is open, closing it if already open.
fn toggle(mut open: Signal<Option<&'static str>>, id: &'static str) {
let next = if *open.peek() == Some(id) {
None
} else {
Some(id)
};
open.set(next);
}

#[component]
pub fn MenuBar(mut schlegel: Signal<bool>) -> 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",
Expand All @@ -123,8 +137,8 @@ pub fn MenuBar(mut schlegel: Signal<bool>) -> 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",
Expand All @@ -138,8 +152,8 @@ pub fn MenuBar(mut schlegel: Signal<bool>) -> 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 |_| {
Expand All @@ -153,7 +167,7 @@ pub fn MenuBar(mut schlegel: Signal<bool>) -> Element {
}
}
if schlegel() {
SchlegelFaceMenu {}
SchlegelFaceMenu { open }
}
}
}
Loading