Skip to content

Commit 23b5081

Browse files
committed
feat(terracotta): add TerracottaPostItem component
1 parent 648ffe6 commit 23b5081

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import React from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { motion } from 'framer-motion';
4+
import { ArrowRightIcon, FolderIcon } from '@phosphor-icons/react';
5+
6+
const TerracottaPostItem = ({ post, isActive, onHover = () => {} }) => {
7+
const { slug, title, date, category, series, seriesIndex, isSeries } = post;
8+
9+
const formattedDate = new Date(date).toLocaleDateString('en-GB', {
10+
day: '2-digit',
11+
month: '2-digit',
12+
year: '2-digit',
13+
});
14+
15+
const categoryColor =
16+
category === 'dev'
17+
? '#6B8E23'
18+
: category === 'series'
19+
? '#B88532'
20+
: category === 'd&d' || category === 'dnd'
21+
? '#9E4A2F'
22+
: category === 'gist'
23+
? '#C96442'
24+
: category === 'feat'
25+
? '#8A6A32'
26+
: category === 'ai'
27+
? '#6B8E23'
28+
: '#C96442';
29+
30+
const categoryBg =
31+
category === 'dev'
32+
? 'rgba(107, 142, 35, 0.18)'
33+
: category === 'series'
34+
? 'rgba(184, 133, 50, 0.2)'
35+
: category === 'd&d' || category === 'dnd'
36+
? 'rgba(158, 74, 47, 0.2)'
37+
: category === 'gist'
38+
? 'rgba(201, 100, 66, 0.2)'
39+
: category === 'feat'
40+
? 'rgba(138, 106, 50, 0.2)'
41+
: category === 'ai'
42+
? 'rgba(107, 142, 35, 0.15)'
43+
: 'rgba(201, 100, 66, 0.18)';
44+
45+
return (
46+
<motion.div
47+
initial={{ opacity: 0, x: -10 }}
48+
animate={{ opacity: 1, x: 0 }}
49+
onMouseEnter={() => onHover(post)}
50+
className="relative mr-4 md:mr-12"
51+
>
52+
<Link
53+
to={isSeries ? `/blog/series/${slug}` : `/blog/${slug}`}
54+
className="group relative flex items-center justify-between border-b border-[#1A161320] py-6 pr-20 transition-all duration-300"
55+
>
56+
<div
57+
className={`absolute left-0 top-0 h-full w-1 transition-all duration-300 ${isActive ? 'opacity-100' : 'opacity-0'}`}
58+
style={{ backgroundColor: categoryColor || '#C96442' }}
59+
/>
60+
61+
<div className="flex flex-1 items-center gap-6 pl-4 md:pl-8 min-w-0 pr-12">
62+
<span
63+
className={`font-mono text-[10px] tracking-widest flex-shrink-0 transition-colors duration-300 ${
64+
isActive ? 'text-[#9E4A2F]' : 'text-[#2E2620]/50'
65+
}`}
66+
>
67+
{formattedDate}
68+
</span>
69+
70+
<div className="flex items-center gap-3 min-w-0 flex-1">
71+
{isSeries && (
72+
<FolderIcon
73+
size={24}
74+
weight="fill"
75+
className="shrink-0"
76+
style={{ color: categoryColor }}
77+
/>
78+
)}
79+
<div className="flex flex-col gap-1">
80+
<h3
81+
className={`text-xl md:text-2xl font-playfairDisplay tracking-tight transition-all duration-300 break-words leading-tight ${
82+
isActive
83+
? 'translate-x-1 text-[#1A1613] italic'
84+
: 'text-[#2E2620]/60 group-hover:text-[#1A1613]'
85+
}`}
86+
>
87+
{title}
88+
</h3>
89+
90+
{series && (
91+
<span className="font-mono text-[9px] uppercase tracking-[0.2em] text-[#9E4A2F]/70">
92+
{typeof series === 'object' ? series.title : series} {'//'} Part {seriesIndex}
93+
</span>
94+
)}
95+
</div>
96+
</div>
97+
</div>
98+
99+
<div className="flex items-center gap-4 flex-shrink-0">
100+
<span
101+
className="px-2 py-0.5 text-[9px] font-mono font-bold uppercase tracking-widest border rounded-sm transition-all duration-300"
102+
style={{
103+
borderColor: categoryColor,
104+
backgroundColor: categoryBg,
105+
color: categoryColor,
106+
}}
107+
>
108+
{category || 'Post'}
109+
</span>
110+
111+
<div className="w-10 flex justify-end">
112+
<ArrowRightIcon
113+
weight="bold"
114+
size={20}
115+
className={`transition-all duration-300 ${
116+
isActive ? 'translate-x-0 opacity-100' : '-translate-x-4 opacity-0 text-[#2E2620]/50'
117+
}`}
118+
style={{ color: isActive ? categoryColor : undefined }}
119+
/>
120+
</div>
121+
</div>
122+
</Link>
123+
</motion.div>
124+
);
125+
};
126+
127+
export default TerracottaPostItem;

0 commit comments

Comments
 (0)