Skip to content

Commit 8e7eafe

Browse files
committed
refactor: update dependencies and improve project structure
- Updated dependencies in package.json for better performance and compatibility. - Refactored ProjectList component to use MySlider for improved slider functionality. - Simplified SkillList component rendering logic for better performance. - Added global CSS import in BaseLayout for consistent styling. - Enhanced Footer and Header components with MyLink for better link management. - Expanded skill set in index.astro to include additional technologies. - Removed obsolete tailwind.config.mjs and migrated styles to global.css. - Introduced MyLink and MySlider components for reusable link and slider functionality.
1 parent d3d3907 commit 8e7eafe

13 files changed

Lines changed: 5310 additions & 6561 deletions

astro.config.mjs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import { defineConfig } from "astro/config";
22

3-
import tailwind from "@astrojs/tailwind";
3+
import tailwindcss from "@tailwindcss/vite";
44

55
import icon from "astro-icon";
66

77
// https://astro.build/config
88
export default defineConfig({
9-
site: 'https://klpod221.com',
10-
integrations: [
11-
tailwind(),
12-
icon({
13-
iconDir: {
14-
mdi: "*", // Include all icons from the Material Design Icons set
15-
tabler: "*", // Include all icons from the Tabler Icons set
16-
"fa6-brands": "*", // Include all icons from the Font Awesome 6 Brands set
17-
"simple-icons": "*", // Include all icons from the Simple Icons set
18-
},
19-
}),
20-
],
9+
site: "https://klpod221.com",
10+
integrations: [icon()],
11+
vite: {
12+
plugins: [
13+
tailwindcss({
14+
config: "./tailwind.config.mjs",
15+
}),
16+
],
17+
},
2118
});

package-lock.json

Lines changed: 4902 additions & 6346 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@
1010
"astro": "astro"
1111
},
1212
"dependencies": {
13-
"@astrojs/tailwind": "^5.1.2",
14-
"astro": "^4.16.13",
15-
"astro-icon": "^1.1.2",
16-
"swiper": "^11.1.15",
17-
"tailwindcss": "^3.4.15"
13+
"@tailwindcss/vite": "^4.1.4",
14+
"astro": "^5.6.2",
15+
"astro-icon": "^1.1.5",
16+
"tailwindcss": "^4.1.4"
1817
},
1918
"devDependencies": {
20-
"@iconify-json/fa6-brands": "^1.2.2",
21-
"@iconify-json/mdi": "^1.2.1",
22-
"@iconify-json/simple-icons": "^1.2.12",
23-
"@iconify-json/tabler": "^1.2.8"
19+
"@iconify-json/fa6-brands": "^1.2.5",
20+
"@iconify-json/mdi": "^1.2.3",
21+
"@iconify-json/simple-icons": "^1.2.32",
22+
"@iconify-json/tabler": "^1.2.17"
2423
}
2524
}

src/components/MyLink.astro

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
const { href, text, className } = Astro.props;
3+
---
4+
5+
<a href={href} class={`relative group ${className}`}>
6+
{text}
7+
<span
8+
class="absolute bottom-0 left-0 w-full h-0.5 bg-primary origin-left transform scale-x-0 transition-transform duration-300 ease-out group-hover:scale-x-100"
9+
></span>
10+
</a>

