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