From 5309779be9b5e1ac09342f4f338ef6edaf5b96d5 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 4 Mar 2026 19:07:06 +0000 Subject: [PATCH] Switch to version 1: modified src/components/cardStack/layouts/timelines/TimelineBase.tsx --- .../layouts/timelines/TimelineBase.tsx | 157 +++++++++++++++--- 1 file changed, 137 insertions(+), 20 deletions(-) diff --git a/src/components/cardStack/layouts/timelines/TimelineBase.tsx b/src/components/cardStack/layouts/timelines/TimelineBase.tsx index c2ef2e8..6c3930a 100644 --- a/src/components/cardStack/layouts/timelines/TimelineBase.tsx +++ b/src/components/cardStack/layouts/timelines/TimelineBase.tsx @@ -1,32 +1,149 @@ -import React from 'react'; +"use client"; + +import React, { Children, useCallback } from "react"; +import { cls } from "@/lib/utils"; +import CardStackTextBox from "../../CardStackTextBox"; +import { useCardAnimation } from "../../hooks/useCardAnimation"; +import type { LucideIcon } from "lucide-react"; +import type { ButtonConfig, CardAnimationType, TitleSegment, ButtonAnimationType } from "../../types"; +import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants"; + +type TimelineVariant = "timeline"; interface TimelineBaseProps { - id: string; - title: string; - description: string; - isActive: boolean; - isPast: boolean; + children: React.ReactNode; + variant?: TimelineVariant; + uniformGridCustomHeightClasses?: string; + animationType: CardAnimationType; + title?: string; + titleSegments?: TitleSegment[]; + description?: string; + tag?: string; + tagIcon?: LucideIcon; + tagAnimation?: ButtonAnimationType; + buttons?: ButtonConfig[]; + buttonAnimation?: ButtonAnimationType; + textboxLayout?: TextboxLayout; + useInvertedBackground?: InvertedBackground; + className?: string; + containerClassName?: string; + textBoxClassName?: string; + titleClassName?: string; + titleImageWrapperClassName?: string; + titleImageClassName?: string; + descriptionClassName?: string; + tagClassName?: string; + buttonContainerClassName?: string; + buttonClassName?: string; + buttonTextClassName?: string; + ariaLabel?: string; } -export const TimelineBase: React.FC = ({ - id, +const TimelineBase = ({ + children, + variant = "timeline", + uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90", + animationType, title, + titleSegments, description, - isActive, - isPast, -}) => { - const opacity = isActive ? 'opacity-100' : isPast ? 'opacity-75' : 'opacity-50'; - const scale = isActive ? 'scale-100' : 'scale-95'; + tag, + tagIcon, + tagAnimation, + buttons, + buttonAnimation, + textboxLayout = "default", + useInvertedBackground, + className = "", + containerClassName = "", + textBoxClassName = "", + titleClassName = "", + titleImageWrapperClassName = "", + titleImageClassName = "", + descriptionClassName = "", + tagClassName = "", + buttonContainerClassName = "", + buttonClassName = "", + buttonTextClassName = "", + ariaLabel = "Timeline section", +}: TimelineBaseProps) => { + const childrenArray = Children.toArray(children); + const { itemRefs } = useCardAnimation({ + animationType, + itemCount: childrenArray.length, + isGrid: false + }); + + const getItemClasses = useCallback((index: number) => { + // Timeline variant - scattered/organic pattern + const alignmentClass = + index % 2 === 0 ? "self-start ml-0" : "self-end mr-0"; + + const marginClasses = cls( + index % 4 === 0 && "md:ml-0", + index % 4 === 1 && "md:mr-20", + index % 4 === 2 && "md:ml-15", + index % 4 === 3 && "md:mr-30" + ); + + return cls(alignmentClass, marginClasses); + }, []); return ( -
-
-

{title}

-

{description}

+
+ {(title || titleSegments || description) && ( + + )} +
+ {Children.map(childrenArray, (child, index) => ( +
{ itemRefs.current[index] = el; }} + > + {child} +
+ ))} +
-
+ ); }; + +TimelineBase.displayName = "TimelineBase"; + +export default React.memo(TimelineBase);