fix(ui): use global touchstart listener for ios dropdowns

This commit is contained in:
spinline
2026-02-04 18:37:36 +03:00
parent 79f18a4c39
commit 95b7535ff2

View File

@@ -85,6 +85,17 @@ pub fn StatusBar() -> impl IntoView {
set_up_menu_open.set(false);
};
// Register global click/touch listener to close menus when clicking outside
let close_menus = move |_| {
if down_menu_open.get_untracked() { set_down_menu_open.set(false); }
if up_menu_open.get_untracked() { set_up_menu_open.set(false); }
if theme_open.get_untracked() { set_theme_open.set(false); }
};
// Use window_event_listener from leptos for both click and touchstart (for iOS)
let _ = window_event_listener(ev::click, close_menus);
let _ = window_event_listener(ev::touchstart, close_menus);
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">
@@ -96,7 +107,7 @@ pub fn StatusBar() -> impl IntoView {
<div
tabindex="0"
role="button"
class="flex items-center gap-2 cursor-pointer hover:text-primary transition-colors select-none relative z-[10001]"
class="flex items-center gap-2 cursor-pointer hover:text-primary transition-colors select-none"
title="Global Download Speed - Click to Set Limit"
on:click=move |e| {
e.stop_propagation();
@@ -104,6 +115,11 @@ pub fn StatusBar() -> impl IntoView {
set_up_menu_open.set(false);
set_theme_open.set(false);
}
on:touchstart=move |e| {
e.stop_propagation();
// touchstart will trigger click usually, but we stop propagation here so window listener doesn't fire.
// We rely on click for the toggle logic to avoid double toggle.
}
>
<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="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" />
@@ -116,19 +132,11 @@ pub fn StatusBar() -> impl IntoView {
</Show>
</div>
<Show when=move || down_menu_open.get() fallback=|| ()>
<div
class="fixed inset-0 z-[9999] cursor-default"
role="button"
tabindex="-1"
on:click=move |_| set_down_menu_open.set(false)
></div>
</Show>
<ul
tabindex="0"
class="dropdown-content z-[10000] menu p-2 shadow bg-base-200 rounded-box w-40 mb-2 border border-base-300"
class="dropdown-content z-[100] menu p-2 shadow bg-base-200 rounded-box w-40 mb-2 border border-base-300"
on:click=move |e| e.stop_propagation()
on:touchstart=move |e| e.stop_propagation()
>
{
limits.clone().into_iter().map(|(val, label)| {
@@ -165,7 +173,7 @@ pub fn StatusBar() -> impl IntoView {
<div
tabindex="0"
role="button"
class="flex items-center gap-2 cursor-pointer hover:text-primary transition-colors select-none relative z-[10001]"
class="flex items-center gap-2 cursor-pointer hover:text-primary transition-colors select-none"
title="Global Upload Speed - Click to Set Limit"
on:click=move |e| {
e.stop_propagation();
@@ -173,6 +181,9 @@ pub fn StatusBar() -> impl IntoView {
set_down_menu_open.set(false);
set_theme_open.set(false);
}
on:touchstart=move |e| {
e.stop_propagation();
}
>
<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="M15 11.25l-3-3m0 0l-3 3m3-3v7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
@@ -185,19 +196,11 @@ pub fn StatusBar() -> impl IntoView {
</Show>
</div>
<Show when=move || up_menu_open.get() fallback=|| ()>
<div
class="fixed inset-0 z-[9999] cursor-default"
role="button"
tabindex="-1"
on:click=move |_| set_up_menu_open.set(false)
></div>
</Show>
<ul
tabindex="0"
class="dropdown-content z-[10000] menu p-2 shadow bg-base-200 rounded-box w-40 mb-2 border border-base-300"
class="dropdown-content z-[100] menu p-2 shadow bg-base-200 rounded-box w-40 mb-2 border border-base-300"
on:click=move |e| e.stop_propagation()
on:touchstart=move |e| e.stop_propagation()
>
{
limits.clone().into_iter().map(|(val, label)| {
@@ -238,7 +241,7 @@ pub fn StatusBar() -> impl IntoView {
<div
tabindex="0"
role="button"
class="btn btn-ghost btn-xs btn-square relative z-[10001]"
class="btn btn-ghost btn-xs btn-square"
title="Change Theme"
on:click=move |e| {
e.stop_propagation();
@@ -246,25 +249,20 @@ pub fn StatusBar() -> impl IntoView {
set_down_menu_open.set(false);
set_up_menu_open.set(false);
}
on:touchstart=move |e| {
e.stop_propagation();
}
>
<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" />
</svg>
</div>
<Show when=move || theme_open.get() fallback=|| ()>
<div
class="fixed inset-0 z-[9999] cursor-default"
role="button"
tabindex="-1"
on:click=move |_| set_theme_open.set(false)
></div>
</Show>
<ul
tabindex="0"
class="dropdown-content z-[10000] menu p-2 shadow bg-base-200 rounded-box w-52 mb-2 border border-base-300 max-h-96 overflow-y-auto block"
class="dropdown-content z-[100] menu p-2 shadow bg-base-200 rounded-box w-52 mb-2 border border-base-300 max-h-96 overflow-y-auto block"
on:click=move |e| e.stop_propagation()
on:touchstart=move |e| e.stop_propagation()
>
{
let themes = vec![