Files
soroushasadi/components/sections/Blog.tsx
T
soroush.asadi add78d8460
ci / build (push) Failing after 23s
deploy / deploy (push) Failing after 10m12s
first commit
2026-05-31 12:47:02 +03:30

109 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import Link from 'next/link';
import { motion } from 'framer-motion';
import { useLocale } from '@/lib/i18n/locale-context';
import { SectionHeader } from '@/components/ui/SectionHeader';
import { cn } from '@/lib/utils';
const FA_DIGITS = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'] as const;
const toFa = (n: number) =>
n.toString().replace(/\d/g, (d) => FA_DIGITS[Number(d)]);
const CATEGORY_COLOR: Record<string, string> = {
LLM: 'text-magenta border-magenta/30 bg-magenta/5',
Automation: 'text-violet border-violet/30 bg-violet/5',
'Google Stack': 'text-cyan border-cyan/30 bg-cyan/5',
Infra: 'text-emerald border-emerald/30 bg-emerald/5',
Mobile: 'text-electric border-electric/30 bg-electric/5',
Strategy: 'text-electric border-electric/30 bg-electric/5',
};
export function Blog() {
const { t, locale } = useLocale();
return (
<section id="blog" className="relative px-5 py-28 sm:px-8">
<div className="mx-auto max-w-7xl">
<SectionHeader
eyebrow={t.blog.eyebrow}
title={t.blog.title}
sub={t.blog.sub}
/>
<div className="mt-14 grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
{t.blog.items.map((post, i) => (
<motion.article
key={post.slug}
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-60px' }}
transition={{
duration: 0.55,
ease: [0.22, 1, 0.36, 1],
delay: 0.04 * i,
}}
className="glass group relative flex flex-col p-6 transition-shadow duration-300 hover:shadow-glow-electric"
>
<div className="flex items-center justify-between">
<span
className={cn(
'rounded-full border px-2.5 py-0.5 font-mono text-[0.65rem] uppercase tracking-wider',
CATEGORY_COLOR[post.category] ?? 'text-slate-300 border-white/10 bg-white/[0.03]',
)}
>
{post.category}
</span>
<span className="font-mono text-[0.7rem] text-slate-500">
{locale === 'fa' ? toFa(post.readTime) : post.readTime}{' '}
{t.blog.readTimeSuffix}
</span>
</div>
<h3
className={cn(
'mt-5 font-display text-[1.05rem] font-semibold leading-snug text-white transition-colors group-hover:text-electric',
locale === 'fa' && 'font-fa',
)}
>
<Link href={`/blog/${post.slug}`} className="after:absolute after:inset-0">
{post.title}
</Link>
</h3>
<p className="mt-3 grow text-[0.92rem] leading-relaxed text-slate-400">
{post.excerpt}
</p>
<span className="mt-5 inline-flex items-center gap-1.5 font-mono text-[0.72rem] uppercase tracking-wider text-electric">
{t.blog.readMore}
<Arrow locale={locale} />
</span>
</motion.article>
))}
</div>
</div>
</section>
);
}
function Arrow({ locale }: { locale: 'fa' | 'en' }) {
return (
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
strokeWidth="2.4"
strokeLinecap="round"
strokeLinejoin="round"
className={locale === 'fa' ? 'rotate-180' : ''}
aria-hidden
>
<path d="M5 12 H19" />
<path d="M13 6 L19 12 L13 18" />
</svg>
);
}