]> BookStack Code Mirror - bookstack/commitdiff
Added animation transition for breadcrumb dropdown load
authorDan Brown <redacted>
Sat, 14 May 2022 12:32:25 +0000 (13:32 +0100)
committerDan Brown <redacted>
Sat, 14 May 2022 12:32:25 +0000 (13:32 +0100)
Animates the height on breadcrumb dropdown menus to transition to the
loaded animations quicker. Includes a new animation helper for doing
similar tasks in future.

resources/js/components/dropdown-search.js
resources/js/services/animations.js

index e2d55f9694ded7b9d938050f563fad4791a93cb4..81fa940c24ca7cf4a38ba66fe7b55e300d746100 100644 (file)
@@ -1,4 +1,5 @@
 import {debounce} from "../services/util";
+import {transitionHeight} from "../services/animations";
 
 class DropdownSearch {
 
@@ -51,7 +52,9 @@ class DropdownSearch {
 
         try {
             const resp = await window.$http.get(this.getAjaxUrl(searchTerm));
+            const animate = transitionHeight(this.listContainerElem, 80);
             this.listContainerElem.innerHTML = resp.data;
+            animate();
         } catch (err) {
             console.error(err);
         }
index 278a765d5802e2af4feefd1fb1cb26aeaee9b805..9ccd5f442499e4e2de247db9a95c43de4a9a6cdb 100644 (file)
@@ -82,6 +82,38 @@ export function slideDown(element, animTime = 400) {
     animateStyles(element, animStyles, animTime);
 }
 
+/**
+ * Transition the height of the given element between two states.
+ * Call with first state, and you'll receive a function in return.
+ * Call the returned function in the second state to animate between those two states.
+ * If animating to/from 0-height use the slide-up/slide down as easier alternatives.
+ * @param {Element} element - Element to animate
+ * @param {Number} animTime - Animation time in ms
+ * @returns {function} - Function to run in second state to trigger animation.
+ */
+export function transitionHeight(element, animTime = 400) {
+    const startHeight = element.getBoundingClientRect().height;
+    const initialComputedStyles = getComputedStyle(element);
+    const startPaddingTop = initialComputedStyles.getPropertyValue('padding-top');
+    const startPaddingBottom = initialComputedStyles.getPropertyValue('padding-bottom');
+
+    return () => {
+        cleanupExistingElementAnimation(element);
+        const targetHeight = element.getBoundingClientRect().height;
+        const computedStyles = getComputedStyle(element);
+        const targetPaddingTop = computedStyles.getPropertyValue('padding-top');
+        const targetPaddingBottom = computedStyles.getPropertyValue('padding-bottom');
+        const animStyles = {
+            height: [`${startHeight}px`, `${targetHeight}px`],
+            overflow: ['hidden', 'hidden'],
+            paddingTop: [startPaddingTop, targetPaddingTop],
+            paddingBottom: [startPaddingBottom, targetPaddingBottom],
+        };
+
+        animateStyles(element, animStyles, animTime);
+    };
+}
+
 /**
  * Animate the css styles of an element using FLIP animation techniques.
  * Styles must be an object where the keys are style properties, camelcase, and the values