diff options
Diffstat (limited to 'packages/frontend/src/components/MkFolder.vue')
| -rw-r--r-- | packages/frontend/src/components/MkFolder.vue | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue index 1236b843f2..e86861c874 100644 --- a/packages/frontend/src/components/MkFolder.vue +++ b/packages/frontend/src/components/MkFolder.vue @@ -31,6 +31,10 @@ SPDX-License-Identifier: AGPL-3.0-only :leaveActiveClass="prefer.s.animation ? $style.transition_toggle_leaveActive : ''" :enterFromClass="prefer.s.animation ? $style.transition_toggle_enterFrom : ''" :leaveToClass="prefer.s.animation ? $style.transition_toggle_leaveTo : ''" + @enter="enter" + @afterEnter="afterEnter" + @leave="leave" + @afterLeave="afterLeave" > <KeepAlive> <div v-show="opened"> @@ -86,6 +90,42 @@ const bgSame = ref(false); const opened = ref(props.defaultOpen); const openedAtLeastOnce = ref(props.defaultOpen); +//#region interpolate-sizeに対応していないブラウザ向け(TODO: 主要ブラウザが対応したら消す) +function enter(el: Element) { + if (CSS.supports('interpolate-size', 'allow-keywords')) return; + if (!(el instanceof HTMLElement)) return; + + const elementHeight = el.getBoundingClientRect().height; + el.style.height = '0'; + el.offsetHeight; // reflow + el.style.height = `${Math.min(elementHeight, props.maxHeight ?? Infinity)}px`; +} + +function afterEnter(el: Element) { + if (CSS.supports('interpolate-size', 'allow-keywords')) return; + if (!(el instanceof HTMLElement)) return; + + el.style.height = ''; +} + +function leave(el: Element) { + if (CSS.supports('interpolate-size', 'allow-keywords')) return; + if (!(el instanceof HTMLElement)) return; + + const elementHeight = el.getBoundingClientRect().height; + el.style.height = `${elementHeight}px`; + el.offsetHeight; // reflow + el.style.height = '0'; +} + +function afterLeave(el: Element) { + if (CSS.supports('interpolate-size', 'allow-keywords')) return; + if (!(el instanceof HTMLElement)) return; + + el.style.height = ''; +} +//#endregion + function toggle() { if (!opened.value) { openedAtLeastOnce.value = true; @@ -108,17 +148,27 @@ onMounted(() => { .transition_toggle_enterActive, .transition_toggle_leaveActive { overflow-y: hidden; // 子要素のmarginが突き出るため clip を使ってはいけない - transition: opacity 0.3s, height 0.3s !important; + transition: opacity 0.3s, height 0.3s; } + +@supports (interpolate-size: allow-keywords) { + .transition_toggle_enterFrom, + .transition_toggle_leaveTo { + height: 0; + } + + .root { + interpolate-size: allow-keywords; // heightのtransitionを動作させるために必要 + } +} + .transition_toggle_enterFrom, .transition_toggle_leaveTo { opacity: 0; - height: 0; } .root { display: block; - interpolate-size: allow-keywords; // heightのtransitionを動作させるために必要 } .header { |