wip
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
import { useEffect, useState } from "react"
|
||||
import { animate, motion, scroll, useAnimate } from "framer-motion"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
@@ -33,6 +34,10 @@ 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)
|
||||
@@ -55,6 +60,49 @@ 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)
|
||||
}
|
||||
@@ -62,7 +110,13 @@ export default function SectionAccordion({
|
||||
const textColor =
|
||||
isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled"
|
||||
return (
|
||||
<div className={styles.accordion} data-open={isOpen} data-step={step}>
|
||||
<motion.div
|
||||
className={styles.accordion}
|
||||
data-open={isOpen}
|
||||
data-step={step}
|
||||
ref={scope}
|
||||
transition={{ duration: 0.3, ease: "easeOut" }}
|
||||
>
|
||||
<div className={styles.iconWrapper}>
|
||||
<div className={styles.circle} data-checked={isComplete}>
|
||||
{isComplete ? (
|
||||
@@ -70,7 +124,7 @@ export default function SectionAccordion({
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<header className={styles.header}>
|
||||
<header className={styles.header} ref={accordionRef}>
|
||||
<button
|
||||
onClick={onModify}
|
||||
disabled={!isComplete}
|
||||
@@ -97,6 +151,6 @@ export default function SectionAccordion({
|
||||
<div className={styles.content}>
|
||||
<div className={styles.contentWrapper}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
@@ -13,6 +13,8 @@
|
||||
grid-template-rows: var(--header-height) 0fr;
|
||||
|
||||
column-gap: var(--Spacing-x-one-and-half);
|
||||
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
.accordion:last-child {
|
||||
@@ -79,9 +81,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);
|
||||
@@ -91,6 +93,7 @@
|
||||
overflow: hidden;
|
||||
grid-area: content;
|
||||
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
|
||||
Reference in New Issue
Block a user