Skip to content

Commit ed18b9d

Browse files
committed
feat: Implement interactive spotlight effect on cards and list borders using mouse tracking.
1 parent c8f5d43 commit ed18b9d

6 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/components/MyWork.astro

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,13 @@ const projects = [
8484
projects.map((project, i) => (
8585
<li class="h-full">
8686
<div
87-
class={`p-4 h-full relative border hover:border-zinc-500 transition-all duration-300 rounded-xl border-zinc-700 bg-slate-900/20 backdrop-blur-sm`}
87+
class={`p-4 h-full relative border border-zinc-700 bg-slate-900/20 backdrop-blur-sm rounded-xl overflow-hidden group`}
88+
data-spotlight
8889
>
90+
<div
91+
class="absolute inset-0 -z-10 rounded-xl border border-zinc-500 transition-opacity duration-300 pointer-events-none"
92+
style="mask-image: radial-gradient(200px circle at var(--x) var(--y), black, transparent);"
93+
/>
8994
{project.image && (
9095
<Image
9196
class="absolute right-3 top-3 rounded-full"

src/components/Podcasts.astro

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ const podcasts = [
6464
<ul class="flex flex-col gap-8">
6565
{
6666
podcasts.map((podcast) => (
67-
<li class="group flex flex-col gap-2 border-l-2 border-transparent hover:border-zinc-500 pl-4 transition-all py-1">
67+
<li
68+
class="group relative flex flex-col gap-2 border-l-2 border-transparent pl-4 transition-all py-1"
69+
data-spotlight
70+
>
71+
<div
72+
class="absolute left-[-2px] top-0 bottom-0 w-[2px] bg-zinc-500 transition-opacity duration-300 pointer-events-none"
73+
style="mask-image: radial-gradient(200px circle at var(--x) var(--y), black, transparent);"
74+
/>
6875
<div class="flex flex-col gap-1">
6976
<div class="flex items-center gap-2">
7077
<h2 class="text-base font-medium tracking-tight text-neutral-100 group-hover:text-white transition-colors">

src/components/Post.astro

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ const { post } = Astro.props;
2222
---
2323

2424
<li
25-
class="group flex flex-col gap-2 border-l-2 border-transparent hover:border-zinc-500 pl-4 transition-all py-1"
25+
class="group relative flex flex-col gap-2 border-l-2 border-transparent pl-4 transition-all py-1"
26+
data-spotlight
2627
>
28+
<div
29+
class="absolute left-[-2px] top-0 bottom-0 w-[2px] bg-zinc-500 transition-opacity duration-300 pointer-events-none"
30+
style="mask-image: radial-gradient(200px circle at var(--x) var(--y), black, transparent);"
31+
>
32+
</div>
2733
<a href={post.url} class="block h-full">
2834
<div class="flex flex-col justify-between gap-1 items-baseline">
2935
<h2
@@ -49,18 +55,18 @@ const { post } = Astro.props;
4955
{post.mentions.length > 0 && (
5056
<span class="flex flex-wrap gap-1 text-neutral-400">
5157
Featured in
52-
<div>
58+
<div class="flex gap-1 flex-wrap">
5359
{post.mentions.map((mention, i) => (
54-
<>
55-
{i !== 0 && <span>, </span>}
60+
<div class="flex">
5661
<a
5762
href={mention.url}
5863
target="_blank"
5964
class="text-neutral-100 hover:text-sky-300 transition-colors"
6065
>
6166
{mention.title}
6267
</a>
63-
</>
68+
{i < post.mentions.length - 1 && <span>, </span>}
69+
</div>
6470
))}
6571
</div>
6672
</span>

src/components/Presentations.astro

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,14 @@ const presentations = [
3636
<ul class="flex flex-col gap-8">
3737
{
3838
presentations.map((presentation) => (
39-
<li class="group flex flex-col gap-2 border-l-2 border-transparent hover:border-zinc-500 pl-4 transition-all py-1">
39+
<li
40+
class="group relative flex flex-col gap-2 border-l-2 border-transparent pl-4 transition-all py-1"
41+
data-spotlight
42+
>
43+
<div
44+
class="absolute left-[-2px] top-0 bottom-0 w-[2px] bg-zinc-500 transition-opacity duration-300 pointer-events-none"
45+
style="mask-image: radial-gradient(200px circle at var(--x) var(--y), black, transparent);"
46+
/>
4047
<div class="flex flex-col gap-1">
4148
<h2 class="text-base font-medium tracking-tight text-neutral-100 group-hover:text-white transition-colors">
4249
{presentation.title}

src/layouts/Layout.astro

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,23 @@ const { title } = Astro.props;
5858
style="color-scheme: dark;"
5959
>
6060
<slot />
61+
<script is:inline>
62+
document.addEventListener("astro:page-load", () => {
63+
if (!window.matchMedia("(pointer: fine)").matches) return;
64+
65+
const cards = document.querySelectorAll("[data-spotlight]");
66+
67+
document.addEventListener("mousemove", (e) => {
68+
cards.forEach((card) => {
69+
const rect = card.getBoundingClientRect();
70+
const x = e.clientX - rect.left;
71+
const y = e.clientY - rect.top;
72+
73+
card.style.setProperty("--x", `${x}px`);
74+
card.style.setProperty("--y", `${y}px`);
75+
});
76+
});
77+
});
78+
</script>
6179
</body>
6280
</html>

src/styles/global.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
@plugin "@tailwindcss/typography";
33
@plugin "tailwindcss-motion";
44

5+
[data-spotlight] {
6+
--x: -10000px;
7+
--y: -10000px;
8+
}
9+
510
@media (prefers-reduced-motion: no-preference) {
611
html {
712
scroll-behavior: smooth;

0 commit comments

Comments
 (0)