diff --git a/packages/eui/changelogs/upcoming/8327.md b/packages/eui/changelogs/upcoming/8327.md new file mode 100644 index 00000000000..72ceb401d2f --- /dev/null +++ b/packages/eui/changelogs/upcoming/8327.md @@ -0,0 +1,2 @@ +- Updated `EuiAccordion` to prevent content from being transitioned on initial render when `initialIsOpen=true` + diff --git a/packages/eui/src/components/accordion/__snapshots__/accordion.test.tsx.snap b/packages/eui/src/components/accordion/__snapshots__/accordion.test.tsx.snap index 451b489a4a3..e78a5da860f 100644 --- a/packages/eui/src/components/accordion/__snapshots__/accordion.test.tsx.snap +++ b/packages/eui/src/components/accordion/__snapshots__/accordion.test.tsx.snap @@ -830,7 +830,7 @@ exports[`EuiAccordion props initialIsOpen is rendered 1`] = `
{children} diff --git a/packages/eui/src/components/accordion/accordion_children/accordion_children.styles.ts b/packages/eui/src/components/accordion/accordion_children/accordion_children.styles.ts index aed75c8447b..e575df81d1c 100644 --- a/packages/eui/src/components/accordion/accordion_children/accordion_children.styles.ts +++ b/packages/eui/src/components/accordion/accordion_children/accordion_children.styles.ts @@ -59,6 +59,15 @@ export const euiAccordionChildWrapperStyles = ( users on Chrome & FF */ ${euiFocusRing(euiThemeContext)} `, + // choosing to override transition instead of applying it conditionally + // to keep a more logical style appliance: + // default case = has transition as part of default styles (all cases expect initial isOpen=true when initialIsOpen=true) + // special case: no transition for initial isOpen=true when initialIsOpen=true + noTransition: css` + ${euiCanAnimate} { + transition: none; + } + `, isClosed: css` ${logicalCSS('height', 0)} opacity: 0; diff --git a/packages/eui/src/components/accordion/accordion_children/accordion_children.tsx b/packages/eui/src/components/accordion/accordion_children/accordion_children.tsx index d119d9b725b..86ae5dd2c09 100644 --- a/packages/eui/src/components/accordion/accordion_children/accordion_children.tsx +++ b/packages/eui/src/components/accordion/accordion_children/accordion_children.tsx @@ -10,6 +10,7 @@ import React, { FunctionComponent, HTMLAttributes, useCallback, + useEffect, useMemo, useState, } from 'react'; @@ -28,7 +29,12 @@ import { type _EuiAccordionChildrenProps = HTMLAttributes & Pick< EuiAccordionProps, - 'role' | 'children' | 'paddingSize' | 'isLoading' | 'isLoadingMessage' + | 'role' + | 'children' + | 'paddingSize' + | 'initialIsOpen' + | 'isLoading' + | 'isLoadingMessage' > & { isOpen: boolean; }; @@ -41,6 +47,7 @@ export const EuiAccordionChildren: FunctionComponent< isLoading, isLoadingMessage, isOpen, + initialIsOpen, ...rest }) => { /** @@ -61,12 +68,22 @@ export const EuiAccordionChildren: FunctionComponent< /** * Wrapper */ + const [hasTransition, setHasTransition] = useState(false); const wrapperStyles = euiAccordionChildWrapperStyles(euiTheme); const wrapperCssStyles = [ wrapperStyles.euiAccordion__childWrapper, isOpen ? wrapperStyles.isOpen : wrapperStyles.isClosed, + initialIsOpen && !hasTransition && isOpen && wrapperStyles.noTransition, ]; + /* Controls enabling opening/closing transitions on first interaction + when initialIsOpen=true; this only runs once */ + useEffect(() => { + if (initialIsOpen && !isOpen && !hasTransition) { + setHasTransition(true); + } + }, [isOpen, initialIsOpen, hasTransition]); + /** * Update the accordion wrapper height whenever the accordion opens, and also * whenever the child content updates (which will change the height)