fix: added event listener to scroll when transition ends

This commit is contained in:
Tobias Johansson
2024-11-29 15:05:38 +01:00
parent d3dad4c73d
commit 92db90502c
3 changed files with 17 additions and 58 deletions

View File

@@ -35,9 +35,6 @@ export default function SectionAccordion({
const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" }) const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" })
const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" }) const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" })
const accordionRef = useRef<HTMLDivElement>(null)
const [scope, animate] = useAnimate()
useEffect(() => { useEffect(() => {
if (step === StepEnum.selectBed && bedType) { if (step === StepEnum.selectBed && bedType) {
setTitle(bedType.description) setTitle(bedType.description)
@@ -60,49 +57,6 @@ export default function SectionAccordion({
setIsOpen(currentStep === step) setIsOpen(currentStep === step)
}, [currentStep, setIsOpen, step]) }, [currentStep, setIsOpen, step])
useEffect(() => {
if (!accordionRef.current) return
const animateAccordion = async () => {
// Measure the initial position of the accordion
const initialOffset = accordionRef.current?.offsetTop || 0
// Start the accordion expansion animation
const accordionAnimation = animate(
scope.current,
{
gridTemplateRows: isOpen
? "var(--header-height) 1fr"
: "var(--header-height) 0fr",
},
{ duration: 0.3, ease: "easeInOut" }
)
if (isOpen) {
// Start scrolling immediately
const scrollAnimation = animate(
window.scrollY,
initialOffset - 100, // 100px offset from top
{
duration: 0.3,
ease: "easeInOut",
onUpdate: (latest) => {
window.scrollTo(0, latest)
},
}
)
// Wait for both animations to complete
await Promise.all([accordionAnimation, scrollAnimation])
} else {
// If closing, just wait for the accordion animation
await accordionAnimation
}
}
animateAccordion()
}, [isOpen, scope, animate])
function onModify() { function onModify() {
navigate(step) navigate(step)
} }
@@ -110,13 +64,7 @@ export default function SectionAccordion({
const textColor = const textColor =
isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled" isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled"
return ( return (
<motion.div <div className={styles.accordion} data-open={isOpen} data-step={step}>
className={styles.accordion}
data-open={isOpen}
data-step={step}
ref={scope}
transition={{ duration: 0.3, ease: "easeOut" }}
>
<div className={styles.iconWrapper}> <div className={styles.iconWrapper}>
<div className={styles.circle} data-checked={isComplete}> <div className={styles.circle} data-checked={isComplete}>
{isComplete ? ( {isComplete ? (
@@ -124,7 +72,7 @@ export default function SectionAccordion({
) : null} ) : null}
</div> </div>
</div> </div>
<header className={styles.header} ref={accordionRef}> <header className={styles.header}>
<button <button
onClick={onModify} onClick={onModify}
disabled={!isComplete} disabled={!isComplete}
@@ -151,6 +99,6 @@ export default function SectionAccordion({
<div className={styles.content}> <div className={styles.content}>
<div className={styles.contentWrapper}>{children}</div> <div className={styles.contentWrapper}>{children}</div>
</div> </div>
</motion.div> </div>
) )
} }

View File

@@ -5,7 +5,7 @@
gap: var(--Spacing-x3); gap: var(--Spacing-x3);
width: 100%; width: 100%;
padding-top: var(--Spacing-x3); padding-top: var(--Spacing-x3);
/* transition: 0.4s ease-out; */ transition: 0.4s ease-out;
display: grid; display: grid;
grid-template-areas: "circle header" "content content"; grid-template-areas: "circle header" "content content";
@@ -15,6 +15,7 @@
column-gap: var(--Spacing-x-one-and-half); column-gap: var(--Spacing-x-one-and-half);
transform-origin: top; transform-origin: top;
scroll-margin-top: 71px; /* booking widget height */
} }
.accordion:last-child { .accordion:last-child {
@@ -81,9 +82,9 @@
background-color: var(--Base-Surface-Subtle-Hover); background-color: var(--Base-Surface-Subtle-Hover);
} }
/* .accordion[data-open="true"] { .accordion[data-open="true"] {
grid-template-rows: var(--header-height) 1fr; grid-template-rows: var(--header-height) 1fr;
} */ }
.contentWrapper { .contentWrapper {
padding-bottom: var(--Spacing-x3); padding-bottom: var(--Spacing-x3);

View File

@@ -42,6 +42,16 @@ export function extractGuestFromUser(user: NonNullable<SafeUser>) {
export function navigate(step: StepEnum, searchParams: string) { export function navigate(step: StepEnum, searchParams: string) {
window.history.pushState({ step }, "", `${step}?${searchParams}`) window.history.pushState({ step }, "", `${step}?${searchParams}`)
const element = document.querySelector(`[data-step='${step}']`)
const isMobile = window.matchMedia("(max-width: 768px)").matches
if (element && isMobile) {
element.addEventListener(
"transitionend",
() => element?.scrollIntoView({ behavior: "smooth" }),
{ once: true }
)
}
} }
export function checkIsSameBooking(prev: BookingData, next: BookingData) { export function checkIsSameBooking(prev: BookingData, next: BookingData) {