Files
Poyraz Avsever 0609170073 feat: enhance components with new features and optimizations
- Added support for conditional rendering of the NekoFollower component in AppShell based on ENABLE_NEKO_FOLLOWER.
- Introduced MarkdownImage component in BlogDetailContent for handling images in markdown, supporting both local and external assets.
- Improved BlogToc component to use IntersectionObserver for better performance in tracking active headings.
- Refactored ContentContent to utilize YoutubeLiteEmbed for embedding YouTube videos, simplifying the video rendering logic.
- Created a new YoutubeLiteEmbed component for lazy loading YouTube videos with thumbnail previews.
- Updated site-settings to include ENABLE_NEKO_FOLLOWER constant for feature toggling.
- Enhanced next.config.ts with image optimization settings for better performance.
- Refactored snippets-content to improve code readability and structure.
- Cleaned up home-hero and home-videos-section components for better layout and performance.
2026-04-15 10:38:28 +03:00

104 lines
3.5 KiB
TypeScript
Raw Permalink 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 { useState } from "react";
import { Badge, Card, Typography } from "poyraz-ui/atoms";
import type { Snippet } from "@/data/snippets";
type SnippetsContentProps = {
snippets: Snippet[];
categories: string[];
};
function extractCode(markdown: string) {
const match = /```\w*\n([\s\S]*?)```/.exec(markdown);
return match ? match[1].trim() : markdown;
}
export function SnippetsContent({
snippets,
categories,
}: SnippetsContentProps) {
const [selected, setSelected] = useState("All");
const filtered =
selected === "All"
? snippets
: snippets.filter((s) => s.category === selected);
return (
<section className="flex h-full flex-col gap-3 overflow-y-auto">
<Card className="rounded-sm border-border p-4">
<div className="flex items-center justify-between">
<div>
<Typography variant="h3">
Kod{" "}
<span className="font-secondary text-red-600">Parçacıkları</span>
</Typography>
<Typography variant="small" className="mt-1 text-muted-foreground">
Sıkça kullandığım, tekrar kullanılabilir kod parçacıkları.
</Typography>
</div>
<div className="flex flex-wrap gap-1.5">
{categories.map((cat) => (
<button key={cat} type="button" onClick={() => setSelected(cat)}>
<Badge
variant={cat === selected ? "default" : "outline"}
className="cursor-pointer rounded-sm"
>
{cat}
</Badge>
</button>
))}
</div>
</div>
</Card>
<div className="grid gap-3 md:grid-cols-2">
{filtered.map((snippet) => (
<div key={snippet.slug}>
<Card className="flex h-full flex-col rounded-sm border-border">
<div className="flex items-start justify-between gap-2 p-4 pb-2">
<div>
<Typography
variant="large"
className="text-base leading-tight"
>
{snippet.title}
</Typography>
<Typography
variant="small"
className="mt-1 text-muted-foreground"
>
{snippet.description}
</Typography>
</div>
<Badge variant="outline" className="shrink-0 rounded-sm">
{snippet.language}
</Badge>
</div>
<div className="flex-1 px-4 pb-4">
<Card className="overflow-hidden rounded-sm border-border p-0">
<div className="border-b border-border bg-muted/40 px-3 py-1.5 text-[11px] uppercase tracking-wide text-muted-foreground">
{snippet.language || "code"}
</div>
<pre className="overflow-x-auto bg-zinc-950/95 p-3 text-[13px] leading-6 text-zinc-100">
<code>{extractCode(snippet.markdown)}</code>
</pre>
</Card>
</div>
</Card>
</div>
))}
</div>
{filtered.length === 0 && (
<Card className="rounded-sm border-border p-5">
<Typography variant="p" className="text-muted-foreground">
Bu kategoride henüz snippet bulunmuyor.
</Typography>
</Card>
)}
</section>
);
}