Create testimonial component + testimonials section (#53)
This commit is contained in:
parent
af323d1642
commit
1a5e537750
7 changed files with 126 additions and 3 deletions
1
src/components/atoms/divider.astro
Normal file
1
src/components/atoms/divider.astro
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="w-full h-px bg-gray-200"></div>
|
||||||
|
|
@ -1 +1 @@
|
||||||
<div class="p-8 bg-white rounded-2xl shadow-md"><slot /></div>
|
<div class="p-8 bg-white rounded-2xl shadow-md flex flex-col gap-6"><slot /></div>
|
||||||
|
|
|
||||||
37
src/components/organisms/testimonial.astro
Normal file
37
src/components/organisms/testimonial.astro
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
import { Image } from '@astrojs/image/components';
|
||||||
|
|
||||||
|
import IconButton from '@/atoms/icon-button.astro';
|
||||||
|
import Typography from '@/atoms/typography.astro';
|
||||||
|
import type { Testimonial } from '@/types/testimonials-section';
|
||||||
|
|
||||||
|
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||||
|
testimonial: Testimonial;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
testimonial: { author, content, image, relation, socials },
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class:list={['w-full', 'px-4', 'py-8', 'flex', 'flex-col', 'gap-4']}>
|
||||||
|
<div class:list={['flex', 'justify-between']}>
|
||||||
|
<div class:list={['flex', 'gap-4', 'flex-col', 'sm:flex-row']}>
|
||||||
|
<Image src={image} alt={author} format="webp" class:list={['w-14', 'h-14', 'rounded-lg']} />
|
||||||
|
<div>
|
||||||
|
<Typography variant="item-title">{author}</Typography>
|
||||||
|
<Typography variant="item-subtitle">{relation}</Typography>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
socials && (
|
||||||
|
<div class:list={['flex', 'gap-3']}>
|
||||||
|
{socials.map(({ icon, url }) => (
|
||||||
|
<IconButton icon={icon} href={url} target="_blank" size="small" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<Typography variant="paragraph">{content}</Typography>
|
||||||
|
</div>
|
||||||
|
|
@ -1,8 +1,28 @@
|
||||||
---
|
---
|
||||||
|
import Divider from '@/atoms/divider.astro';
|
||||||
import SectionCard from '@/atoms/section-card.astro';
|
import SectionCard from '@/atoms/section-card.astro';
|
||||||
|
import Typography from '@/atoms/typography.astro';
|
||||||
|
import Testimonial from '@/organisms/testimonial.astro';
|
||||||
import type { TestimonialsSection } from '@/types/testimonials-section';
|
import type { TestimonialsSection } from '@/types/testimonials-section';
|
||||||
|
|
||||||
export interface Props extends TestimonialsSection {}
|
export interface Props extends TestimonialsSection {}
|
||||||
|
|
||||||
|
const {
|
||||||
|
testimonials,
|
||||||
|
config: { title },
|
||||||
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard>Testimonials section</SectionCard>
|
<SectionCard>
|
||||||
|
<Typography variant="section-title">{title}</Typography>
|
||||||
|
<div class:list={['flex', 'flex-col']}>
|
||||||
|
{
|
||||||
|
testimonials.map((testimonial, index) => (
|
||||||
|
<>
|
||||||
|
<Testimonial testimonial={testimonial} />
|
||||||
|
{index !== testimonials.length - 1 && <Divider />}
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</SectionCard>
|
||||||
|
|
|
||||||
20
src/pages/playground/testimonial.astro
Normal file
20
src/pages/playground/testimonial.astro
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
import Testimonial from '@/organisms/testimonial.astro';
|
||||||
|
import type { Testimonial as TestimonialData } from '@/types/testimonials-section';
|
||||||
|
|
||||||
|
const testimonial: TestimonialData = {
|
||||||
|
author: 'Howard Stewart',
|
||||||
|
relation: 'We work together as front-end developers at Google',
|
||||||
|
content:
|
||||||
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl vel tincidunt aliquam, nunc nisl aliquet nisl, eget aliquet nunc nisl euismod nisl. Sed euismod, nisl vel tincidunt aliquam, nunc nisl aliquet nisl, eget aliquet nunc nisl euismod nisl.',
|
||||||
|
image: import('@/assets/testimonials/testimonial-1.jpeg'),
|
||||||
|
socials: [
|
||||||
|
{ name: 'GitHub', icon: 'fa6-brands:github', url: '#' },
|
||||||
|
{ name: 'LinkedIn', icon: 'fa6-brands:linkedin-in', url: '#' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class:list={['flex', 'flex-col', 'gap-2', 'max-w-[896px]']}>
|
||||||
|
<Testimonial testimonial={testimonial} />
|
||||||
|
</div>
|
||||||
45
src/pages/playground/testimonials-section.astro
Normal file
45
src/pages/playground/testimonials-section.astro
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
import TestimonialsSection from '@/sections/testimonials-section.astro';
|
||||||
|
import type { Testimonial } from '@/types/testimonials-section';
|
||||||
|
|
||||||
|
const testimonials: Testimonial[] = [
|
||||||
|
{
|
||||||
|
image: import('@/assets/testimonials/testimonial-1.jpeg'),
|
||||||
|
author: 'Howard Stewart',
|
||||||
|
relation: 'We work together as front-end developers at Google',
|
||||||
|
content:
|
||||||
|
'In nec mattis sem. Morbi purus lorem, euismod ac varius at, aliquet vitae augue. Pellentesque ut facilisis felis. In sed dui blandit, aliquet odio eu, elementum leo. In facilisis dapibus tortor ac volutpat. Cras cursus nec odio maximus elementum.',
|
||||||
|
socials: [
|
||||||
|
{ name: 'GitHub', icon: 'fa6-brands:github', url: '#' },
|
||||||
|
{ name: 'LinkedIn', icon: 'fa6-brands:linkedin-in', url: '#' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: import('@/assets/testimonials/testimonial-2.jpeg'),
|
||||||
|
author: 'Jean Richards',
|
||||||
|
relation: 'My project manager at GitLab',
|
||||||
|
content:
|
||||||
|
'Praesent nec congue elit. Vestibulum lobortis congue ipsum, a gravida mi tempus ac. Mauris aliquet purus nibh, vel varius turpis tempus non. Nullam eget ultricies orci. Quisque nulla ante, auctor eget varius ac, imperdiet nec magna.',
|
||||||
|
socials: [{ name: 'LinkedIn', icon: 'fa6-brands:linkedin-in', url: '#' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: import('@/assets/testimonials/testimonial-3.jpeg'),
|
||||||
|
author: 'Jason Fisher',
|
||||||
|
relation: 'My customer for sidewing.com website',
|
||||||
|
content:
|
||||||
|
'Mauris tincidunt at purus vehicula porta. Mauris eget mollis turpis. Sed iaculis rutrum pharetra. Vivamus risus quam, suscipit et semper ut, aliquet ut tellus. Donec quis auctor nunc.',
|
||||||
|
socials: [
|
||||||
|
{ name: 'GitHub', icon: 'fa6-brands:github', url: '#' },
|
||||||
|
{ name: 'Website', icon: 'fa6-solid:globe', url: '#' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
---
|
||||||
|
|
||||||
|
<body class="flex justify-center bg-gray-50">
|
||||||
|
<div class="flex gap-8 w-full max-w-6xl px-2 py-3 sm:px-8 sm:py-12 lg:px-16 lg:py-20 lg:ml-22">
|
||||||
|
<main class="w-full space-y-4 sm:space-y-6 lg:space-y-8">
|
||||||
|
<TestimonialsSection testimonials={testimonials} config={{ title: 'Testimonials', icon: 'fa6-solid:comment' }} />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { LocalImage, SectionConfig, Social } from './common';
|
import type { LocalImage, SectionConfig, Social } from './common';
|
||||||
|
|
||||||
interface Testimonial {
|
export interface Testimonial {
|
||||||
image: LocalImage;
|
image: LocalImage;
|
||||||
author: string;
|
author: string;
|
||||||
relation: string;
|
relation: string;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue