summaryrefslogtreecommitdiff
path: root/src/components/widgets/Testimonials.astro
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2025-07-22 15:08:37 +0300
committerDawid Rycerz <dawid@rycerz.xyz>2025-07-22 15:08:37 +0300
commitfcc2f4704e39b0e69b377cc138f75027721dac22 (patch)
tree732fc94b354a26c08fba9cc9059f9c6c900182be /src/components/widgets/Testimonials.astro
Initial template
Diffstat (limited to 'src/components/widgets/Testimonials.astro')
-rw-r--r--src/components/widgets/Testimonials.astro75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/components/widgets/Testimonials.astro b/src/components/widgets/Testimonials.astro
new file mode 100644
index 0000000..11db7b5
--- /dev/null
+++ b/src/components/widgets/Testimonials.astro
@@ -0,0 +1,75 @@
+---
+import Headline from '~/components/ui/Headline.astro';
+import WidgetWrapper from '~/components/ui/WidgetWrapper.astro';
+import Button from '~/components/ui/Button.astro';
+import Image from '~/components/common/Image.astro';
+import type { Testimonials as Props } from '~/types';
+
+const {
+ title = '',
+ subtitle = '',
+ tagline = '',
+ testimonials = [],
+ callToAction,
+
+ id,
+ isDark = false,
+ classes = {},
+ bg = await Astro.slots.render('bg'),
+} = Astro.props;
+---
+
+<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl mx-auto ${classes?.container ?? ''}`} bg={bg}>
+ <Headline title={title} subtitle={subtitle} tagline={tagline} />
+
+ <div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
+ {
+ testimonials &&
+ testimonials.map(({ title, testimonial, name, job, image }) => (
+ <div class="flex h-auto intersect-once motion-safe:md:intersect:animate-fade motion-safe:md:opacity-0 intersect-quarter">
+ <div class="flex flex-col p-4 md:p-6 rounded-md shadow-xl dark:shadow-none dark:border dark:border-slate-600">
+ {title && <h2 class="text-lg font-medium leading-6 pb-4">{title}</h2>}
+ {testimonial && (
+ <blockquote class="flex-auto">
+ <p class="text-muted">" {testimonial} "</p>
+ </blockquote>
+ )}
+
+ <hr class="border-slate-200 dark:border-slate-600 my-4" />
+
+ <div class="flex items-center">
+ {image && (
+ <div class="h-10 w-10 rounded-full border border-slate-200 dark:border-slate-600">
+ {typeof image === 'string' ? (
+ <Fragment set:html={image} />
+ ) : (
+ <Image
+ class="h-10 w-10 rounded-full border border-slate-200 dark:border-slate-600 min-w-full min-h-full"
+ width={40}
+ height={40}
+ widths={[400, 768]}
+ layout="fixed"
+ {...image}
+ />
+ )}
+ </div>
+ )}
+
+ <div class="grow ml-3 rtl:ml-0 rtl:mr-3">
+ {name && <p class="text-base font-semibold">{name}</p>}
+ {job && <p class="text-xs text-muted">{job}</p>}
+ </div>
+ </div>
+ </div>
+ </div>
+ ))
+ }
+ </div>
+ {
+ callToAction && (
+ <div class="flex justify-center mx-auto w-fit mt-8 md:mt-12 font-medium">
+ <Button {...callToAction} />
+ </div>
+ )
+ }
+</WidgetWrapper>