fix(frontend): replace theme dropdown with signal-controlled menu for better mobile touch support
This commit is contained in:
@@ -3,6 +3,8 @@ use wasm_bindgen::JsCast;
|
|||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn StatusBar() -> impl IntoView {
|
pub fn StatusBar() -> impl IntoView {
|
||||||
|
let (theme_open, set_theme_open) = create_signal(false);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="h-8 min-h-8 bg-base-200 border-t border-base-300 flex items-center px-4 text-xs gap-4 text-base-content/70">
|
<div class="h-8 min-h-8 bg-base-200 border-t border-base-300 flex items-center px-4 text-xs gap-4 text-base-content/70">
|
||||||
<div class="flex items-center gap-2 cursor-pointer hover:text-primary">
|
<div class="flex items-center gap-2 cursor-pointer hover:text-primary">
|
||||||
@@ -24,13 +26,26 @@ pub fn StatusBar() -> impl IntoView {
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown dropdown-top dropdown-end">
|
<div class="relative">
|
||||||
<div tabindex="0" role="button" class="btn btn-ghost btn-xs btn-square" title="Change Theme">
|
<button
|
||||||
|
class="btn btn-ghost btn-xs btn-square"
|
||||||
|
title="Change Theme"
|
||||||
|
on:click=move |_| set_theme_open.update(|v| *v = !*v)
|
||||||
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072c0 .657.66 1.175 1.312 1.133 3.421-.22 6.187 2.546 6.187 5.965 0 1.595-.572 3.064-1.524 4.195" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072c0 .657.66 1.175 1.312 1.133 3.421-.22 6.187 2.546 6.187 5.965 0 1.595-.572 3.064-1.524 4.195" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</button>
|
||||||
<ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-200 rounded-box w-52 mb-2 border border-base-300">
|
|
||||||
|
<Show when=move || theme_open.get() fallback=|| ()>
|
||||||
|
// Backdrop
|
||||||
|
<div
|
||||||
|
class="fixed inset-0 z-[49] cursor-default"
|
||||||
|
on:click=move |_| set_theme_open.set(false)
|
||||||
|
></div>
|
||||||
|
|
||||||
|
// Dropdown Content
|
||||||
|
<ul class="absolute bottom-full right-0 mb-2 z-[50] menu p-2 shadow bg-base-200 rounded-box w-52 border border-base-300">
|
||||||
{
|
{
|
||||||
let themes = vec!["light", "dark", "cupcake", "dracula", "cyberpunk", "emerald", "luxury", "nord"];
|
let themes = vec!["light", "dark", "cupcake", "dracula", "cyberpunk", "emerald", "luxury", "nord"];
|
||||||
themes.into_iter().map(|theme| {
|
themes.into_iter().map(|theme| {
|
||||||
@@ -42,11 +57,8 @@ pub fn StatusBar() -> impl IntoView {
|
|||||||
let doc = web_sys::window().unwrap().document().unwrap();
|
let doc = web_sys::window().unwrap().document().unwrap();
|
||||||
let _ = doc.document_element().unwrap().set_attribute("data-theme", theme);
|
let _ = doc.document_element().unwrap().set_attribute("data-theme", theme);
|
||||||
|
|
||||||
// Update theme-color meta tag to match new theme
|
|
||||||
if let Some(meta) = doc.query_selector("meta[name='theme-color']").unwrap() {
|
if let Some(meta) = doc.query_selector("meta[name='theme-color']").unwrap() {
|
||||||
let window = web_sys::window().unwrap();
|
let window = web_sys::window().unwrap();
|
||||||
// Force a style recalc by reading a property or just wait for next tick?
|
|
||||||
// Usually get_computed_style forces it.
|
|
||||||
if let Ok(Some(style)) = window.get_computed_style(&doc.body().unwrap()) {
|
if let Ok(Some(style)) = window.get_computed_style(&doc.body().unwrap()) {
|
||||||
if let Ok(color) = style.get_property_value("background-color") {
|
if let Ok(color) = style.get_property_value("background-color") {
|
||||||
let _ = meta.set_attribute("content", &color);
|
let _ = meta.set_attribute("content", &color);
|
||||||
@@ -54,12 +66,7 @@ pub fn StatusBar() -> impl IntoView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the dropdown by blurring the active element
|
set_theme_open.set(false);
|
||||||
if let Some(active) = doc.active_element() {
|
|
||||||
if let Ok(html_element) = active.dyn_into::<web_sys::HtmlElement>() {
|
|
||||||
let _ = html_element.blur();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{theme}
|
{theme}
|
||||||
@@ -68,7 +75,8 @@ pub fn StatusBar() -> impl IntoView {
|
|||||||
}
|
}
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-ghost btn-xs btn-square" title="Settings">
|
<button class="btn btn-ghost btn-xs btn-square" title="Settings">
|
||||||
|
|||||||
Reference in New Issue
Block a user