From 7c49d60389414afa7fc3d73171491ac2decf866c Mon Sep 17 00:00:00 2001 From: zhmou <43105172+zhmou@users.noreply.github.com> Date: Thu, 8 Dec 2022 22:13:05 +0800 Subject: [PATCH] Add transition animation for the height of `tab-content` when tab switches (#596) --- source/js/utils.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/js/utils.js b/source/js/utils.js index b6aad90..d14737e 100644 --- a/source/js/utils.js +++ b/source/js/utils.js @@ -171,6 +171,14 @@ NexT.utils = { // Prevent selected tab to select again. if (element.classList.contains('active')) return; const nav = element.parentNode; + // Get the height of `tab-pane` which is activated before, and set it as the height of `tab-content` with extra margin / paddings. + const tabContent = nav.nextElementSibling; + tabContent.style.overflow = 'hidden'; + tabContent.style.transition = 'height 1s'; + const prevHeight = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).height.replace('px', ''), 10); + const paddingTop = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).paddingTop.replace('px', ''), 10); + const marginBottom = parseInt(window.getComputedStyle(tabContent.querySelector('.active').firstChild).marginBottom.replace('px', ''), 10); + tabContent.style.height = prevHeight + paddingTop + marginBottom + 'px'; // Add & Remove active class on `nav-tabs` & `tab-content`. [...nav.children].forEach(target => { target.classList.toggle('active', target === element); @@ -184,6 +192,25 @@ NexT.utils = { tActive.dispatchEvent(new Event('tabs:click', { bubbles: true })); + // Get the height of `tab-pane` which is activated now. + const hasScrollBar = document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight); + const currHeight = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).height.replace('px', ''), 10); + // Reset the height of `tab-content` and see the animation. + tabContent.style.height = currHeight + paddingTop + marginBottom + 'px'; + // Change the height of `tab-content` may cause scrollbar show / disappear, which may result in the change of the `tab-pane`'s height + setTimeout(() => { + if ((document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight)) !== hasScrollBar) { + tabContent.style.transition = 'height 0.3s linear'; + // After the animation, we need reset the height of `tab-content` again. + const currHeightAfterScrollBarChange = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).height.replace('px', ''), 10); + tabContent.style.height = currHeightAfterScrollBarChange + paddingTop + marginBottom + 'px'; + } + // Remove all the inline styles, and let the height be adaptive again. + setTimeout(() => { + tabContent.style.transition = ''; + tabContent.style.height = ''; + }, 250); + }, 1000); if (!CONFIG.stickytabs) return; const offset = nav.parentNode.getBoundingClientRect().top + window.scrollY + 10; window.anime({