From c3c75bcc1cb714b0792f8f601d570a05c132ca2c Mon Sep 17 00:00:00 2001 From: David Padilla Date: Wed, 4 Oct 2023 17:56:01 -0500 Subject: [PATCH] fix: rework accordion component animation (#9818) --- .../components/Accordion/AccordionItem.tsx | 32 +++++++++--- .../scss/components/accordion/_accordion.scss | 50 +++++-------------- 2 files changed, 38 insertions(+), 44 deletions(-) diff --git a/packages/react/src/components/Accordion/AccordionItem.tsx b/packages/react/src/components/Accordion/AccordionItem.tsx index e978d0cc7c82..5d279e6f34ad 100644 --- a/packages/react/src/components/Accordion/AccordionItem.tsx +++ b/packages/react/src/components/Accordion/AccordionItem.tsx @@ -87,7 +87,7 @@ interface AccordionItemProps { * The callback function to run on the `onAnimationEnd` * event for the list item. */ - handleAnimationEnd?: AnimationEventHandler; + handleAnimationEnd?: AnimationEventHandler; } interface AccordionToggleProps { @@ -117,7 +117,6 @@ function AccordionItem({ ...rest }: PropsWithChildren) { const [isOpen, setIsOpen] = useState(open); - const [animation, setAnimation] = useState(''); const accordionState = useContext(AccordionContext); const disabledIsControlled = typeof controlledDisabled === 'boolean'; @@ -130,7 +129,6 @@ function AccordionItem({ const className = cx({ [`${prefix}--accordion__item`]: true, [`${prefix}--accordion__item--active`]: isOpen, - [`${prefix}--accordion__item--${animation}`]: animation, [`${prefix}--accordion__item--disabled`]: disabled, [customClassName]: !!customClassName, }); @@ -140,8 +138,24 @@ function AccordionItem({ // When the AccordionItem heading is clicked, toggle the open state of the // panel function onClick(event) { + const toggleElement = event.target; + + let content = toggleElement.nextElementSibling; + + // when toggle element is not the button + if (toggleElement.nodeName !== 'BUTTON') { + content = toggleElement.parentElement.nextElementSibling; + } + + if (content.style.maxBlockSize) { + // accordion closes + content.style.maxBlockSize = null; + } else { + // accordion opens + content.style.maxBlockSize = content.scrollHeight + 15 + 'px'; + } + const nextValue = !isOpen; - setAnimation(isOpen ? '' : 'expanding'); setIsOpen(nextValue); if (onHeadingClick) { // TODO: normalize signature, potentially: @@ -164,7 +178,7 @@ function AccordionItem({ } return ( -
  • +
  • -
    - {children} +
    +
    + {children} +
  • ); diff --git a/packages/styles/scss/components/accordion/_accordion.scss b/packages/styles/scss/components/accordion/_accordion.scss index 66ab3a346971..3629614a3aeb 100644 --- a/packages/styles/scss/components/accordion/_accordion.scss +++ b/packages/styles/scss/components/accordion/_accordion.scss @@ -59,7 +59,6 @@ $content-padding: 0 0 0 $spacing-05 !default; display: list-item; overflow: visible; border-block-start: 1px solid $border-subtle; - transition: all $duration-fast-02 motion(standard, productive); &:last-child { border-block-end: 1px solid $border-subtle; @@ -144,11 +143,18 @@ $content-padding: 0 0 0 $spacing-05 !default; text-align: start; } + .#{$prefix}--accordion__wrapper { + // Properties for when the accordion closes + padding: 0; + max-block-size: 0; + opacity: 0; + transition: all $duration-fast-02 motion(entrance, productive); + writing-mode: horizontal-tb; + } + .#{$prefix}--accordion__content { - display: none; + overflow: hidden; padding-inline: layout.density('padding-inline'); - // Transition property for when the accordion closes - transition: padding motion(standard, productive) $duration-fast-02; // Custom breakpoints based on issue #4993 @include breakpoint-up(480px) { @@ -189,44 +195,14 @@ $content-padding: 0 0 0 $spacing-05 !default; display: block; } - @keyframes collapse-accordion { - 0% { - @include -content-visible; - } - - 100% { - @include -content-hidden; - } - } - - @keyframes expand-accordion { - 0% { - @include -content-hidden; - } - - 100% { - @include -content-visible; - } - } - - .#{$prefix}--accordion__item--collapsing .#{$prefix}--accordion__content { - animation: $duration-fast-02 motion(standard, productive) collapse-accordion; - } - - .#{$prefix}--accordion__item--expanding .#{$prefix}--accordion__content { - animation: $duration-fast-02 motion(standard, productive) expand-accordion; - } - .#{$prefix}--accordion__item--active { overflow: visible; - .#{$prefix}--accordion__content { - display: block; + .#{$prefix}--accordion__wrapper { + // Properties for when the accordion opens + opacity: 1; padding-block: $spacing-03; padding-block-end: $spacing-06; - // Transition property for when the accordion opens - transition: padding-top motion(entrance, productive) $duration-fast-02, - padding-bottom motion(entrance, productive) $duration-fast-02; } .#{$prefix}--accordion__arrow {