Skip to content

Commit c11fcf2

Browse files
authored
feat: updated skills section
feat: updated skills section
2 parents d518905 + b65773e commit c11fcf2

File tree

13 files changed

+420
-50
lines changed

13 files changed

+420
-50
lines changed

astro.config.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ export default defineConfig({
1414
markdown: {
1515
syntaxHighlight: "shiki",
1616
shikiConfig: {
17-
theme: "nord",
18-
wrap: false
17+
themes: {
18+
light: "github-light",
19+
dark: "github-dark"
20+
},
21+
wrap: true
1922
}
2023
},
2124
//output: 'server',

src/components/CompanyLogo.astro

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ type Props = HTMLAttributes<"img"> & {
77
darkLogo?: string;
88
website?: string;
99
description?: string;
10+
categories?: string[];
1011
};
1112
12-
const { name, logo, darkLogo, website, description, ...props } = Astro.props;
13+
const { name, logo, darkLogo, website, description, categories, ...props } = Astro.props;
1314
---
1415

1516
{website ? (
1617
<a
1718
href={website}
1819
target="_blank"
1920
rel="noopener noreferrer"
20-
class="flex items-center justify-center p-2"
21+
class="company-logo flex items-center justify-center p-2 transition-all duration-300"
22+
data-categories={categories?.join(',')}
2123
title={description ? `${name} - ${description}` : name}
2224
>
2325
{darkLogo ? (
@@ -46,7 +48,8 @@ const { name, logo, darkLogo, website, description, ...props } = Astro.props;
4648
</a>
4749
) : (
4850
<div
49-
class="flex items-center justify-center p-2"
51+
class="company-logo flex items-center justify-center p-2 transition-all duration-300"
52+
data-categories={categories?.join(',')}
5053
title={description ? `${name} - ${description}` : name}
5154
>
5255
{darkLogo ? (
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
---
2+
import skills from '@/data/techStack';
3+
---
4+
5+
<div class="tech-stack-container">
6+
<div class="radar-section">
7+
<canvas id="radarChart" width="500" height="500"></canvas>
8+
</div>
9+
<div class="skills-legend">
10+
{skills.map((skill) => (
11+
<div class="skill-item">
12+
<h4 class="skill-name">{skill.name}</h4>
13+
<p class="skill-list">{skill.subSkills.join(' / ')}</p>
14+
</div>
15+
))}
16+
</div>
17+
</div>
18+
19+
<script>
20+
import skills from '@/data/techStack';
21+
22+
const canvas = document.getElementById('radarChart') as HTMLCanvasElement;
23+
const ctx = canvas.getContext('2d');
24+
25+
if (ctx) {
26+
const centerX = canvas.width / 2;
27+
const centerY = canvas.height / 2;
28+
const radius = 180;
29+
const levels = 5;
30+
const angleStep = (Math.PI * 2) / skills.length;
31+
32+
// Check if dark mode
33+
const isDark = document.documentElement.classList.contains('dark');
34+
const gridColor = isDark ? '#404040' : '#e5e5e5';
35+
const textColor = isDark ? '#a3a3a3' : '#525252';
36+
const fillColor = isDark ? 'rgba(250, 204, 21, 0.12)' : 'rgba(250, 204, 21, 0.15)';
37+
const strokeColor = isDark ? '#fbbf24' : '#f59e0b';
38+
39+
// Draw grid levels
40+
ctx.strokeStyle = gridColor;
41+
ctx.lineWidth = 1;
42+
43+
for (let i = 1; i <= levels; i++) {
44+
ctx.beginPath();
45+
const levelRadius = (radius / levels) * i;
46+
47+
for (let j = 0; j <= skills.length; j++) {
48+
const angle = angleStep * j - Math.PI / 2;
49+
const x = centerX + Math.cos(angle) * levelRadius;
50+
const y = centerY + Math.sin(angle) * levelRadius;
51+
52+
if (j === 0) {
53+
ctx.moveTo(x, y);
54+
} else {
55+
ctx.lineTo(x, y);
56+
}
57+
}
58+
ctx.closePath();
59+
ctx.stroke();
60+
}
61+
62+
// Draw axes
63+
ctx.strokeStyle = gridColor;
64+
ctx.lineWidth = 1;
65+
66+
skills.forEach((_, index) => {
67+
const angle = angleStep * index - Math.PI / 2;
68+
const x = centerX + Math.cos(angle) * radius;
69+
const y = centerY + Math.sin(angle) * radius;
70+
71+
ctx.beginPath();
72+
ctx.moveTo(centerX, centerY);
73+
ctx.lineTo(x, y);
74+
ctx.stroke();
75+
});
76+
77+
// Draw data polygon
78+
ctx.beginPath();
79+
skills.forEach((skill, index) => {
80+
const angle = angleStep * index - Math.PI / 2;
81+
const value = (skill.value / 100) * radius;
82+
const x = centerX + Math.cos(angle) * value;
83+
const y = centerY + Math.sin(angle) * value;
84+
85+
if (index === 0) {
86+
ctx.moveTo(x, y);
87+
} else {
88+
ctx.lineTo(x, y);
89+
}
90+
});
91+
ctx.closePath();
92+
ctx.fillStyle = fillColor;
93+
ctx.fill();
94+
ctx.strokeStyle = strokeColor;
95+
ctx.lineWidth = 2.5;
96+
ctx.stroke();
97+
98+
// Draw data points
99+
skills.forEach((skill, index) => {
100+
const angle = angleStep * index - Math.PI / 2;
101+
const value = (skill.value / 100) * radius;
102+
const x = centerX + Math.cos(angle) * value;
103+
const y = centerY + Math.sin(angle) * value;
104+
105+
ctx.beginPath();
106+
ctx.arc(x, y, 6, 0, Math.PI * 2);
107+
ctx.fillStyle = strokeColor;
108+
ctx.fill();
109+
});
110+
111+
// Draw labels
112+
ctx.fillStyle = textColor;
113+
ctx.font = 'bold 15px system-ui, -apple-system, sans-serif';
114+
ctx.textAlign = 'center';
115+
ctx.textBaseline = 'middle';
116+
117+
skills.forEach((skill, index) => {
118+
const angle = angleStep * index - Math.PI / 2;
119+
const labelRadius = radius + 35;
120+
const x = centerX + Math.cos(angle) * labelRadius;
121+
const y = centerY + Math.sin(angle) * labelRadius;
122+
123+
ctx.fillText(skill.name, x, y);
124+
});
125+
}
126+
127+
// Redraw on theme change
128+
const observer = new MutationObserver(() => {
129+
location.reload();
130+
});
131+
132+
observer.observe(document.documentElement, {
133+
attributes: true,
134+
attributeFilter: ['class']
135+
});
136+
</script>
137+
138+
<style>
139+
.tech-stack-container {
140+
display: grid;
141+
grid-template-columns: 1fr 1fr;
142+
gap: 3rem;
143+
align-items: center;
144+
padding: 2rem 0;
145+
}
146+
147+
.radar-section {
148+
display: flex;
149+
justify-content: center;
150+
align-items: center;
151+
}
152+
153+
#radarChart {
154+
max-width: 100%;
155+
height: auto;
156+
}
157+
158+
.skills-legend {
159+
display: flex;
160+
flex-direction: column;
161+
gap: 2rem;
162+
}
163+
164+
.skill-item {
165+
display: flex;
166+
flex-direction: column;
167+
gap: 0.3rem;
168+
}
169+
170+
.skill-name {
171+
font-size: 0.9rem;
172+
font-weight: 700;
173+
color: #171717;
174+
}
175+
176+
:global(.dark) .skill-name {
177+
color: #f5f5f5;
178+
}
179+
180+
.skill-list {
181+
font-size: 0.875rem;
182+
color: #737373;
183+
line-height: 1.5;
184+
}
185+
186+
:global(.dark) .skill-list {
187+
color: #a3a3a3;
188+
}
189+
190+
@media (max-width: 768px) {
191+
.tech-stack-container {
192+
grid-template-columns: 1fr;
193+
gap: 2rem;
194+
}
195+
196+
.skills-legend {
197+
gap: 1.5rem;
198+
}
199+
}
200+
</style>

src/components/shared/Link.astro

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ type Props = HTMLAttributes<"a"> & {
66
isUnderline?: boolean;
77
};
88
9-
const { label, isUnderline, ...props } = Astro.props;
9+
const { label, isUnderline, class: customClass, ...props } = Astro.props;
1010
---
1111

1212
<a
1313
href={props.href}
14-
class:list={{
15-
["hover:text-neutral-800 dark:hover:text-neutral-100 cursor-pointer"]: true,
16-
["underline decoration-dashed underline-offset-8"]: isUnderline,
17-
}}
14+
class:list={[
15+
"hover:text-neutral-800 dark:hover:text-neutral-100 cursor-pointer",
16+
{ "underline decoration-dashed underline-offset-8": isUnderline },
17+
customClass
18+
]}
1819
{...props}
1920
rel="noreferrer"
2021
target="_blank"

src/data/companies.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,85 +4,98 @@ type Company = {
44
darkLogo?: string;
55
website?: string;
66
description?: string;
7+
categories?: string[];
78
};
89

910
const companies: Company[] = [
1011
{
1112
name: "Fountane",
1213
logo: "/img/companies/fountane.png",
1314
website: "https://www.fountane.com/",
14-
description: "Software Engineer"
15+
description: "Software Engineer",
16+
categories: ["fullstack", "devops"]
1517
},
1618
{
1719
name: "Ortelius",
1820
logo: "/img/companies/ortelius-logo.svg",
1921
website: "https://ortelius.io/",
20-
description: "Full Stack Developer"
22+
description: "Full Stack Developer",
23+
categories: ["fullstack", "devops"]
2124
},
2225
{
2326
name: "Build Club",
2427
logo: "/img/companies/build-club.png",
2528
website: "https://www.buildclub.ai/",
26-
description: "Frontend Developer"
29+
description: "Frontend Developer",
30+
categories: ["ai", "fullstack"]
2731
},
2832
{
2933
name: "rechat",
3034
logo: "/img/companies/rechat.png",
3135
website: "https://www.rechat.vc/",
32-
description: "React Developer"
36+
description: "React Developer",
37+
categories: ["ai", "fullstack","devops"]
3338
},
3439
{
3540
name: "OpenSSF",
3641
logo: "/img/companies/openssf.avif",
3742
darkLogo: "/img/companies/openssf-light.svg",
3843
website: "https://openssf.org/",
39-
description: "Open Source Developer"
44+
description: "Open Source Developer",
45+
categories: ["devops"]
4046
},
4147
{
4248
name: "Cd Foundation",
4349
logo: "/img/companies/cdf.svg",
4450
darkLogo: "/img/companies/cdf-white.svg",
4551
website: "https://cd.foundation/",
46-
description: "Open Source Developer"
52+
description: "Open Source Developer",
53+
categories: ["devops"]
4754
},
4855
{
4956
name: "Linux Foundation",
5057
logo: "/img/companies/linux-foundation.png",
5158
darkLogo: "/img/companies/linux-foundation-light.png",
5259
website: "https://www.linuxfoundation.org/",
53-
description: "Open Source Developer"
60+
description: "Open Source Developer",
61+
categories: ["devops"]
5462
},
5563
{
5664
name: "ComplyIQ",
5765
logo: "/img/companies/complyiq.webp",
5866
darkLogo: "/img/companies/complyiq-light.png",
5967
website: "https://www.complyiq.io/",
60-
description: "DevOps Engineer"
68+
description: "DevOps Engineer",
69+
categories: ["devops"]
6170
},
6271
{
6372
name: "ASI",
6473
logo: "/img/companies/asi.png",
6574
website: "https://anandsystems.com/",
66-
description: "Automation Engineer"
75+
description: "Automation Engineer",
76+
categories: ["devops","fullstack"]
6777
},
6878
{
6979
name: "PMC",
7080
logo: "/img/companies/pmc.jpg",
7181
darkLogo: "/img/companies/pmc.webp",
7282
website: "https://parkingmgt.com/",
73-
description: "Automation Engineer"
83+
description: "Automation Engineer",
84+
categories: ["fullstack"]
7485
},
7586
{
7687
name: "Profilkep",
7788
logo: "/img/companies/profilkep.png",
7889
darkLogo: "/img/companies/profilkep-light.png",
7990
website: "https://profilkep.hu/",
80-
description: "Full Stack Developer"
91+
description: "Full Stack Developer",
92+
categories: ["fullstack","ai"]
8193
},
8294
{
8395
name: "ViralPost",
8496
logo: "/img/companies/viralpost.png",
85-
description: "Full Stack Developer"
97+
description: "Full Stack Developer",
98+
categories: ["fullstack", "ai"]
8699
}
87100
];
88101

src/data/presentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const presentation: Presentation = {
1616
title: "Hi, I’m Arvind 👋",
1717
// profile: "/profile.webp",
1818
description:
19-
"Building software is both my *passion* and my *profession*. I am a *Full Stack software crafter* with *3 years of industry experience* specialised in building and scaling *cloud-native web applications*. I have a solid background in producing software with state-of-the-art technologies. I am a big fan of AI tools, with the ultimate goal of creating software that makes customers happy. In addition, I am a contributor and active member of open-source communities. I have demonstrated a strong ability to create developer-focused content that empoweres engineers to write better softawre and grow their careers. \n\n If you need any assistance or have any questions, feel free to reach me.",
19+
"I specialise in 3 things: Full stack development, DevOps & AI Prototyping",
2020
socials: [
2121
{
2222
label: "X",

0 commit comments

Comments
 (0)