Remove skeleton swaps and deferred layout estimates, restore reveal state, and use native proximity scrolling for project cards. Also make the Docker build npm registry configurable.
80 lines
2.9 KiB
TypeScript
80 lines
2.9 KiB
TypeScript
import Image from 'next/image';
|
|
import { ExternalLink } from 'lucide-react';
|
|
import { getMilestones } from '@/data/milestones';
|
|
import { messagesByLocale, type Locale } from '@/i18n/content';
|
|
import styles from './MilestonesSection.module.css';
|
|
|
|
export const MilestonesSection = ({ locale }: { locale: Locale }) => {
|
|
const isRtl = locale === 'fa';
|
|
const milestones = getMilestones(locale);
|
|
const copy = messagesByLocale[locale].milestones;
|
|
|
|
return (
|
|
<section id="milestones" className={styles.milestonesSection}>
|
|
<div className="content-container">
|
|
{/* Section Header */}
|
|
<div className="section-header" data-reveal="soft">
|
|
<span className="section-eyebrow">{copy.eyebrow}</span>
|
|
<div className="section-title-wrap">
|
|
<h2 className="section-title">{copy.title}</h2>
|
|
<div className="section-underline" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Certificate Cards List */}
|
|
<div className={styles.cardsList} data-reveal-group>
|
|
{milestones.map((item) => (
|
|
<div key={item.id} className={styles.certCard}>
|
|
{/* Thumbnail */}
|
|
<div className={styles.thumbnailContainer} data-reveal="image">
|
|
<Image
|
|
src={item.image.src}
|
|
alt={item.title}
|
|
fill
|
|
sizes="(max-width: 650px) calc(100vw - 3rem), (max-width: 1024px) 44vw, 520px"
|
|
className={styles.certImage}
|
|
/>
|
|
</div>
|
|
|
|
{/* Content Details */}
|
|
<div className={styles.certDetails} data-reveal="soft">
|
|
<div className={styles.titleRow}>
|
|
<h3 className={styles.certTitle}>{item.title}</h3>
|
|
</div>
|
|
|
|
<div className={styles.issuerRow}>
|
|
<span className={styles.issuerText}>{item.issuer}</span>
|
|
</div>
|
|
|
|
<div className={styles.dateBadge}>{item.date}</div>
|
|
|
|
<p className={styles.description}>{item.description}</p>
|
|
|
|
{item.link && (
|
|
<div className={styles.actionRow}>
|
|
<a
|
|
href={item.link}
|
|
className={styles.viewCertLink}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
aria-label={copy.viewCertificateLabel(item.title)}
|
|
>
|
|
{isRtl && (
|
|
<ExternalLink size={20} strokeWidth={2.25} aria-hidden="true" />
|
|
)}
|
|
<span>{copy.viewCertificate}</span>
|
|
{!isRtl && (
|
|
<ExternalLink size={20} strokeWidth={2.25} aria-hidden="true" />
|
|
)}
|
|
</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|