fix(header,accordion): liquid-glass header + progress bar animation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-05-28 16:51:24 +01:00
parent 32e0f688d1
commit ef693589bc
3 changed files with 44 additions and 9 deletions

View file

@ -24,3 +24,12 @@
/* Brand shadow used on cards, buttons */
--shadow-brand: 0px 4px 60px rgba(242, 139, 74, 0.25);
}
@keyframes progress-fill {
from {
width: 0%;
}
to {
width: 100%;
}
}

View file

@ -39,8 +39,10 @@ export function HeaderClient({ navLinks, ctaLabel, ctaHref, logo }: HeaderClient
<div
className="relative mx-auto max-w-[1204px] rounded-b-[20px]"
style={{
backgroundColor: '#396817',
boxShadow: '0 4px 20px rgba(0,0,0,0.18)',
backgroundColor: 'rgba(34, 62, 13, 0.55)',
backdropFilter: 'blur(18px) saturate(180%) brightness(1.1)',
WebkitBackdropFilter: 'blur(18px) saturate(180%) brightness(1.1)',
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.15), 0 2px 12px rgba(0,0,0,0.20)',
}}
>
<div className="relative flex h-[60px] items-center justify-between px-[20px] lg:h-[120px] lg:px-[30px]">

View file

@ -45,27 +45,39 @@ interface WhyParentsProps {
title?: string
}
const INTERVAL = 4000
export function WhyParents({ items, sideGallery: _sideGallery, title }: WhyParentsProps) {
const [openIndex, setOpenIndex] = useState<number>(0)
const [progressKey, setProgressKey] = useState<number>(0)
const autoTimer = useRef<ReturnType<typeof setInterval> | null>(null)
const lenRef = useRef(0)
const activeItems = items && items.length > 0 ? items : STATIC_ITEMS
useEffect(() => {
autoTimer.current = setInterval(() => {
setOpenIndex((prev) => (prev + 1) % activeItems.length)
}, 4000)
lenRef.current = activeItems.length
})
useEffect(() => {
const tick = () => {
setOpenIndex((prev) => (prev + 1) % lenRef.current)
setProgressKey((k) => k + 1)
}
autoTimer.current = setInterval(tick, INTERVAL)
return () => {
if (autoTimer.current) clearInterval(autoTimer.current)
}
}, [activeItems.length])
}, [])
function handleItemClick(i: number) {
setOpenIndex(i)
setProgressKey((k) => k + 1)
if (autoTimer.current) clearInterval(autoTimer.current)
autoTimer.current = setInterval(() => {
setOpenIndex((prev) => (prev + 1) % activeItems.length)
}, 4000)
setOpenIndex((prev) => (prev + 1) % lenRef.current)
setProgressKey((k) => k + 1)
}, INTERVAL)
}
return (
@ -89,7 +101,7 @@ export function WhyParents({ items, sideGallery: _sideGallery, title }: WhyParen
<button
key={i}
onClick={() => handleItemClick(i)}
className="flex w-full flex-col gap-2.5 rounded-[10px] bg-[#f1fbeb] px-[50px] py-[20px] text-left shadow-[0_4px_60px_0_rgba(242,139,74,0.25)] transition-all duration-200 lg:w-[628px]"
className="relative flex w-full flex-col gap-2.5 overflow-hidden rounded-[10px] bg-[#f1fbeb] px-[50px] py-[20px] text-left shadow-[0_4px_60px_0_rgba(242,139,74,0.25)] transition-all duration-200 lg:w-[628px]"
aria-expanded={isOpen}
>
<div className="flex items-center gap-5">
@ -128,6 +140,18 @@ export function WhyParents({ items, sideGallery: _sideGallery, title }: WhyParen
</p>
</div>
</div>
{/* Progress bar — CSS animation, keyed to reset on each advance */}
{isOpen && (
<div className="absolute bottom-0 left-0 h-[3px] w-full">
<div
key={progressKey}
className="h-full bg-[#f28b4a]"
style={{
animation: `progress-fill ${INTERVAL}ms linear forwards`,
}}
/>
</div>
)}
</button>
)
})}