Skip to content

Commit

Permalink
fix(@clayui/shared): removes the onTransitionEnd listener from elemen…
Browse files Browse the repository at this point in the history
…ts by setTimeout

Trusting `onTransitionEnd` has been showing a little uncertainty as to whether the transition happened, so instead of adding a fallback to this we will add the implementation only in setTimeout as the trigger of the final transition, calculating the duration time of the style properties.
  • Loading branch information
matuzalemsteles committed Sep 22, 2020
1 parent bb1a858 commit 4cf740a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 76 deletions.
13 changes: 6 additions & 7 deletions packages/clay-nav/src/Vertical.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ function Item({
const menuRef = React.useRef(null);
const [expanded, setExpaned] = React.useState(!initialExpanded);

const [
transitioning,
handleTransitionEnd,
handleClickToggler,
] = useTransitionHeight(expanded, setExpaned, menuRef);
const {animate, transitioning} = useTransitionHeight(
expanded,
setExpaned,
menuRef
);

const showIconCollapsed = !(
(!expanded && transitioning) ||
Expand All @@ -128,7 +128,7 @@ function Item({
collapsed={showIconCollapsed}
href={href}
onClick={(e) => {
handleClickToggler(e);
animate(e);

if (onClick) {
onClick();
Expand All @@ -148,7 +148,6 @@ function Item({
collapsing: transitioning,
show: expanded,
})}
onTransitionEnd={handleTransitionEnd}
ref={menuRef}
>
<Nav stacked>
Expand Down
13 changes: 6 additions & 7 deletions packages/clay-navigation-bar/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ const ClayNavigationBar: React.FunctionComponent<IProps> & {
}: IProps) => {
const [visible, setVisible] = React.useState(false);
const contentRef = React.useRef<HTMLDivElement>(null);
const [
transitioning,
handleTransitionEnd,
handleClickToggler,
] = useTransitionHeight(visible, setVisible, contentRef);
const {animate, transitioning} = useTransitionHeight(
visible,
setVisible,
contentRef
);

const activeElementsCount = children.filter((child) => child.props.active)
.length;
Expand Down Expand Up @@ -89,7 +89,7 @@ const ClayNavigationBar: React.FunctionComponent<IProps> & {
)}
data-testid="navbarToggler"
displayType="unstyled"
onClick={handleClickToggler}
onClick={animate}
>
<span className="navbar-text-truncate">{triggerLabel}</span>

Expand All @@ -103,7 +103,6 @@ const ClayNavigationBar: React.FunctionComponent<IProps> & {
show: visible,
})}
data-testid="NavigationBarDropdown"
onTransitionEnd={handleTransitionEnd}
ref={contentRef}
>
<ClayLayout.ContainerFluid>
Expand Down
13 changes: 6 additions & 7 deletions packages/clay-panel/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ const ClayPanel: React.FunctionComponent<IProps> & {
const panelRef = React.useRef<HTMLDivElement>(null);
const [expanded, setExpaned] = React.useState<boolean>(defaultExpanded);

const [
transitioning,
handleTransitionEnd,
handleClickToggler,
] = useTransitionHeight(expanded, setExpaned, panelRef);
const {animate, transitioning} = useTransitionHeight(
expanded,
setExpaned,
panelRef
);

const showIconCollapsed = !(
(!expanded && transitioning) ||
Expand Down Expand Up @@ -120,7 +120,7 @@ const ClayPanel: React.FunctionComponent<IProps> & {
collapsed: showIconCollapsed,
}
)}
onClick={handleClickToggler}
onClick={animate}
role="tab"
>
{displayTitle &&
Expand Down Expand Up @@ -160,7 +160,6 @@ const ClayPanel: React.FunctionComponent<IProps> & {
show: expanded,
}
)}
onTransitionEnd={handleTransitionEnd}
ref={panelRef}
role="tabpanel"
>
Expand Down
87 changes: 32 additions & 55 deletions packages/clay-shared/src/useTransitionHeight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

import React from 'react';
import React, {useCallback, useEffect, useState} from 'react';

/**
* Removes the height style that triggers a transition when collapse
Expand Down Expand Up @@ -35,74 +35,51 @@ function setCollapseHeight(collapseElementRef: React.RefObject<any>) {

export function useTransitionHeight(
visible: boolean,
setVisible: any,
setVisible: React.Dispatch<React.SetStateAction<boolean>>,
contentRef: React.RefObject<any>
) {
const [transitioning, setTransitioning] = React.useState<boolean>(false);
const [transitioning, setTransitioning] = useState<boolean>(false);

const transitionBuffer = 0.01;
const transitionTimerRef = React.useRef<NodeJS.Timeout | null>(null);

const fakeTransitionEnd = () => {
const {transitionDelay, transitionDuration} = window.getComputedStyle(
contentRef.current
);
const totalDuration =
(parseFloat(transitionDelay) +
parseFloat(transitionDuration) +
transitionBuffer) *
1000;

transitionTimerRef.current = setTimeout(() => {
setTransitioning(false);
setVisible(!visible);

if (!visible) {
removeCollapseHeight(contentRef);
}
}, totalDuration);
};

React.useEffect(() => {
useEffect(() => {
if (transitioning) {
setCollapseHeight(contentRef);

if (visible) {
removeCollapseHeight(contentRef);
}

fakeTransitionEnd();
}
}, [transitioning]);
const {
transitionDelay,
transitionDuration,
} = window.getComputedStyle(contentRef.current);

const handleTransitionEnd = (event: React.TransitionEvent) => {
if (transitionTimerRef.current) {
clearTimeout(transitionTimerRef.current);
}
const totalDuration =
(parseFloat(transitionDelay) + parseFloat(transitionDuration)) *
1000;

if (event.target === contentRef.current && transitioning && !visible) {
setVisible(true);
setTransitioning(false);
removeCollapseHeight(contentRef);
} else if (event.target === contentRef.current) {
setVisible(false);
setTransitioning(false);
}
};
setTimeout(() => {
setVisible(!visible);
setTransitioning(false);

const willTriggerTransition = (event: React.MouseEvent | MouseEvent) => {
event.preventDefault();
if (visible && !transitioning) {
setCollapseHeight(contentRef);
if (!visible) {
removeCollapseHeight(contentRef);
}
}, totalDuration);
}
}, [transitioning]);

const animate = useCallback(
(event: React.SyntheticEvent) => {
event.preventDefault();

if (visible && !transitioning) {
setCollapseHeight(contentRef);
}

if (!transitioning) {
setTransitioning(true);
}
};
},
[transitioning, visible]
);

return [transitioning, handleTransitionEnd, willTriggerTransition] as [
boolean,
(event: React.TransitionEvent) => void,
(event: React.MouseEvent | MouseEvent) => void
];
return {animate, transitioning};
}

0 comments on commit 4cf740a

Please sign in to comment.