Skip to content

Commit f4b9b4b

Browse files
feat: abstract the Tabs component for optimization and transformed both tab interactives
1 parent 0f02d51 commit f4b9b4b

File tree

4 files changed

+58
-64
lines changed

4 files changed

+58
-64
lines changed

src/components/ExperienceTabs.jsx

+7-30
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,18 @@ import { useState } from "react";
22
import { EXPERIENCE_TABS, TAB_VARIANTS } from "../utils/constants";
33
import { motion, AnimatePresence } from "motion/react";
44
import Timeline from "./Timeline";
5-
import { spring } from "motion";
5+
import Tabs from "./Tabs";
66

77
const ExperienceTabs = () => {
88
const [activeTab, setActiveTab] = useState(EXPERIENCE_TABS[1]?.tabName);
99
return (
1010
<div className="container mt-10 flex-col items-center p-2">
11-
<div className="flex items-center justify-center gap-20">
12-
{EXPERIENCE_TABS.map(({ tabName, tabIcon: Icon }) => (
13-
<button
14-
key={tabName}
15-
onClick={() => setActiveTab(tabName)}
16-
className={`${
17-
activeTab === tabName
18-
? "text-white dark:!text-gray-900"
19-
: "hover:opacity-70"
20-
} relative flex items-center justify-center rounded-full px-4 py-2 font-medium text-dark-blue duration-300 md:text-lg dark:text-gray-100`}
21-
>
22-
{activeTab === tabName && (
23-
<motion.div
24-
layoutId="active-pill"
25-
className="absolute inset-0 bg-light-blue dark:bg-custom-yellow"
26-
style={{ borderRadius: 9999 }}
27-
transition={{ type: spring, duration: 0.6 }}
28-
/>
29-
)}
30-
31-
<span className="relative z-10 flex gap-3">
32-
<Icon className="text-2xl" />
33-
{tabName}
34-
</span>
35-
</button>
36-
))}
37-
</div>
38-
39-
<div className="h-full w-full md:mt-2">
11+
<Tabs
12+
tabs={EXPERIENCE_TABS}
13+
activeTab={activeTab}
14+
setActiveTab={setActiveTab}
15+
/>
16+
<div className="mx-auto h-full max-w-screen-lg">
4017
<AnimatePresence mode="wait">
4118
<motion.div
4219
key={activeTab}

src/components/SkillTabs.jsx

+8-26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useState } from "react";
22
import { motion, AnimatePresence } from "motion/react";
33
import { SKILL_TABS, ALL_SKILLS, TAB_VARIANTS } from "../utils/constants";
44
import SkillBar from "./SkillBar";
5+
import Tabs from "./Tabs";
56

67
const SkillTabs = () => {
78
const [activeTab, setActiveTab] = useState(SKILL_TABS[1]?.tabName);
@@ -10,33 +11,14 @@ const SkillTabs = () => {
1011
);
1112

1213
return (
13-
<div className="mt-10 flex h-full w-1/2 flex-col items-center justify-center p-2 md:w-3/4 lg:w-4/5">
14-
<div className="mb-5 flex h-20 items-center justify-center gap-5 md:gap-10">
15-
{SKILL_TABS.map(({ tabName, tabIcon: Icon }) => (
16-
<button
17-
key={tabName}
18-
onClick={() => setActiveTab(tabName)}
19-
className={`relative flex flex-col items-center justify-center gap-2 truncate p-2 pb-2 font-medium leading-5 md:text-lg md:leading-7 ${
20-
activeTab === tabName
21-
? "text-custom-violet dark:text-custom-yellow"
22-
: "text-gray-500 dark:text-gray-100"
23-
}`}
24-
>
25-
<Icon
26-
className={`text-2xl md:text-3xl ${activeTab === tabName ? "text-light-blue" : ""}`}
27-
/>
28-
{tabName}
29-
{activeTab === tabName && (
30-
<motion.div
31-
layoutId="underline"
32-
className="absolute bottom-0 left-0 right-0 h-0.5 rounded bg-light-blue"
33-
/>
34-
)}
35-
</button>
36-
))}
37-
</div>
14+
<div className="container mt-10 flex-col items-center justify-center p-2">
15+
<Tabs
16+
tabs={SKILL_TABS}
17+
activeTab={activeTab}
18+
setActiveTab={setActiveTab}
19+
/>
3820

39-
<div className="h-full w-[17rem] sm:w-96 md:mt-2">
21+
<div className="mx-auto h-full w-full max-w-screen-xs">
4022
<AnimatePresence mode="wait">
4123
<motion.div
4224
key={activeTab}

src/components/Tabs.jsx

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { motion } from "motion/react";
2+
3+
const Tabs = ({ tabs, activeTab, setActiveTab }) => {
4+
return (
5+
<div className="mx-auto mb-10 flex max-w-screen-sm items-center justify-between">
6+
{tabs.map(({ tabName, tabIcon: Icon }) => (
7+
<button
8+
key={tabName}
9+
onClick={() => setActiveTab(tabName)}
10+
className={`${
11+
activeTab === tabName
12+
? "text-white dark:!text-gray-900"
13+
: "hover:opacity-70"
14+
} relative flex items-center justify-center rounded-full px-4 py-2 font-medium text-dark-blue duration-300 md:text-lg dark:text-gray-100`}
15+
>
16+
{activeTab === tabName && (
17+
<motion.div
18+
layoutId="active-pill"
19+
className="absolute inset-0 bg-light-blue dark:bg-custom-yellow"
20+
style={{ borderRadius: 9999 }}
21+
transition={{ type: "spring", duration: 0.6 }}
22+
/>
23+
)}
24+
25+
<span className="relative z-10 flex flex-wrap items-center justify-center gap-2 sm:gap-3">
26+
<Icon className="text-2xl" />
27+
{tabName}
28+
</span>
29+
</button>
30+
))}
31+
</div>
32+
);
33+
};
34+
35+
export default Tabs;

src/utils/constants.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -123,49 +123,49 @@ export const ALL_SKILLS = [
123123
styles: "bg-[#08D9FF]",
124124
icon: FaReact,
125125
percentage: 80,
126-
category: "Libraries & Frameworks",
126+
category: "Frameworks",
127127
},
128128
{
129129
logoName: "Tailwind CSS",
130130
styles: "bg-[#38BDF8]",
131131
icon: RiTailwindCssFill,
132132
percentage: 97,
133-
category: "Libraries & Frameworks",
133+
category: "Frameworks",
134134
},
135135
{
136136
logoName: "Node.js",
137137
styles: "bg-[#5FAE4B]",
138138
icon: IoLogoNodejs,
139139
percentage: 60,
140-
category: "Libraries & Frameworks",
140+
category: "Frameworks",
141141
},
142142
{
143143
logoName: "Redux",
144144
styles: "bg-[#7A50BE]",
145145
icon: SiRedux,
146146
percentage: 60,
147-
category: "Libraries & Frameworks",
147+
category: "Frameworks",
148148
},
149149
{
150150
logoName: "Babel",
151151
styles: "bg-[#F5DF63]",
152152
icon: SiBabel,
153153
percentage: 70,
154-
category: "Libraries & Frameworks",
154+
category: "Frameworks",
155155
},
156156
{
157157
logoName: "Webpack",
158158
styles: "bg-[#92D6FA]",
159159
icon: SiWebpack,
160160
percentage: 70,
161-
category: "Libraries & Frameworks",
161+
category: "Frameworks",
162162
},
163163
{
164164
logoName: "Vite",
165165
styles: "bg-[#9F61FC]",
166166
icon: SiVite,
167167
percentage: 86,
168-
category: "Libraries & Frameworks",
168+
category: "Frameworks",
169169
},
170170
{
171171
logoName: "GitHub",
@@ -220,7 +220,7 @@ export const ALL_SKILLS = [
220220

221221
export const SKILL_TABS = [
222222
{ tabName: "languages", tabIcon: AiOutlineCode },
223-
{ tabName: "Libraries & Frameworks", tabIcon: GoStack },
223+
{ tabName: "Frameworks", tabIcon: GoStack },
224224
{ tabName: "Tools", tabIcon: AiOutlineTool },
225225
];
226226

0 commit comments

Comments
 (0)