src/components/MySlider.astro

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
---
2+
import { Icon } from "astro-icon/components";
3+
4+
interface Props {
5+
items: any[];
6+
className?: string;
7+
showArrows?: boolean;
8+
showPagination?: boolean;
9+
autoplay?: boolean;
10+
autoplayDelay?: number;
11+
}
12+
13+
const {
14+
items,
15+
className = "",
16+
showArrows = true,
17+
showPagination = true,
18+
autoplay = true,
19+
autoplayDelay = 5000
20+
} = Astro.props;
21+
---
22+
23+
<div class={`slider relative w-full overflow-hidden ${className}`}>
24+
<div class="slider-wrapper flex w-full transition-transform duration-500 ease-in-out">
25+
<slot />
26+
</div>
27+
28+
{showPagination && (
29+
<div class="pagination flex justify-center mt-4 gap-2"></div>
30+
)}
31+
32+
{showArrows && (
33+
<>
34+
<button
35+
class="prev-button hidden sm:flex sm:hover:flex items-center justify-center w-10 h-10 absolute top-1/2 left-2 -translate-y-1/2 z-10 cursor-pointer bg-background/50 backdrop-blur-sm rounded-full border border-tertiary hover:bg-tertiary transition-colors duration-300 max-sm:opacity-70"
36+
aria-label="Previous slide"
37+
>
38+
<Icon name="mdi:chevron-left" class="w-6 h-6" />
39+
</button>
40+
41+
<button
42+
class="next-button hidden sm:flex sm:hover:flex items-center justify-center w-10 h-10 absolute top-1/2 right-2 -translate-y-1/2 z-10 cursor-pointer bg-background/50 backdrop-blur-sm rounded-full border border-tertiary hover:bg-tertiary transition-colors duration-300 max-sm:opacity-70"
43+
aria-label="Next slide"
44+
>
45+
<Icon name="mdi:chevron-right" class="w-6 h-6" />
46+
</button>
47+
</>
48+
)}
49+
</div>
50+
51+
<script define:vars={{ autoplay, autoplayDelay }}>
52+
document.addEventListener("DOMContentLoaded", () => {
53+
const slider = document.querySelector(".slider");
54+
if (!slider) return;
55+
56+
const sliderWrapper = slider.querySelector(".slider-wrapper");
57+
const slides = slider.querySelectorAll(".slide");
58+
const prevButton = slider.querySelector(".prev-button");
59+
const nextButton = slider.querySelector(".next-button");
60+
const paginationContainer = slider.querySelector(".pagination");
61+
62+
if (!sliderWrapper || !slides.length) return;
63+
64+
// Type assertion for sliderWrapper to access style property
65+
const sliderWrapperElement = sliderWrapper;
66+
67+
let currentIndex = 0;
68+
const totalSlides = slides.length;
69+
let autoplayTimer = null;
70+
let isTransitioning = false;
71+
let touchStartX = 0;
72+
let touchEndX = 0;
73+
74+
// Create pagination bullets if pagination container exists
75+
if (paginationContainer) {
76+
for (let i = 0; i < totalSlides; i++) {
77+
const bullet = document.createElement("button");
78+
bullet.classList.add(
79+
"pagination-bullet",
80+
"w-2",
81+
"h-2",
82+
"rounded-full",
83+
"bg-tertiary",
84+
"hover:bg-primary",
85+
"transition-all",
86+
"duration-300"
87+
);
88+
bullet.setAttribute("aria-label", `Go to slide ${i + 1}`);
89+
bullet.dataset.index = i.toString();
90+
paginationContainer.appendChild(bullet);
91+
}
92+
}
93+
94+
const paginationBullets = slider.querySelectorAll(".pagination-bullet");
95+
96+
// Set initial active bullet
97+
if (paginationBullets.length > 0) {
98+
paginationBullets[0].classList.add("!bg-primary", "w-4");
99+
}
100+
101+
// Function to go to a specific slide
102+
const goToSlide = (index, animate = true) => {
103+
if (isTransitioning) return;
104+
105+
// Handle circular navigation
106+
if (index < 0) index = totalSlides - 1;
107+
if (index >= totalSlides) index = 0;
108+
109+
currentIndex = index;
110+
111+
// Calculate transform value
112+
const transformValue = `translateX(-${currentIndex * 100}%)`;
113+
114+
if (!animate) {
115+
sliderWrapperElement.style.transition = "none";
116+
sliderWrapperElement.style.transform = transformValue;
117+
// Force reflow
118+
sliderWrapperElement.offsetHeight;
119+
sliderWrapperElement.style.transition = "transform 500ms ease-in-out";
120+
} else {
121+
isTransitioning = true;
122+
sliderWrapperElement.style.transform = transformValue;
123+
124+
// Reset transitioning state after animation completes
125+
setTimeout(() => {
126+
isTransitioning = false;
127+
}, 500);
128+
}
129+
130+
// Update pagination bullets
131+
paginationBullets.forEach((bullet, i) => {
132+
if (i === currentIndex) {
133+
bullet.classList.add("!bg-primary", "w-4");
134+
} else {
135+
bullet.classList.remove("!bg-primary", "w-4");
136+
}
137+
});
138+
139+
// Reset autoplay timer if autoplay is enabled
140+
if (autoplayTimer) {
141+
clearTimeout(autoplayTimer);
142+
if (autoplay) {
143+
startAutoplay();
144+
}
145+
}
146+
};
147+
148+
// Initialize autoplay if enabled
149+
const startAutoplay = () => {
150+
if (autoplay) {
151+
autoplayTimer = setTimeout(() => {
152+
goToSlide(currentIndex + 1);
153+
}, autoplayDelay);
154+
}
155+
};
156+
157+
// Add event listeners for pagination bullets
158+
paginationBullets.forEach((bullet) => {
159+
bullet.addEventListener("click", () => {
160+
const index = parseInt(bullet.dataset.index || "0");
161+
goToSlide(index);
162+
});
163+
});
164+
165+
// Navigation buttons
166+
if (prevButton) {
167+
prevButton.addEventListener("click", () => {
168+
goToSlide(currentIndex - 1);
169+
});
170+
}
171+
172+
if (nextButton) {
173+
nextButton.addEventListener("click", () => {
174+
goToSlide(currentIndex + 1);
175+
});
176+
}
177+
178+
// Touch swiping support
179+
sliderWrapperElement.addEventListener(
180+
"touchstart",
181+
(e) => {
182+
touchStartX = e.changedTouches[0].screenX;
183+
184+
// Pause autoplay during touch
185+
if (autoplayTimer) {
186+
clearTimeout(autoplayTimer);
187+
}
188+
},
189+
{ passive: true }
190+
);
191+
192+
sliderWrapperElement.addEventListener(
193+
"touchend",
194+
(e) => {
195+
touchEndX = e.changedTouches[0].screenX;
196+
handleSwipe();
197+
198+
// Resume autoplay if enabled
199+
if (autoplay) {
200+
startAutoplay();
201+
}
202+
},
203+
{ passive: true }
204+
);
205+
206+
const handleSwipe = () => {
207+
const swipeThreshold = 50; // Minimum distance to register a swipe
208+
209+
if (touchStartX - touchEndX > swipeThreshold) {
210+
// Swiped left, go to next slide
211+
goToSlide(currentIndex + 1);
212+
} else if (touchEndX - touchStartX > swipeThreshold) {
213+
// Swiped right, go to previous slide
214+
goToSlide(currentIndex - 1);
215+
}
216+
};
217+
218+
// Add keyboard navigation
219+
document.addEventListener("keydown", (e) => {
220+
if (e.key === "ArrowLeft") {
221+
goToSlide(currentIndex - 1);
222+
} else if (e.key === "ArrowRight") {
223+
goToSlide(currentIndex + 1);
224+
}
225+
});
226+
227+
// Start autoplay if enabled
228+
if (autoplay) {
229+
startAutoplay();
230+
}
231+
232+
// Pause autoplay when hovering over slider
233+
slider.addEventListener("mouseenter", () => {
234+
if (autoplayTimer && autoplay) {
235+
clearTimeout(autoplayTimer);
236+
}
237+
});
238+
239+
// Resume autoplay when mouse leaves
240+
slider.addEventListener("mouseleave", () => {
241+
if (autoplay) {
242+
startAutoplay();
243+
}
244+
});
245+
246+
// Handle visibility change to pause/resume autoplay
247+
document.addEventListener("visibilitychange", () => {
248+
if (document.hidden) {
249+
// Page is hidden, pause autoplay
250+
if (autoplayTimer) {
251+
clearTimeout(autoplayTimer);
252+
}
253+
} else if (autoplay) {
254+
// Page is visible, resume autoplay if enabled
255+
startAutoplay();
256+
}
257+
});
258+
});
259+
</script>

0 commit comments

Comments
 (0)