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 breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" })
const accordionRef = useRef<HTMLDivElement>(null)
const [scope, animate] = useAnimate()
useEffect(() => {
if (step === StepEnum.selectBed && bedType) {
setTitle(bedType.description)
@@ -60,49 +57,6 @@ export default function SectionAccordion({
setIsOpen(currentStep === 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() {
navigate(step)
}
@@ -110,13 +64,7 @@ export default function SectionAccordion({
const textColor =
isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled"
return (
<motion.div
className={styles.accordion}
data-open={isOpen}
data-step={step}
ref={scope}
transition={{ duration: 0.3, ease: "easeOut" }}
>
<div className={styles.accordion} data-open={isOpen} data-step={step}>
<div className={styles.iconWrapper}>
<div className={styles.circle} data-checked={isComplete}>
{isComplete ? (
@@ -124,7 +72,7 @@ export default function SectionAccordion({
) : null}
</div>
</div>
<header className={styles.header} ref={accordionRef}>
<header className={styles.header}>
<button
onClick={onModify}
disabled={!isComplete}
@@ -151,6 +99,6 @@ export default function SectionAccordion({
<div className={styles.content}>
<div className={styles.contentWrapper}>{children}</div>
</div>
</motion.div>
</div>
)
}

View File

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

View File

@@ -42,6 +42,16 @@ export function extractGuestFromUser(user: NonNullable<SafeUser>) {
export function navigate(step: StepEnum, searchParams: string) {
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) {