diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-22 15:08:37 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-22 15:08:37 +0300 |
| commit | fcc2f4704e39b0e69b377cc138f75027721dac22 (patch) | |
| tree | 732fc94b354a26c08fba9cc9059f9c6c900182be /src/components/widgets/Pricing.astro | |
Initial template
Diffstat (limited to 'src/components/widgets/Pricing.astro')
| -rw-r--r-- | src/components/widgets/Pricing.astro | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/components/widgets/Pricing.astro b/src/components/widgets/Pricing.astro new file mode 100644 index 0000000..3f20b74 --- /dev/null +++ b/src/components/widgets/Pricing.astro @@ -0,0 +1,83 @@ +--- +import { Icon } from 'astro-icon/components'; +import Button from '~/components/ui/Button.astro'; +import Headline from '~/components/ui/Headline.astro'; +import WidgetWrapper from '~/components/ui/WidgetWrapper.astro'; +import type { Pricing as Props } from '~/types'; + +const { + title = '', + subtitle = '', + tagline = '', + prices = [], + + id, + isDark = false, + classes = {}, + bg = await Astro.slots.render('bg'), +} = Astro.props; +--- + +<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-7xl mx-auto ${classes?.container ?? ''}`} bg={bg}> + <Headline title={title} subtitle={subtitle} tagline={tagline} /> + <div class="flex items-stretch justify-center"> + <div class="grid grid-cols-3 gap-4 dark:text-white sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3"> + { + prices && + prices.map(({ title, subtitle, price, period, items, callToAction, hasRibbon = false, ribbonTitle }) => ( + <div class="col-span-3 mx-auto flex w-full sm:col-span-1 md:col-span-1 lg:col-span-1 xl:col-span-1 intersect-once motion-safe:md:intersect:animate-fade motion-safe:md:opacity-0 intersect-quarter"> + {price && period && ( + <div class="rounded-lg backdrop-blur border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900 shadow px-6 py-8 flex w-full max-w-sm flex-col justify-between text-center"> + {hasRibbon && ribbonTitle && ( + <div class="absolute right-[-5px] 2xl:right-[-8px] rtl:right-auto rtl:left-[-8px] rtl:2xl:left-[-10px] top-[-5px] 2xl:top-[-10px] z-[1] h-[100px] w-[100px] overflow-hidden text-right"> + <span class="absolute top-[19px] right-[-21px] rtl:right-auto rtl:left-[-21px] block w-full rotate-45 rtl:-rotate-45 bg-green-700 text-center text-[10px] font-bold uppercase leading-5 text-white shadow-[0_3px_10px_-5px_rgba(0,0,0,0.3)] before:absolute before:left-0 before:top-full before:z-[-1] before:border-[3px] before:border-r-transparent before:border-b-transparent before:border-l-green-800 before:border-t-green-800 before:content-[''] after:absolute after:right-0 after:top-full after:z-[-1] after:border-[3px] after:border-l-transparent after:border-b-transparent after:border-r-green-800 after:border-t-green-800 after:content-['']"> + {ribbonTitle} + </span> + </div> + )} + <div class="px-2 py-0"> + {title && ( + <h3 class="text-center text-xl font-semibold uppercase leading-6 tracking-wider mb-2">{title}</h3> + )} + {subtitle && <p class="font-light sm:text-lg text-gray-600 dark:text-slate-400">{subtitle}</p>} + <div class="my-8"> + <div class="flex items-center justify-center text-center mb-1"> + <span class="text-5xl">$</span> + <span class="text-6xl font-extrabold">{price}</span> + </div> + <span class="text-base leading-6 lowercase text-gray-600 dark:text-slate-400">{period}</span> + </div> + {items && ( + <ul class="my-8 md:my-10 space-y-2 text-left"> + {items.map( + ({ description, icon }) => + description && ( + <li class="mb-1.5 flex items-start space-x-3 leading-7"> + <div class="rounded-full bg-primary mt-1"> + <Icon name={icon ? icon : 'tabler:check'} class="w-5 h-5 font-bold p-1 text-white" /> + </div> + <span>{description}</span> + </li> + ) + )} + </ul> + )} + </div> + {callToAction && ( + <div class={`flex justify-center`}> + {typeof callToAction === 'string' ? ( + <Fragment set:html={callToAction} /> + ) : ( + callToAction && + callToAction.href && <Button {...(hasRibbon ? { variant: 'primary' } : {})} {...callToAction} /> + )} + </div> + )} + </div> + )} + </div> + )) + } + </div> + </div> +</WidgetWrapper> |
