This commit is contained in:
50
components/blog/ComparisonGrid.tsx
Normal file
50
components/blog/ComparisonGrid.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
|
||||
interface ComparisonGridItem {
|
||||
label: string;
|
||||
leftValue: string;
|
||||
rightValue: string;
|
||||
}
|
||||
|
||||
interface ComparisonGridProps {
|
||||
title?: string;
|
||||
leftLabel: string;
|
||||
rightLabel: string;
|
||||
items: ComparisonGridItem[];
|
||||
}
|
||||
|
||||
export default function ComparisonGrid({ title, leftLabel, rightLabel, items }: ComparisonGridProps) {
|
||||
return (
|
||||
<div className="my-16 not-prose">
|
||||
{title && (
|
||||
<h3 className="text-2xl font-bold text-text-primary mb-8">
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
<div className="border border-neutral-200 rounded-3xl overflow-hidden shadow-sm bg-white">
|
||||
<div className="grid grid-cols-3 bg-neutral-50 border-b border-neutral-200">
|
||||
<div className="p-4 md:p-6"></div>
|
||||
<div className="p-4 md:p-6 text-center font-bold text-primary uppercase tracking-widest border-l border-neutral-200 text-xs md:text-sm">
|
||||
{leftLabel}
|
||||
</div>
|
||||
<div className="p-4 md:p-6 text-center font-bold text-primary uppercase tracking-widest border-l border-neutral-200 text-xs md:text-sm">
|
||||
{rightLabel}
|
||||
</div>
|
||||
</div>
|
||||
{items.map((item, index) => (
|
||||
<div key={index} className="grid grid-cols-3 border-b border-neutral-200 last:border-0 hover:bg-neutral-50 transition-colors group">
|
||||
<div className="p-4 md:p-6 font-bold text-text-primary flex items-center text-sm md:text-base">
|
||||
{item.label}
|
||||
</div>
|
||||
<div className="p-4 md:p-6 text-center text-text-secondary border-l border-neutral-200 flex items-center justify-center group-hover:text-text-primary transition-colors text-sm md:text-base">
|
||||
{item.leftValue}
|
||||
</div>
|
||||
<div className="p-4 md:p-6 text-center text-text-secondary border-l border-neutral-200 flex items-center justify-center group-hover:text-text-primary transition-colors text-sm md:text-base">
|
||||
{item.rightValue}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
36
components/blog/StickyNarrative.tsx
Normal file
36
components/blog/StickyNarrative.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
|
||||
interface StickyNarrativeItem {
|
||||
title: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface StickyNarrativeProps {
|
||||
title: string;
|
||||
items: StickyNarrativeItem[];
|
||||
}
|
||||
|
||||
export default function StickyNarrative({ title, items }: StickyNarrativeProps) {
|
||||
return (
|
||||
<div className="my-24 grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-20 items-start not-prose">
|
||||
<div className="lg:col-span-4 lg:sticky lg:top-32">
|
||||
<h3 className="text-3xl md:text-4xl font-bold text-primary leading-tight">
|
||||
{title}
|
||||
</h3>
|
||||
<div className="w-16 h-1.5 bg-accent mt-8 rounded-full" />
|
||||
</div>
|
||||
<div className="lg:col-span-8 space-y-12 md:space-y-16">
|
||||
{items.map((item, index) => (
|
||||
<div key={index} className="group border-b border-neutral-200 pb-12 last:border-0 last:pb-0">
|
||||
<h4 className="text-xl md:text-2xl font-bold text-text-primary mb-4 group-hover:text-primary transition-colors">
|
||||
{item.title}
|
||||
</h4>
|
||||
<div className="text-lg text-text-secondary leading-relaxed">
|
||||
{item.content}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
43
components/blog/TechnicalGrid.tsx
Normal file
43
components/blog/TechnicalGrid.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import Scribble from '@/components/Scribble';
|
||||
|
||||
interface TechnicalGridItem {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface TechnicalGridProps {
|
||||
title?: string;
|
||||
items: TechnicalGridItem[];
|
||||
}
|
||||
|
||||
export default function TechnicalGrid({ title, items }: TechnicalGridProps) {
|
||||
return (
|
||||
<div className="my-16 not-prose">
|
||||
{title && (
|
||||
<h3 className="text-2xl font-bold text-text-primary mb-8 flex items-center gap-4 relative">
|
||||
<span className="relative inline-block">
|
||||
{title}
|
||||
<Scribble
|
||||
variant="underline"
|
||||
className="absolute -bottom-2 left-0 w-full h-3 text-accent/40"
|
||||
/>
|
||||
</span>
|
||||
</h3>
|
||||
)}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{items.map((item, index) => (
|
||||
<div key={index} className="bg-white p-8 rounded-2xl border border-neutral-200 shadow-sm hover:shadow-md transition-all duration-300 group relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-16 h-16 bg-primary/5 -mr-8 -mt-8 rotate-45 transition-transform group-hover:scale-110" />
|
||||
<span className="block text-xs font-bold text-primary uppercase tracking-[0.2em] mb-3 opacity-70">
|
||||
{item.label}
|
||||
</span>
|
||||
<span className="text-lg text-text-secondary leading-relaxed group-hover:text-text-primary transition-colors">
|
||||
{item.value}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user