all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Shannon Sterz <s.sterz@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [PATCH yew-widget-toolkit 2/3] dropdown/align: make the picker render above or below a dropdown
Date: Mon,  4 May 2026 16:39:10 +0200	[thread overview]
Message-ID: <20260504143911.288747-3-s.sterz@proxmox.com> (raw)
In-Reply-To: <20260504143911.288747-1-s.sterz@proxmox.com>

and detect dropup mode. this allows better ux restricting the height
of the picker to the maximum of the space below or above a `Dropdown`.
by setting the `pwt-dropup` class the picker can also set the proper
flex direction for its content. for example, rendering filter input
fields closer to the `Dropdown` itself, further improving usability.

this implements the fix outlined in [1].

[1]:
https://git.proxmox.com/?p=proxmox-datacenter-manager.git;a=commit;f=ui/css/desktop-yew-style.scss;h=dafa21a3

Signed-off-by: Shannon Sterz <s.sterz@proxmox.com>
---
 src/dom/align.rs       |  6 +++-
 src/widget/dropdown.rs | 62 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/src/dom/align.rs b/src/dom/align.rs
index 603a5b8d..a20cc6ed 100644
--- a/src/dom/align.rs
+++ b/src/dom/align.rs
@@ -456,7 +456,11 @@ where
         style.remove_property("overflow")?;
     }
     let padding = 2.0 * options.viewport_padding;
-    style.set_property("max-height", &format!("calc(100dvh - {padding}px)"))?;
+
+    if style.get_property_value("max-height")? == "" {
+        style.set_property("max-height", &format!("calc(100dvh - {padding}px)"))?;
+    }
+
     style.set_property("max-width", &format!("calc(100dvw - {padding}px)"))?;
 
     if options.align_width {
diff --git a/src/widget/dropdown.rs b/src/widget/dropdown.rs
index 1af09633..64db380a 100644
--- a/src/widget/dropdown.rs
+++ b/src/widget/dropdown.rs
@@ -1,7 +1,11 @@
+use std::cmp;
+
 use html::Scope;
 use wasm_bindgen::JsCast;
 use web_sys::HtmlInputElement;
 
+use crate::dom::IntoHtmlElement;
+
 use yew::html::{IntoEventCallback, IntoPropValue};
 use yew::prelude::*;
 
@@ -155,15 +159,18 @@ impl PwtDropdown {
     }
 
     fn update_picker_placer(&mut self, _props: &Dropdown) {
-        let align_options = _props.align_options.clone().unwrap_or(
-            AlignOptions::new(
-                Point::BottomStart,
-                Point::TopStart,
-                GrowDirection::TopBottom,
-            )
-            .viewport_padding(5.0)
-            .align_width(true),
-        );
+        let align_options =
+            AlignOptions::new(Point::BottomStart, Point::TopStart, GrowDirection::None)
+                .viewport_padding(5.0)
+                .align_width(true)
+                .with_fallback_placement(Point::TopStart, Point::BottomStart, GrowDirection::None)
+                .with_fallback_placement(
+                    Point::BottomStart,
+                    Point::TopStart,
+                    GrowDirection::TopBottom,
+                );
+
+        let align_options = _props.align_options.clone().unwrap_or(align_options);
         self.picker_placer = match AutoFloatingPlacement::new(
             self.dropdown_ref.clone(),
             self.picker_ref.clone(),
@@ -497,7 +504,6 @@ impl Component for PwtDropdown {
     fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
         if first_render {
             let props = ctx.props();
-
             self.update_picker_placer(props);
 
             if props.input_props.autofocus {
@@ -525,6 +531,42 @@ impl Component for PwtDropdown {
             }
         }
 
+        // intentionally fail silently here; if any of these values aren't available here, falling
+        // back to the default logic is fine, this should just provide improved ui/ux.
+        let dropdown_rect = self
+            .dropdown_ref
+            .clone()
+            .into_html_element()
+            .map(|e| e.get_bounding_client_rect());
+
+        let window_height = web_sys::window()
+            .and_then(|w| w.inner_height().ok())
+            .and_then(|h| h.as_f64().map(|h| h as i64));
+
+        if let Some(dropdown_rect) = dropdown_rect
+            && let Some(window_height) = window_height
+        {
+            let top = dropdown_rect.y() as i64;
+            let bottom = window_height - (top + (dropdown_rect.height() as i64));
+            let height = cmp::max(top, bottom) - 5;
+
+            if let Some(picker) = self.picker_ref.clone().into_html_element() {
+                let _ = picker
+                    .style()
+                    .set_property("max-height", &format!("{height}px"))
+                    .ok();
+
+                let height = picker.get_bounding_client_rect().height() as i64;
+                let class_list = picker.class_list();
+
+                if height > bottom && height <= top {
+                    let _ = class_list.add_1("pwt-dropup");
+                } else {
+                    let _ = class_list.remove_1("pwt-dropup");
+                }
+            }
+        }
+
         // update picker placement after we opened/closed to cope with a bug that only seems to
         // affect webkit based browsers like Safari
         if let Some(placer) = &self.picker_placer {
-- 
2.47.3





  parent reply	other threads:[~2026-05-04 14:39 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-04 14:39 [RFC yew-comp/yew-widget-toolkit/yew-widget-toolkit-assets 0/3] minor ui/ux tweaks for pwt and yew-comp Shannon Sterz
2026-05-04 14:39 ` [PATCH yew-widget-toolkit-assets 1/3] dropdown: add class for dropup mode Shannon Sterz
2026-05-04 14:39 ` Shannon Sterz [this message]
2026-05-04 14:39 ` [PATCH yew-comp 3/3] task_viewer/syslog: make padding margin to improve ux Shannon Sterz
2026-05-06  7:53 ` [RFC yew-comp/yew-widget-toolkit/yew-widget-toolkit-assets 0/3] minor ui/ux tweaks for pwt and yew-comp Dominik Csapak
2026-05-06  9:43   ` Shannon Sterz
2026-05-06  9:55     ` Dominik Csapak
2026-05-06  9:56 ` Superseded: " Shannon Sterz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260504143911.288747-3-s.sterz@proxmox.com \
    --to=s.sterz@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal