Files
2026-03-12 07:10:37 -04:00

92 lines
2.8 KiB
TypeScript

'use client'
import { PortableText, type PortableTextComponents } from 'next-sanity'
import Image from 'next/image'
import { urlFor } from '@/lib/sanity'
const components: PortableTextComponents = {
block: {
normal: ({ children }) => (
<p className="mb-5 leading-relaxed text-zinc-300">{children}</p>
),
h1: ({ children }) => (
<h1 className="mb-4 mt-10 text-3xl font-semibold text-zinc-100">{children}</h1>
),
h2: ({ children }) => (
<h2 className="mb-3 mt-8 text-2xl font-semibold text-zinc-100">{children}</h2>
),
h3: ({ children }) => (
<h3 className="mb-2 mt-6 text-xl font-semibold text-zinc-100">{children}</h3>
),
blockquote: ({ children }) => (
<blockquote className="my-6 border-l-2 border-amber-400/60 pl-4 text-zinc-400 italic">
{children}
</blockquote>
),
},
marks: {
strong: ({ children }) => (
<strong className="font-semibold text-zinc-100">{children}</strong>
),
em: ({ children }) => <em className="italic text-zinc-300">{children}</em>,
code: ({ children }) => (
<code className="rounded bg-zinc-800 px-1.5 py-0.5 font-mono text-sm text-amber-300">
{children}
</code>
),
link: ({ value, children }) => (
<a
href={value?.href}
target={value?.href?.startsWith('http') ? '_blank' : undefined}
rel={value?.href?.startsWith('http') ? 'noopener noreferrer' : undefined}
className="text-amber-400 underline underline-offset-2 hover:text-amber-300"
>
{children}
</a>
),
},
list: {
bullet: ({ children }) => (
<ul className="mb-5 ml-6 list-disc space-y-1.5 text-zinc-300">{children}</ul>
),
number: ({ children }) => (
<ol className="mb-5 ml-6 list-decimal space-y-1.5 text-zinc-300">{children}</ol>
),
},
listItem: {
bullet: ({ children }) => <li className="leading-relaxed">{children}</li>,
number: ({ children }) => <li className="leading-relaxed">{children}</li>,
},
types: {
image: ({ value }) => {
if (!value?.asset) return null
return (
<figure className="my-8">
<div className="relative overflow-hidden rounded-lg">
<Image
src={urlFor(value).width(800).url()}
alt={value.alt ?? ''}
width={800}
height={450}
className="w-full object-cover"
/>
</div>
{value.caption && (
<figcaption className="mt-2 text-center text-xs text-zinc-500">
{value.caption}
</figcaption>
)}
</figure>
)
},
},
}
export function PortableTextRenderer({ value }: { value: unknown[] }) {
return (
<div className="prose-battl">
<PortableText value={value as any} components={components} />
</div>
)
}