diff options
Diffstat (limited to 'src/components/ui/Timeline.astro')
| -rw-r--r-- | src/components/ui/Timeline.astro | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/components/ui/Timeline.astro b/src/components/ui/Timeline.astro new file mode 100644 index 0000000..b25c9de --- /dev/null +++ b/src/components/ui/Timeline.astro @@ -0,0 +1,60 @@ +--- +import { Icon } from 'astro-icon/components'; +import { twMerge } from 'tailwind-merge'; +import type { Item } from '~/types'; + +export interface Props { + items?: Array<Item>; + defaultIcon?: string; + classes?: Record<string, string>; +} + +const { items = [], classes = {}, defaultIcon } = Astro.props as Props; + +const { + container: containerClass = '', + panel: panelClass = '', + title: titleClass = '', + description: descriptionClass = '', + icon: defaultIconClass = 'text-primary dark:text-slate-200 border-primary dark:border-secondary', +} = classes; +--- + +{ + items && items.length > 0 && ( + <div class={containerClass}> + {items.map(({ title, description, icon, classes: itemClasses = {} }, index = 0) => ( + <div + class={twMerge( + 'flex intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade', + panelClass, + itemClasses?.panel + )} + > + <div class="flex flex-col items-center mr-4 rtl:mr-0 rtl:ml-4"> + <div> + <div class="flex items-center justify-center"> + {(icon || defaultIcon) && ( + <Icon + name={icon || defaultIcon} + class={twMerge('w-10 h-10 p-2 rounded-full border-2', defaultIconClass, itemClasses?.icon)} + /> + )} + </div> + </div> + {index !== items.length - 1 && <div class="w-px h-full bg-black/10 dark:bg-slate-400/50" />} + </div> + <div class={`pt-1 ${index !== items.length - 1 ? 'pb-8' : ''}`}> + {title && <p class={twMerge('text-xl font-bold', titleClass, itemClasses?.title)} set:html={title} />} + {description && ( + <p + class={twMerge('text-muted mt-2', descriptionClass, itemClasses?.description)} + set:html={description} + /> + )} + </div> + </div> + ))} + </div> + ) +} |
