From e0c663c20dcab44fba6046b0783fea7803f68ea3 Mon Sep 17 00:00:00 2001
From: Joe <33972521+hnb-ku@users.noreply.github.com>
Date: Tue, 19 Apr 2022 21:13:54 +0800
Subject: [PATCH] UX: Improves select-kit body placement when vertical space is
 short (#16504)

1. When the select-kit body is rendered, it defaults to being displayed under the triggering select-kit header, unless...

    there isn't enough space between the bottom of the select-kit header and the bottom of the viewport
    &
    there's enough space on top of the select-kit header, and in that case, we render it on top.

2. We give it a bit of padding on top, so it never renders below the header on the Z-axis.

https://github.com/discourse/discourse/blob/14778ba52e6f9281f58f74dbf4090c53e971a966/app/assets/javascripts/select-kit/addon/components/select-kit.js#L877-L884

3. If there isn't enough space between the bottom of the viewport and the bottom of the select-kit header, and there isn't enough space between its top and the bottom of `d-header`, it renders at the bottom of the select-kit header.

In theory, number 3 above rarely ever happens. However, it can occur in the case of the user preferences page in combination with a large select-kit body (many categories).

The select-kit body then renders below the trigging select-kit header, but it's cut off. Users won't be able to see the entire select-kit body.

Here's an example

https://d11a6trkgmumsb.cloudfront.net/original/4X/a/7/1/a719734d9227c9c9e0ffee5718284a70f8eb1c89.mp4

This PR adds a "prevent overflow" modifier to Popper. What it does is that it handles the case above.

If there's not enough space below the select-kit header or above it, render the select-kit body below the select-kit header BUT... anchor it to the bottom of the viewport.

Here's what that looks like

https://d11a6trkgmumsb.cloudfront.net/original/4X/3/2/c/32cd1639bbbc499c89676b587f7152ac2e92ae48.mp4

After this fix, even very large select-kit bodies will always be on the screen.

Please note that this PR has no impact on either number 1 or number 2 above, and those will continue to function as they currently do.

The only downside here is that the select-kit body might cover the select-kit header if it needs to be anchored at the bottom of the viewport, and it's very large. However, between that and not being able to see all the options, I think it's a fair compromise. There's only so much space in the viewport.

This PR ignores mobile because we have a different placement strategy. We use `position: absolute`... so, users can scroll the viewport if needed.
---
 .../javascripts/select-kit/addon/components/select-kit.js   | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit.js b/app/assets/javascripts/select-kit/addon/components/select-kit.js
index 3de48b094c3..ff6308e1dca 100644
--- a/app/assets/javascripts/select-kit/addon/components/select-kit.js
+++ b/app/assets/javascripts/select-kit/addon/components/select-kit.js
@@ -885,6 +885,12 @@ export default Component.extend(
                 },
               },
             },
+            {
+              name: "preventOverflow",
+              options: {
+                altAxis: !this?.site?.mobileView,
+              },
+            },
             {
               name: "offset",
               options: {