From fa6ac211b61bd3d86dadc558c89f7366f6613ab3 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Tue, 7 Nov 2023 15:07:11 +0000
Subject: [PATCH] Dropdowns: Fixed bad direction logic, added dynmaic height

Changes since adding notifications would cause direction to be assessed
upon max height of 80vh, which caused large dropdowns like the audit log
dropdown to drop up and/or go offscreen.
This restores the default assessment of 500px, and adds dynamic
max-height adjustment to provide more room for large dropdowns.

For #4652
---
 resources/js/components/dropdown.js      | 6 ++++++
 resources/sass/_lists.scss               | 2 +-
 resources/views/settings/audit.blade.php | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/resources/js/components/dropdown.js b/resources/js/components/dropdown.js
index 2c5919a37..4efd428ac 100644
--- a/resources/js/components/dropdown.js
+++ b/resources/js/components/dropdown.js
@@ -34,6 +34,7 @@ export class Dropdown extends Component {
         let heightOffset = 0;
         const toggleHeight = this.toggle.getBoundingClientRect().height;
         const dropUpwards = menuOriginalRect.bottom > window.innerHeight;
+        const containerRect = this.container.getBoundingClientRect();
 
         // If enabled, Move to body to prevent being trapped within scrollable sections
         if (this.moveMenu) {
@@ -52,9 +53,13 @@ export class Dropdown extends Component {
         if (dropUpwards) {
             this.menu.style.top = 'initial';
             this.menu.style.bottom = `${heightOffset}px`;
+            const maxHeight = (window.innerHeight - 40) - (window.innerHeight - containerRect.bottom);
+            this.menu.style.maxHeight = `${Math.floor(maxHeight)}px`;
         } else {
             this.menu.style.top = `${heightOffset}px`;
             this.menu.style.bottom = 'initial';
+            const maxHeight = (window.innerHeight - 40) - containerRect.top;
+            this.menu.style.maxHeight = `${Math.floor(maxHeight)}px`;
         }
 
         // Set listener to hide on mouse leave or window click
@@ -91,6 +96,7 @@ export class Dropdown extends Component {
         this.toggle.setAttribute('aria-expanded', 'false');
         this.menu.style.top = '';
         this.menu.style.bottom = '';
+        this.menu.style.maxHeight = '';
 
         if (this.moveMenu) {
             this.menu.style.position = '';
diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss
index 299bfbc33..865b503c8 100644
--- a/resources/sass/_lists.scss
+++ b/resources/sass/_lists.scss
@@ -672,7 +672,7 @@ ul.pagination {
   @include lightDark(color, #555, #eee);
   fill: currentColor;
   text-align: start !important;
-  max-height: 80vh;
+  max-height: 500px;
   overflow-y: auto;
   &.anchor-left {
     inset-inline-end: auto;
diff --git a/resources/views/settings/audit.blade.php b/resources/views/settings/audit.blade.php
index 9f0572c1a..89d743fdc 100644
--- a/resources/views/settings/audit.blade.php
+++ b/resources/views/settings/audit.blade.php
@@ -16,7 +16,7 @@
                     <input type="hidden" name="{{ $key }}" value="{{ $val }}">
                 @endforeach
 
-                <div component="dropdown" class="list-sort-type dropdown-container">
+                <div component="dropdown" class="list-sort-type dropdown-container relative">
                     <label for="">{{ trans('settings.audit_event_filter') }}</label>
                     <button refs="dropdown@toggle"
                             type="button"