From 5e4fa82f8ec56fa4681d1764261168630ace2e84 Mon Sep 17 00:00:00 2001 From: Daniil Suvorov Date: Mon, 22 Jan 2024 14:57:16 +0300 Subject: [PATCH] fix(Accordion): use max-height (#6429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit margin-top при выставлении процентов берет значение от ширины, а не высоты Для фикса бага используем max-height, вместо margin-top - Fixes #6414 --- .../components/Accordion/Accordion.module.css | 4 +-- .../components/Accordion/AccordionContent.tsx | 30 ++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/vkui/src/components/Accordion/Accordion.module.css b/packages/vkui/src/components/Accordion/Accordion.module.css index d76c686195..581b206f73 100644 --- a/packages/vkui/src/components/Accordion/Accordion.module.css +++ b/packages/vkui/src/components/Accordion/Accordion.module.css @@ -7,6 +7,6 @@ } .AccordionContent__in { - margin-block-start: -100%; - transition: margin-top 100ms ease-in-out; + max-block-size: 0; + transition: max-height 100ms ease-in-out; } diff --git a/packages/vkui/src/components/Accordion/AccordionContent.tsx b/packages/vkui/src/components/Accordion/AccordionContent.tsx index 4cfc709f2b..d43a339ec0 100644 --- a/packages/vkui/src/components/Accordion/AccordionContent.tsx +++ b/packages/vkui/src/components/Accordion/AccordionContent.tsx @@ -3,31 +3,25 @@ import { classNames } from '@vkontakte/vkjs'; import { useExternRef } from '../../hooks/useExternRef'; import { useGlobalEventListener } from '../../hooks/useGlobalEventListener'; import { useDOM } from '../../lib/dom'; +import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect'; import { HasRef, HasRootRef } from '../../types'; import { AccordionContext } from './AccordionContext'; import styles from './Accordion.module.css'; /** - * Функция расчета отрицательного margin, для скрытия контента. + * Функция расчета max-height, для скрытия или раскрытия контента. */ -function calcMarginTop(expanded: boolean, el: HTMLElement | null): string { - if (expanded) { - return `0px`; +function calcMaxHeight(expanded: boolean, el: HTMLElement | null): string { + if (!expanded) { + return '0px'; } - // В первый рендеринг нельзя узнать высоту элемента, поэтому прячем таким образом + // В первый рендеринг нельзя узнать высоту элемента if (el === null) { - return '-100%'; + return 'inherit'; } - return `${-el.clientHeight}px`; -} - -/** - * В первый рендеринг отключаем анимации. - */ -function calcTransition(el: HTMLElement | null) { - return el === null ? 'none' : undefined; + return `${el.scrollHeight}px`; } /** @@ -35,11 +29,12 @@ function calcTransition(el: HTMLElement | null) { */ function useResizeContent(expanded: boolean, inRef: React.MutableRefObject) { const resize = () => { - inRef.current!.style.marginTop = calcMarginTop(expanded, inRef.current); + inRef.current!.style.maxHeight = calcMaxHeight(expanded, inRef.current); }; const { window } = useDOM(); useGlobalEventListener(window, 'resize', resize); + useIsomorphicLayoutEffect(resize, []); } /** @@ -49,12 +44,11 @@ function useAccordionContent( expanded: boolean, inRef: React.MutableRefObject, ) { - const marginTop = calcMarginTop(expanded, inRef.current); - const transition = calcTransition(inRef.current); + const maxHeight = calcMaxHeight(expanded, inRef.current); useResizeContent(expanded, inRef); - return { marginTop, transition }; + return { maxHeight }; } export interface AccordionContentProps