-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBrutalistPostItem.jsx
More file actions
135 lines (124 loc) · 4.52 KB
/
BrutalistPostItem.jsx
File metadata and controls
135 lines (124 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import React from 'react';
import { Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { ArrowRightIcon, FolderIcon } from '@phosphor-icons/react';
const BrutalistPostItem = ({ post, isActive, onHover = () => {} }) => {
const { slug, title, date, category, series, seriesIndex, isSeries } = post;
const formattedDate = new Date(date).toLocaleDateString('en-GB', {
day: '2-digit',
month: '2-digit',
year: '2-digit',
});
const categoryColor =
category === 'dev'
? 'var(--color-dev-badge)'
: category === 'series'
? 'var(--color-series-badge)'
: category === 'd&d' || category === 'dnd'
? 'var(--color-dnd-badge)'
: category === 'gist'
? 'var(--color-gist-badge)'
: category === 'feat'
? 'var(--color-feat-badge)'
: category === 'ai'
? 'var(--color-ai-badge)'
: 'var(--color-rant-badge)';
const categoryBg =
category === 'dev'
? 'rgba(59, 130, 246, 0.3)'
: category === 'series'
? 'rgba(237, 197, 49, 0.3)'
: category === 'd&d' || category === 'dnd'
? 'rgba(236, 72, 153, 0.3)'
: category === 'gist'
? 'rgba(245, 158, 11, 0.3)'
: category === 'feat'
? 'rgba(168, 85, 247, 0.3)'
: category === 'ai'
? 'rgba(132, 204, 22, 0.2)'
: 'rgba(16, 185, 129, 0.2)';
return (
<motion.div
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
onMouseEnter={() => onHover(post)}
className="relative mr-4 md:mr-12"
>
<Link
to={isSeries ? `/blog/series/${slug}` : `/blog/${slug}`}
className="group relative flex items-center justify-between border-b border-white/10 py-6 pr-20 transition-all duration-300"
>
{/* Active Marker */}
<div
className={`absolute left-0 top-0 h-full w-1 transition-all duration-300 ${
isActive ? 'opacity-100' : 'opacity-0'
}`}
style={{ backgroundColor: categoryColor || 'var(--emerald-400)' }}
/>
<div className="flex flex-1 items-center gap-6 pl-4 md:pl-8 min-w-0 pr-12">
{/* Date */}
<span
className={`font-mono text-[10px] tracking-widest flex-shrink-0 transition-colors duration-300 ${
isActive ? 'text-emerald-400' : 'text-gray-600'
}`}
>
{formattedDate}
</span>
{/* Title Area */}
<div className="flex items-center gap-3 min-w-0 flex-1">
{isSeries && (
<FolderIcon
size={24}
weight="fill"
className="shrink-0"
style={{ color: categoryColor }}
/>
)}
<div className="flex flex-col gap-1">
<h3
className={`text-xl font-medium uppercase tracking-tight transition-all duration-300 md:text-2xl break-words leading-tight ${
isActive
? 'translate-x-1 text-white'
: 'text-gray-500 group-hover:text-gray-300'
}`}
>
{title}
</h3>
{series && (
<span className="font-mono text-[9px] uppercase tracking-[0.2em] text-emerald-500/60">
{typeof series === 'object' ? series.title : series} {'//'}{' '}
Part {seriesIndex}
</span>
)}
</div>
</div>
</div>
{/* Category Badge & Arrow */}
<div className="flex items-center gap-4 flex-shrink-0">
<span
className="px-2 py-0.5 text-[9px] font-mono font-bold uppercase tracking-widest border rounded-sm transition-all duration-300 text-gray-300"
style={{
borderColor: categoryColor,
backgroundColor: categoryBg,
}}
>
{category || 'Post'}
</span>
<div className="w-10 flex justify-end">
<ArrowRightIcon
weight="bold"
size={20}
className={`transition-all duration-300 ${
isActive
? 'translate-x-0 opacity-100'
: '-translate-x-4 opacity-0 text-gray-500'
}`}
style={{ color: isActive ? categoryColor : undefined }}
/>
</div>
</div>
</Link>
</motion.div>
);
};
export default BrutalistPostItem;