feat(animation-sources): improve discovery and sharing

This commit is contained in:
Poyraz
2026-08-29 17:38:08 +03:00
parent a019910d61
commit 6907ec5183
8 changed files with 161 additions and 46 deletions
+11 -28
View File
@@ -1,5 +1,5 @@
import Image from "next/image";
import { Badge, Card, Typography } from "poyraz-ui/atoms";
import { Card, Typography } from "poyraz-ui/atoms";
import { NewsCard } from "poyraz-ui/molecules";
import { Link } from "@/i18n/routing";
import type { AnimationSource } from "@/data/animation-sources";
@@ -34,38 +34,21 @@ export function AnimationSourcesContent({
</header>
{sources.length > 0 ? (
<div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
<div className="space-y-3">
{sources.map((source) => (
<Link
key={`${source.lang}-${source.slug}`}
href={`/animation-sources/${source.slug}`}
data-animation-source-card
className="group min-w-0"
className="block min-w-0"
>
<Card className="h-full overflow-hidden rounded-sm border-border p-0 transition-colors group-hover:border-red-600/60">
<div className="relative aspect-square overflow-hidden bg-white">
<Image
src={source.coverImage}
alt=""
fill
unoptimized={source.coverImage.toLowerCase().endsWith(".gif")}
sizes="(max-width: 640px) 50vw, 280px"
className="object-cover transition-transform duration-300 group-hover:scale-[1.02] motion-reduce:transition-none motion-reduce:group-hover:scale-100"
/>
</div>
<div className="space-y-2 border-t border-border p-3">
<Badge variant="outline" className="rounded-sm">
{source.platform}
</Badge>
<Typography
variant="large"
data-animation-source-title
className="line-clamp-2 min-h-10 text-sm leading-5 sm:text-base"
>
{source.title}
</Typography>
</div>
</Card>
<NewsCard
image={source.coverImage}
category={source.platform}
title={source.title}
date={source.date}
className="w-full rounded-sm border-border [&>div]:min-h-32 [&>div>div:first-child]:w-32 sm:[&>div>div:first-child]:w-40 [&_h3]:text-base"
/>
</Link>
))}
</div>
+8 -2
View File
@@ -9,6 +9,7 @@ import { ANNOUNCEMENT_ITEMS, ENABLE_NEKO_FOLLOWER } from "@/data/site-settings";
import { useLocale } from "next-intl";
import { getLocalizedValue } from "@/lib/locale";
import dynamic from "next/dynamic";
import type { AnimationSourceSearchItem } from "@/lib/command-palette-links";
const AtaturkWidgetModal = dynamic(
() => import("@/components/ataturk-widget-modal").then((mod) => mod.AtaturkWidgetModal),
@@ -17,6 +18,7 @@ const AtaturkWidgetModal = dynamic(
type AppShellProps = {
children: React.ReactNode;
animationSources: AnimationSourceSearchItem[];
};
export type ThemeMode = "light" | "dark";
@@ -30,7 +32,7 @@ function getInitialTheme(): ThemeMode {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
export function AppShell({ children }: AppShellProps) {
export function AppShell({ children, animationSources }: AppShellProps) {
const pathname = usePathname();
const locale = useLocale();
const announcement = ANNOUNCEMENT_ITEMS[0];
@@ -57,7 +59,11 @@ export function AppShell({ children }: AppShellProps) {
<AtaturkWidgetModal theme={theme} />
{ENABLE_NEKO_FOLLOWER ? <NekoFollower /> : null}
<div className="mx-auto flex w-full max-w-4xl flex-col px-4 py-4 ">
<SiteNavbar theme={theme} onThemeChange={setTheme} />
<SiteNavbar
theme={theme}
onThemeChange={setTheme}
animationSources={animationSources}
/>
{announcement ? (
<AnnouncementBar
variant="branded"
+9 -3
View File
@@ -17,6 +17,7 @@ import {
} from "poyraz-ui/molecules";
import {
getCommandPaletteGroups,
type AnimationSourceSearchItem,
type CommandPaletteItem as PaletteItem,
} from "@/lib/command-palette-links";
import { useKeyboardShortcutLabel } from "@/lib/use-keyboard-shortcut-label";
@@ -24,9 +25,14 @@ import { useKeyboardShortcutLabel } from "@/lib/use-keyboard-shortcut-label";
type SearchCommandProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
animationSources: AnimationSourceSearchItem[];
};
export function SearchCommand({ open, onOpenChange }: SearchCommandProps) {
export function SearchCommand({
open,
onOpenChange,
animationSources,
}: SearchCommandProps) {
const router = useRouter();
const locale = useLocale();
const tLinks = useTranslations("Links");
@@ -36,8 +42,8 @@ export function SearchCommand({ open, onOpenChange }: SearchCommandProps) {
const [query, setQuery] = useState("");
const groups = useMemo(() => {
return getCommandPaletteGroups(locale, tLinks, tNav);
}, [locale, tLinks, tNav]);
return getCommandPaletteGroups(locale, tLinks, tNav, animationSources);
}, [animationSources, locale, tLinks, tNav]);
const handleOpenChange = useCallback((nextOpen: boolean) => {
if (!nextOpen) {
+14 -3
View File
@@ -43,6 +43,7 @@ import {
TOP_ICON_LINKS,
} from "@/lib/links";
import type { ThemeMode } from "@/components/app-shell";
import type { AnimationSourceSearchItem } from "@/lib/command-palette-links";
const SearchCommand = dynamic(
() => import("@/components/search-command").then((mod) => mod.SearchCommand),
@@ -98,9 +99,15 @@ function ThemeToggle({ theme, onThemeChange }: ThemeToggleProps) {
);
}
type SiteNavbarProps = ThemeToggleProps;
type SiteNavbarProps = ThemeToggleProps & {
animationSources: AnimationSourceSearchItem[];
};
export function SiteNavbar({ theme, onThemeChange }: SiteNavbarProps) {
export function SiteNavbar({
theme,
onThemeChange,
animationSources,
}: SiteNavbarProps) {
const pathname = usePathname();
const [searchOpen, setSearchOpen] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
@@ -545,7 +552,11 @@ export function SiteNavbar({ theme, onThemeChange }: SiteNavbarProps) {
</Sheet>
</div>
<SearchCommand open={searchOpen} onOpenChange={setSearchOpen} />
<SearchCommand
open={searchOpen}
onOpenChange={setSearchOpen}
animationSources={animationSources}
/>
</header>
</div>
);