From a91c9db4e0c2092e31e767ac771b72acff7925a5 Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Thu, 30 May 2024 14:13:34 +0530 Subject: [PATCH] chore: optimized survey card animation (#2707) --- .../wrappers/StackedCardsContainer.tsx | 110 +++++++++++------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/packages/surveys/src/components/wrappers/StackedCardsContainer.tsx b/packages/surveys/src/components/wrappers/StackedCardsContainer.tsx index b137a80d38..e930568407 100644 --- a/packages/surveys/src/components/wrappers/StackedCardsContainer.tsx +++ b/packages/surveys/src/components/wrappers/StackedCardsContainer.tsx @@ -10,7 +10,7 @@ interface StackedCardsContainerProps { cardArrangement: TCardArrangementOptions; currentQuestionId: string; survey: TSurvey; - getCardContent: (questionIdx: number, offset: number) => JSX.Element | undefined; + getCardContent: (questionIdxTemp: number, offset: number) => JSX.Element | undefined; styling: TProductStyling | TSurveyStyling; setQuestionId: (questionId: string) => void; shouldResetQuestionId?: boolean; @@ -33,23 +33,42 @@ export const StackedCardsContainer = ({ const resizeObserver = useRef(null); const [cardHeight, setCardHeight] = useState("auto"); - const cardIndexes = useMemo(() => { - let cardIndexTemp = survey.questions.map((_, index) => index); - if (survey.welcomeCard.enabled) { - cardIndexTemp.unshift(-1); - } - if (survey.thankYouCard.enabled) { - cardIndexTemp.push(survey.questions.length); - } - return cardIndexTemp; - }, [survey]); - - const questionIdx = useMemo(() => { + const questionIdxTemp = useMemo(() => { if (currentQuestionId === "start") return survey.welcomeCard.enabled ? -1 : 0; if (currentQuestionId === "end") return survey.thankYouCard.enabled ? survey.questions.length : 0; return survey.questions.findIndex((question) => question.id === currentQuestionId); }, [currentQuestionId, survey.welcomeCard.enabled, survey.thankYouCard.enabled, survey.questions]); + const [prevQuestionIdx, setPrevQuestionIdx] = useState(questionIdxTemp - 1); + const [currentQuestionIdx, setCurrentQuestionIdx] = useState(questionIdxTemp); + const [nextQuestionIdx, setNextQuestionIdx] = useState(questionIdxTemp + 1); + const [visitedQuestions, setVisitedQuestions] = useState([]); + + useEffect(() => { + if (questionIdxTemp > currentQuestionIdx) { + // Next button is clicked + setPrevQuestionIdx(currentQuestionIdx); + setCurrentQuestionIdx(questionIdxTemp); + setNextQuestionIdx(questionIdxTemp + 1); + setVisitedQuestions((prev) => { + return [...prev, currentQuestionIdx]; + }); + } else if (questionIdxTemp < currentQuestionIdx) { + // Back button is clicked + setNextQuestionIdx(currentQuestionIdx); + setCurrentQuestionIdx(questionIdxTemp); + setPrevQuestionIdx(visitedQuestions[visitedQuestions.length - 2]); + setVisitedQuestions((prev) => { + if (prev.length > 0) { + const newStack = prev.slice(0, -1); + return newStack; + } + return prev; + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [questionIdxTemp]); + const borderStyles = useMemo(() => { const baseStyle = { border: "1px solid", @@ -89,7 +108,7 @@ export const StackedCardsContainer = ({ // UseEffect to handle the resize of current question card and set cardHeight accordingly useEffect(() => { - const currentElement = cardRefs.current[questionIdx]; + const currentElement = cardRefs.current[questionIdxTemp]; if (currentElement) { if (resizeObserver.current) resizeObserver.current.disconnect(); resizeObserver.current = new ResizeObserver((entries) => { @@ -98,7 +117,7 @@ export const StackedCardsContainer = ({ resizeObserver.current.observe(currentElement); } return () => resizeObserver.current?.disconnect(); - }, [questionIdx, cardArrangement]); + }, [questionIdxTemp, cardArrangement]); // Reset question progress, when card arrangement changes useEffect(() => { @@ -138,35 +157,42 @@ export const StackedCardsContainer = ({ style={{ ...borderStyles, }}> - {getCardContent(questionIdx, 0)} + {getCardContent(questionIdxTemp, 0)} ) : ( - questionIdx !== undefined && - cardIndexes.map((_, idx) => { - const index = survey.welcomeCard.enabled ? idx - 1 : idx; - const offset = index - questionIdx; - const isHidden = offset < 0; - return ( -
(cardRefs.current[index] = el)} - id={`questionCard-${index}`} - key={index} - style={{ - zIndex: 1000 - index, - transform: `${calculateCardTransform(offset)}`, - opacity: isHidden ? 0 : (100 - 30 * offset) / 100, - height: getCardHeight(offset), - transitionDuration: "600ms", - pointerEvents: offset === 0 ? "auto" : "none", - ...borderStyles, - ...straightCardArrangementStyles(offset), - ...getBottomStyles(), - }} - className="pointer rounded-custom bg-survey-bg absolute inset-x-0 backdrop-blur-md transition-all ease-in-out"> - {getCardContent(index, offset)} -
- ); - }) + questionIdxTemp !== undefined && + [prevQuestionIdx, currentQuestionIdx, nextQuestionIdx, nextQuestionIdx + 1].map( + (questionIdxTemp, index) => { + //Check for hiding extra card + if (survey.thankYouCard.enabled) { + if (questionIdxTemp > survey.questions.length) return; + } else { + if (questionIdxTemp > survey.questions.length - 1) return; + } + const offset = index - 1; + const isHidden = offset < 0; + return ( +
(cardRefs.current[questionIdxTemp] = el)} + id={`questionCard-${questionIdxTemp}`} + key={questionIdxTemp} + style={{ + zIndex: 1000 - questionIdxTemp, + transform: `${calculateCardTransform(offset)}`, + opacity: isHidden ? 0 : (100 - 0 * offset) / 100, + height: getCardHeight(offset), + transitionDuration: "600ms", + pointerEvents: offset === 0 ? "auto" : "none", + ...borderStyles, + ...straightCardArrangementStyles(offset), + ...getBottomStyles(), + }} + className="pointer rounded-custom bg-survey-bg absolute inset-x-0 backdrop-blur-md transition-all ease-in-out"> + {getCardContent(questionIdxTemp, offset)} +
+ ); + } + ) )} );