Unify spacing for section cards (#121)
This commit is contained in:
parent
7e15cd3412
commit
eb48d73020
11 changed files with 47 additions and 47 deletions
3
src/components/atoms/divided-list.astro
Normal file
3
src/components/atoms/divided-list.astro
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class:list={['flex', 'flex-col', 'gap-8']}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
---
|
---
|
||||||
import type { Section } from '@/types/data';
|
import type { Section } from '@/types/data';
|
||||||
|
|
||||||
|
import Typography from './typography.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
section: Section;
|
section: Section;
|
||||||
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { section } = Astro.props;
|
const { section, title } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id={section} class="p-8 bg-white dark:bg-gray-800 rounded-2xl shadow-md flex flex-col gap-6"><slot /></div>
|
<div id={section} class="p-8 bg-white dark:bg-gray-800 rounded-2xl shadow-md flex flex-col gap-6">
|
||||||
|
{
|
||||||
|
title && (
|
||||||
|
<Typography variant="section-title" id={`${section}-heading`}>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const { alt, ...sharedImageProps } = {
|
||||||
} as const;
|
} as const;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class:list={['flex', 'flex-col', 'gap-6', 'py-8', 'px-4']}>
|
<div class:list={['flex', 'flex-col', 'gap-6']}>
|
||||||
<div class:list={['flex', 'flex-col', 'gap-4']}>
|
<div class:list={['flex', 'flex-col', 'gap-4']}>
|
||||||
<div class:list={['flex', 'gap-6']}>
|
<div class:list={['flex', 'gap-6']}>
|
||||||
<Image
|
<Image
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const {
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class:list={['w-full', 'px-4', 'py-8', 'flex', 'flex-col', 'gap-4']}>
|
<div class:list={['w-full', 'flex', 'flex-col', 'gap-4']}>
|
||||||
<div class:list={['flex', 'justify-between']}>
|
<div class:list={['flex', 'justify-between']}>
|
||||||
<div class:list={['flex', 'gap-4', 'flex-col', 'sm:flex-row']}>
|
<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']} />
|
<Image src={image} alt={author} format="webp" class:list={['w-14', 'h-14', 'rounded-lg']} />
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,9 @@ export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||||
i18n: I18n;
|
i18n: I18n;
|
||||||
}
|
}
|
||||||
const { job, i18n, ...props } = Astro.props;
|
const { job, i18n, ...props } = Astro.props;
|
||||||
const WorkTimelineItem = 'div';
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<WorkTimelineItem class:list={['flex', 'flex-col', 'gap-2', 'md:gap-0', 'mb-4', props.class]}>
|
<div class:list={['flex', 'flex-col', 'gap-2', 'md:gap-0', props.class]}>
|
||||||
<div class:list={['flex', 'flex-row', 'justify-between', 'w-full']}>
|
<div class:list={['flex', 'flex-row', 'justify-between', 'w-full']}>
|
||||||
<div>
|
<div>
|
||||||
<Typography variant="item-title"
|
<Typography variant="item-title"
|
||||||
|
|
@ -67,4 +66,4 @@ const WorkTimelineItem = 'div';
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</WorkTimelineItem>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
---
|
---
|
||||||
|
import DividedList from '@/atoms/divided-list.astro';
|
||||||
import Divider from '@/atoms/divider.astro';
|
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 WorkTimelineItem from '@/organisms/work-timeline-item.astro';
|
import WorkTimelineItem from '@/organisms/work-timeline-item.astro';
|
||||||
import type { Section } from '@/types/data';
|
import type { Section } from '@/types/data';
|
||||||
import type { ExperienceSection, Job } from '@/types/experience-section';
|
import type { ExperienceSection, Job } from '@/types/experience-section';
|
||||||
import type { I18n } from '@/types/i18n';
|
import type { I18n } from '@/types/i18n';
|
||||||
|
import removeLast from '@/utils/remove-last';
|
||||||
|
|
||||||
export interface Props extends ExperienceSection {
|
export interface Props extends ExperienceSection {
|
||||||
jobs: Job[];
|
jobs: Job[];
|
||||||
|
|
@ -21,14 +22,8 @@ const {
|
||||||
const section: Section = 'experience';
|
const section: Section = 'experience';
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard section={section}
|
<SectionCard section={section} title={title}>
|
||||||
><Typography variant="section-title" id={`${section}-heading`}>{title}</Typography>
|
<DividedList>
|
||||||
{
|
{removeLast(jobs.flatMap((job) => [<WorkTimelineItem job={job} i18n={i18n} />, <Divider />]))}
|
||||||
jobs.map((value, id) => (
|
</DividedList>
|
||||||
<>
|
|
||||||
<WorkTimelineItem job={value} i18n={i18n} />
|
|
||||||
{id !== jobs.length - 1 && <Divider />}
|
|
||||||
</>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</SectionCard>
|
</SectionCard>
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,7 @@ const subsections = [booksSubsection, peopleSubsection, videosSubsection, medias
|
||||||
const section: Section = 'favorites';
|
const section: Section = 'favorites';
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard section={section}>
|
<SectionCard section={section} title={title}>
|
||||||
<Typography variant="section-title" id={`${section}-heading`}>{title}</Typography>
|
|
||||||
<div class:list={['flex', 'flex-col', 'gap-16']}>
|
<div class:list={['flex', 'flex-col', 'gap-16']}>
|
||||||
{
|
{
|
||||||
subsections.map(({ Component, data, name, columnsLayout, title: subsectionTitle }) => (
|
subsections.map(({ Component, data, name, columnsLayout, title: subsectionTitle }) => (
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
---
|
---
|
||||||
|
import DividedList from '@/atoms/divided-list.astro';
|
||||||
import Divider from '@/atoms/divider.astro';
|
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 ProjectTimelineItem from '@/organisms/project-timeline-item.astro';
|
import ProjectTimelineItem from '@/organisms/project-timeline-item.astro';
|
||||||
import type { Section } from '@/types/data';
|
import type { Section } from '@/types/data';
|
||||||
import type { I18n } from '@/types/i18n';
|
import type { I18n } from '@/types/i18n';
|
||||||
import type { PortfolioSection } from '@/types/portfolio-section';
|
import type { PortfolioSection } from '@/types/portfolio-section';
|
||||||
|
import removeLast from '@/utils/remove-last';
|
||||||
|
|
||||||
export interface Props extends PortfolioSection {
|
export interface Props extends PortfolioSection {
|
||||||
i18n: I18n;
|
i18n: I18n;
|
||||||
|
|
@ -20,14 +21,8 @@ const {
|
||||||
const section: Section = 'portfolio';
|
const section: Section = 'portfolio';
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard section={section}
|
<SectionCard section={section} title={title}>
|
||||||
><Typography variant="section-title" id={`${section}-heading`}>{title}</Typography>
|
<DividedList>
|
||||||
{
|
{removeLast(projects.flatMap((project) => [<ProjectTimelineItem project={project} i18n={i18n} />, <Divider />]))}
|
||||||
projects.map((project, index) => (
|
</DividedList>
|
||||||
<>
|
|
||||||
<ProjectTimelineItem project={project} i18n={i18n} />
|
|
||||||
{index !== projects.length - 1 && <Divider />}
|
|
||||||
</>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</SectionCard>
|
</SectionCard>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
---
|
---
|
||||||
import SectionCard from '@/atoms/section-card.astro';
|
import SectionCard from '@/atoms/section-card.astro';
|
||||||
import Typography from '@/atoms/typography.astro';
|
|
||||||
import SkillSubsection from '@/organisms/skill-subsection.astro';
|
import SkillSubsection from '@/organisms/skill-subsection.astro';
|
||||||
import type { Section } from '@/types/data';
|
import type { Section } from '@/types/data';
|
||||||
import type { SkillsSection } from '@/types/skills-section';
|
import type { SkillsSection } from '@/types/skills-section';
|
||||||
|
|
@ -15,8 +14,7 @@ const {
|
||||||
const section: Section = 'skills';
|
const section: Section = 'skills';
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard section={section}>
|
<SectionCard section={section} title={title}>
|
||||||
<Typography variant="section-title" id={`${section}-heading`}>{title}</Typography>
|
|
||||||
<div class:list={['flex', 'flex-col', 'gap-10']}>
|
<div class:list={['flex', 'flex-col', 'gap-10']}>
|
||||||
{skillSets.map((skillSet) => <SkillSubsection skillSet={skillSet} />)}
|
{skillSets.map((skillSet) => <SkillSubsection skillSet={skillSet} />)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
---
|
---
|
||||||
|
import DividedList from '@/atoms/divided-list.astro';
|
||||||
import Divider from '@/atoms/divider.astro';
|
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 Testimonial from '@/organisms/testimonial.astro';
|
||||||
import type { Section } from '@/types/data';
|
import type { Section } from '@/types/data';
|
||||||
import type { TestimonialsSection } from '@/types/testimonials-section';
|
import type { TestimonialsSection } from '@/types/testimonials-section';
|
||||||
|
import removeLast from '@/utils/remove-last';
|
||||||
|
|
||||||
export interface Props extends TestimonialsSection {}
|
export interface Props extends TestimonialsSection {}
|
||||||
|
|
||||||
|
|
@ -16,16 +17,8 @@ const {
|
||||||
const section: Section = 'testimonials';
|
const section: Section = 'testimonials';
|
||||||
---
|
---
|
||||||
|
|
||||||
<SectionCard section={section}>
|
<SectionCard section={section} title={title}>
|
||||||
<Typography variant="section-title" id={`${section}-heading`}>{title}</Typography>
|
<DividedList>
|
||||||
<div class:list={['flex', 'flex-col']}>
|
{removeLast(testimonials.flatMap((testimonial) => [<Testimonial testimonial={testimonial} />, <Divider />]))}
|
||||||
{
|
</DividedList>
|
||||||
testimonials.map((testimonial, index) => (
|
|
||||||
<>
|
|
||||||
<Testimonial testimonial={testimonial} />
|
|
||||||
{index !== testimonials.length - 1 && <Divider />}
|
|
||||||
</>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</SectionCard>
|
</SectionCard>
|
||||||
|
|
|
||||||
6
src/utils/remove-last.ts
Normal file
6
src/utils/remove-last.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* Get all elements of array except last one.
|
||||||
|
*/
|
||||||
|
const removeLast = <T>(arr: T[]): T[] => arr.slice(0, -1);
|
||||||
|
|
||||||
|
export default removeLast;
|
||||||
Loading…
Reference in a new issue