Built Portfolio Page -3 (Projects Component)

Steps:

  1. Add project component

Add projects component

add src/components/Projects.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import React from 'react'
import SectionHeading from './Section-heading'
import { projectsData } from '@/libs/data'
import Image from 'next/image';

export default function Projects() {
return (
<section>
<SectionHeading>
My Projects
</SectionHeading>
<div>
{projectsData.map((project, index)=>(
<React.Fragment key={index}>
<Project {...project} />
</React.Fragment>
))}
</div>
</section>
)
}

type ProjectProps = (typeof projectsData)[number];

function Project({title,description,tags,imageUrl } :
ProjectProps) {
return(
<section className="group bg-gray-100 max-w-[42rem] border border-black/5
overflow-hidden sm:pr-8 relative sm:h-[20rem] mb-3 sm:mb-8 last:mb-0 even:pl-8
hover:bg-gray-200 transition">
<div className='py-4 pb-7 px-5 sm:pl-10 sm:pr-2 sm:pt-10 sm:max-w-[50%]
flex flex-col h-full group-even:ml-[18rem]'>
<h3 className='text-2xl font-semibold'>{title}</h3>
<p className='mt-2 leading-relaxed text-gray-700'>{description}</p>
<ul className='flex flex-wrap mt-4 gap-2 sm:mt-auto'>
{tags.map((tag,index) => (
<li className='bg-black/[0.7] px-3 py-1 text-[0.7rem] upppercase
tracking-wider text-white rounded-full'
key={index}
>
{tag}
</li>
))}
</ul>
</div>
<Image
src={imageUrl} alt="Project I worked on" quality={95}
className='absolute top-8 -right-40 w-[28.25rem] rounded-t-lg shadow-2xl
transition
group-hover:scale-[1.05]
group-hover:-translate-x-3
group-hover:translate-y-3
group-hover:-rotate-2

group-even:group-hover:translate-x-3
group-even:group-hover:-translate-y-3
group-even:group-hover:rotate-2
group-even:right-[inital] group-even:-left-40'
/>
</section>
)
}

Memo:

  1. Extract same node to component
  2. type ProjectProps = (typeof projectsData)[number]; 代表 ProjectProps 是 projectsData 数组项目元素类型
  3. group-even:group-hover:translate-x-3 用group-even 和 translate 来实现隔行样式变化和动画

projectsData.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...

export const projectsData = [
{
title: "CorpComment",
description:
"I worked as a full-stack developer on this startup project for 2 years. Users can give public feedback to companies.",
tags: ["React", "Next.js", "MongoDB", "Tailwind", "Prisma"],
imageUrl: corpcommentImg,
},
{
title: "rmtDev",
description:
"Job board for remote developer jobs. I was the front-end developer. It has features like filtering, sorting and pagination.",
tags: ["React", "TypeScript", "Next.js", "Tailwind", "Redux"],
imageUrl: rmtdevImg,
},
{
title: "Word Analytics",
description:
"A public web app for quick analytics on text. It shows word count, character count and social media post limits.",
tags: ["React", "Next.js", "SQL", "Tailwind", "Framer"],
imageUrl: wordanalyticsImg,
},
] as const;
...

add src/components/Section-heading.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react'

type SectionHeadingProps = {
children: React.ReactNode;
}

export default function SectionHeading(
{ children } : SectionHeadingProps) {
return (
<h2 className='text-3xl font-medium capitalize mb-8 text-center'>
{children}
</h2>
)
}

Demo

Demo Page

请我喝杯咖啡吧~

支付宝
微信