Skip to content

Commit 41960d7

Browse files
committed
Restore original article hover visuals
1 parent c135382 commit 41960d7

4 files changed

Lines changed: 38 additions & 194 deletions

File tree

src/app/blog/page.tsx

Lines changed: 25 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { motion, useReducedMotion } from "motion/react";
66
import { useMemo, useRef, useState } from "react";
77
import { toast } from "sonner";
88
import { MotionButton, MotionLabel } from "@/components/motion-primitives";
9-
import { articleRowHover, cardReveal, motionViewport, pageEnter } from "@/lib/motion-presets";
9+
import { cardReveal, motionViewport, pageEnter } from "@/lib/motion-presets";
1010
import { groupBlogsByYear } from "@/lib/blog-index";
1111
import { readFileAsText } from "@/lib/file-utils";
1212
import { getErrorMessage } from "@/lib/utils";
@@ -195,74 +195,43 @@ export default function BlogPage() {
195195
transition: { duration: 0.26, delay: index * 0.025 },
196196
};
197197

198-
if (!editing) {
199-
return (
200-
<MotionLink
201-
className="blog-list-item"
202-
href={`/blog/${item.slug}`}
203-
key={item.slug}
204-
prefetch={false}
205-
{...itemRevealProps}
206-
{...articleRowHover(reduced)}
207-
>
208-
<time dateTime={item.date}>{item.date.slice(5)}</time>
209-
210-
<div>
211-
<span className="blog-title-link">
212-
<span className="article-row-title-text">{item.title}</span>
213-
<span aria-hidden="true" className="article-row-title-gradient">
214-
{item.title}
215-
</span>
216-
</span>
217-
<p>{item.summary}</p>
218-
<div className="tag-row">
219-
{item.tags.map((tag) => (
220-
<span className="tag" key={tag}>
221-
#{tag}
222-
</span>
223-
))}
224-
</div>
225-
</div>
226-
</MotionLink>
227-
);
228-
}
229-
230198
return (
231199
<motion.article
232200
className={checked ? "blog-list-item selected" : "blog-list-item"}
233201
key={item.slug}
234202
layout={editing && !reduced ? "position" : false}
235203
{...itemRevealProps}
236-
{...articleRowHover(reduced)}
237204
>
238-
<input
239-
checked={checked}
240-
className="select-check"
241-
type="checkbox"
242-
onChange={(event) => {
243-
setSelected((current) => {
244-
const next = new Set(current);
245-
if (event.target.checked) {
246-
next.add(item.slug);
247-
} else {
248-
next.delete(item.slug);
249-
}
250-
return next;
251-
});
252-
}}
253-
/>
205+
{editing ? (
206+
<input
207+
checked={checked}
208+
className="select-check"
209+
type="checkbox"
210+
onChange={(event) => {
211+
setSelected((current) => {
212+
const next = new Set(current);
213+
if (event.target.checked) {
214+
next.add(item.slug);
215+
} else {
216+
next.delete(item.slug);
217+
}
218+
return next;
219+
});
220+
}}
221+
/>
222+
) : (
223+
<time dateTime={item.date}>{item.date.slice(5)}</time>
224+
)}
254225

255226
<div>
256-
<Link
227+
<MotionLink
257228
className="blog-title-link"
258229
href={`/blog/${item.slug}`}
259230
prefetch={false}
231+
{...(!reduced ? { whileHover: { x: 2 } } : {})}
260232
>
261-
<span className="article-row-title-text">{item.title}</span>
262-
<span aria-hidden="true" className="article-row-title-gradient">
263-
{item.title}
264-
</span>
265-
</Link>
233+
{item.title}
234+
</MotionLink>
266235
<p>{item.summary}</p>
267236
<div className="tag-row">
268237
{item.tags.map((tag) => (

src/app/globals.css

Lines changed: 8 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -698,94 +698,43 @@ button {
698698
display: grid;
699699
grid-template-columns: 72px 1fr;
700700
gap: 18px;
701-
overflow: hidden;
702-
contain: paint;
703701
border-radius: 18px;
704702
padding: 14px;
705-
backface-visibility: hidden;
706-
transform: translateZ(0);
707-
transition:
708-
color 180ms ease;
703+
transform-origin: center;
704+
will-change: transform;
709705
}
710706

711707
.home-article-row::before {
712708
position: absolute;
713709
inset: 0;
714710
z-index: -1;
715711
border-radius: inherit;
716-
background:
717-
linear-gradient(112deg, rgba(255, 255, 255, 0.78) 0%, rgba(142, 216, 255, 0.2) 58%, rgba(238, 194, 94, 0.18) 100%),
718-
rgba(255, 255, 255, 0.58);
719-
box-shadow: inset 0 0 0 1px rgba(47, 203, 231, 0.16);
712+
background: rgba(255, 255, 255, 0.58);
720713
content: "";
721714
opacity: 0;
722715
pointer-events: none;
723-
transition: opacity 180ms ease;
716+
will-change: opacity;
724717
}
725718

726-
.home-article-row:hover,
727-
.home-article-row:focus-visible {
728-
will-change: transform;
729-
}
730-
731-
.home-article-row:focus-visible,
732-
.blog-list-item:focus-visible,
733-
.blog-list-item:focus-within {
734-
outline: 2px solid rgba(47, 203, 231, 0.42);
735-
outline-offset: -3px;
736-
}
737-
738-
.home-article-row:hover::before,
739-
.home-article-row:focus-visible::before {
719+
.home-article-row:hover::before {
740720
opacity: 1;
741721
}
742722

743-
.home-article-row:hover strong,
744-
.home-article-row:focus-visible strong {
745-
transform: translate3d(2px, 0, 0);
746-
}
747-
748723
.home-article-row time {
749724
color: var(--gold);
750725
font-size: 0.88rem;
751726
font-weight: 900;
752727
}
753728

754-
.article-row-title,
729+
.home-article-row strong,
755730
.home-article-row small {
756731
display: block;
757732
}
758733

759-
.article-row-title {
760-
position: relative;
734+
.home-article-row strong {
761735
color: var(--foreground);
762736
font-size: 1rem;
763737
font-weight: 900;
764-
transition:
765-
text-shadow 180ms ease,
766-
transform 180ms ease;
767-
}
768-
769-
.article-row-title-gradient {
770-
position: absolute;
771-
inset: 0;
772-
background: linear-gradient(112deg, var(--cyan) 0%, #2f80ff 36%, #8ed8ff 64%, var(--gold) 100%);
773-
background-clip: text;
774-
color: transparent;
775-
opacity: 0;
776-
pointer-events: none;
777-
transition: opacity 180ms ease;
778-
-webkit-background-clip: text;
779-
-webkit-text-fill-color: transparent;
780-
}
781-
782-
.home-article-row:hover .article-row-title-gradient,
783-
.home-article-row:focus-visible .article-row-title-gradient,
784-
.blog-title-link:hover .article-row-title-gradient,
785-
.blog-title-link:focus-visible .article-row-title-gradient,
786-
.blog-list-item:hover .article-row-title-gradient,
787-
.blog-list-item:focus-within .article-row-title-gradient {
788-
opacity: 1;
789738
}
790739

791740
.home-article-row small {
@@ -993,20 +942,6 @@ button {
993942
animation: none;
994943
opacity: 0;
995944
}
996-
997-
.home-article-row strong,
998-
.blog-title-link {
999-
transition: text-shadow 160ms ease;
1000-
}
1001-
1002-
.home-article-row:hover strong,
1003-
.home-article-row:focus-visible strong,
1004-
.blog-title-link:hover,
1005-
.blog-title-link:focus-visible,
1006-
.blog-list-item:hover .blog-title-link,
1007-
.blog-list-item:focus-within .blog-title-link {
1008-
transform: none;
1009-
}
1010945
}
1011946

1012947
@media (max-width: 1120px) {
@@ -1415,36 +1350,23 @@ button {
14151350
grid-template-columns: 72px 1fr auto;
14161351
gap: 18px;
14171352
align-items: start;
1418-
overflow: hidden;
1419-
contain: paint;
14201353
border-radius: 20px;
14211354
padding: 14px;
1422-
backface-visibility: hidden;
1423-
transform: translateZ(0);
14241355
}
14251356

14261357
.blog-list-item::before {
14271358
position: absolute;
14281359
inset: 0;
14291360
z-index: -1;
14301361
border-radius: inherit;
1431-
background:
1432-
linear-gradient(112deg, rgba(255, 255, 255, 0.78) 0%, rgba(142, 216, 255, 0.2) 58%, rgba(238, 194, 94, 0.18) 100%),
1433-
rgba(255, 255, 255, 0.58);
1434-
box-shadow: inset 0 0 0 1px rgba(47, 203, 231, 0.16);
1362+
background: rgba(255, 255, 255, 0.58);
14351363
content: "";
14361364
opacity: 0;
14371365
pointer-events: none;
14381366
transition: opacity 180ms ease;
14391367
}
14401368

1441-
.blog-list-item:hover,
1442-
.blog-list-item:focus-within {
1443-
will-change: transform;
1444-
}
1445-
14461369
.blog-list-item:hover::before,
1447-
.blog-list-item:focus-within::before,
14481370
.blog-list-item.selected::before {
14491371
opacity: 1;
14501372
}
@@ -1457,36 +1379,10 @@ button {
14571379
}
14581380

14591381
.blog-title-link {
1460-
position: relative;
14611382
display: inline-block;
14621383
color: var(--foreground);
14631384
font-size: 1rem;
14641385
font-weight: 900;
1465-
transform: translateZ(0);
1466-
transition:
1467-
text-shadow 180ms ease,
1468-
transform 180ms ease;
1469-
}
1470-
1471-
.blog-title-link:hover,
1472-
.blog-title-link:focus-visible,
1473-
.blog-list-item:hover .blog-title-link,
1474-
.blog-list-item:focus-within .blog-title-link {
1475-
text-shadow: 0 8px 22px rgba(47, 203, 231, 0.12);
1476-
transform: translate3d(2px, 0, 0);
1477-
}
1478-
1479-
@media (prefers-reduced-motion: reduce) {
1480-
.blog-title-link {
1481-
transition: text-shadow 160ms ease;
1482-
}
1483-
1484-
.blog-title-link:hover,
1485-
.blog-title-link:focus-visible,
1486-
.blog-list-item:hover .blog-title-link,
1487-
.blog-list-item:focus-within .blog-title-link {
1488-
transform: none;
1489-
}
14901386
}
14911387

14921388
.blog-list-item p {

src/components/home-content-sections.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Link from "next/link";
44
import { ArrowRight, ExternalLink, GitBranch, Package } from "lucide-react";
55
import { motion, useReducedMotion } from "motion/react";
66
import { MotionCard } from "@/components/motion-primitives";
7-
import { articleRowHover, buttonTap, cardReveal, motionViewport } from "@/lib/motion-presets";
7+
import { buttonTap, cardReveal, motionViewport } from "@/lib/motion-presets";
88
import { projects, visibleArticles } from "@/data/content";
99
import type { ProjectRecord } from "@/types/content";
1010

@@ -88,22 +88,18 @@ export function HomeContentSections() {
8888
viewport={motionViewport}
8989
>
9090
{previewArticles.length > 0 ? (
91-
previewArticles.map((article) => (
91+
previewArticles.map((article, index) => (
9292
<MotionLink
9393
className="home-article-row"
9494
href={`/blog/${article.slug}`}
9595
key={article.slug}
9696
prefetch={false}
97-
{...articleRowHover(reduced)}
97+
style={{ transitionDelay: `${index * 35}ms` }}
98+
{...buttonTap(reduced)}
9899
>
99100
<time dateTime={article.date}>{article.date.slice(5)}</time>
100101
<span>
101-
<strong className="article-row-title">
102-
<span className="article-row-title-text">{article.title}</span>
103-
<span aria-hidden="true" className="article-row-title-gradient">
104-
{article.title}
105-
</span>
106-
</strong>
102+
<strong>{article.title}</strong>
107103
<small>{article.summary}</small>
108104
</span>
109105
</MotionLink>

src/lib/motion-presets.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const motionDurations = {
1010
card: 0.34,
1111
panel: 0.2,
1212
button: 0.16,
13-
articleRow: 0.18,
1413
} as const;
1514

1615
export function pageEnter(reducedMotion: boolean, delay = 0) {
@@ -66,19 +65,3 @@ export function buttonTap(reducedMotion: boolean) {
6665
transition: { duration: motionDurations.button, ease: motionEase },
6766
};
6867
}
69-
70-
export function articleRowHover(reducedMotion: boolean) {
71-
return reducedMotion
72-
? {}
73-
: {
74-
whileHover: {
75-
y: -3,
76-
scale: 1.01,
77-
transition: { duration: motionDurations.articleRow, ease: motionEase },
78-
},
79-
whileTap: {
80-
scale: 0.99,
81-
transition: { duration: motionDurations.button, ease: motionEase },
82-
},
83-
};
84-
}

0 commit comments

Comments
 (0)