style(explore): 将公开文件夹改为网格布局展示

- 移除 CardList 组件,改用 CSS Grid
- 响应式网格: 1/2/3/4 列 (sm/lg/xl)
- 重新设计卡片样式:圆角边框、hover 效果
- 文件夹图标移至左上角,收藏按钮移至右上角
This commit is contained in:
2026-03-08 15:03:35 +08:00
parent e74cd80fac
commit c6878ed1e5

View File

@@ -1,7 +1,6 @@
"use client";
import {
ChevronRight,
Folder as Fd,
Heart,
Search,
@@ -13,7 +12,6 @@ import { useTranslations } from "next-intl";
import { toast } from "sonner";
import { PageLayout } from "@/components/ui/PageLayout";
import { PageHeader } from "@/components/ui/PageHeader";
import { CardList } from "@/components/ui/CardList";
import {
actionSearchPublicFolders,
actionToggleFavorite,
@@ -63,36 +61,15 @@ const PublicFolderCard = ({ folder, currentUserId, onFavoriteChange }: PublicFol
return (
<div
className="flex justify-between items-center group py-4 px-5 border-b border-gray-200 last:border-b-0 hover:bg-gray-50 cursor-pointer transition-colors"
className="group bg-white border-2 border-gray-200 rounded-lg p-5 hover:border-primary-300 hover:shadow-md cursor-pointer transition-all"
onClick={() => {
router.push(`/explore/${folder.id}`);
}}
>
<div className="flex items-center gap-4 flex-1">
<div className="shrink-0 text-primary-500">
<Fd size={24} />
<div className="flex items-start justify-between mb-3">
<div className="shrink-0 w-10 h-10 rounded-lg bg-primary-50 flex items-center justify-center text-primary-500">
<Fd size={22} />
</div>
<div className="flex items-center gap-1 text-sm text-gray-400">
<Heart
size={14}
className={isFavorited ? "fill-red-500 text-red-500" : ""}
/>
<span>{favoriteCount}</span>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-semibold text-gray-900 truncate">{folder.name}</h3>
<p className="text-sm text-gray-500 mt-0.5">
{t("folderInfo", {
userName: folder.userName ?? folder.userUsername ?? t("unknownUser"),
totalPairs: folder.totalPairs,
})}
</p>
</div>
</div>
<div className="flex items-center gap-2">
<CircleButton
onClick={handleToggleFavorite}
title={isFavorited ? t("unfavorite") : t("favorite")}
@@ -102,7 +79,23 @@ const PublicFolderCard = ({ folder, currentUserId, onFavoriteChange }: PublicFol
className={isFavorited ? "fill-red-500 text-red-500" : ""}
/>
</CircleButton>
<ChevronRight size={20} className="text-gray-400" />
</div>
<h3 className="font-semibold text-gray-900 truncate mb-2">{folder.name}</h3>
<p className="text-sm text-gray-500 mb-3">
{t("folderInfo", {
userName: folder.userName ?? folder.userUsername ?? t("unknownUser"),
totalPairs: folder.totalPairs,
})}
</p>
<div className="flex items-center gap-1 text-sm text-gray-400">
<Heart
size={14}
className={isFavorited ? "fill-red-500 text-red-500" : ""}
/>
<span>{favoriteCount}</span>
</div>
</div>
);
@@ -148,7 +141,7 @@ export function ExploreClient({ initialPublicFolders }: ExploreClientProps) {
<PageLayout>
<PageHeader title={t("title")} subtitle={t("subtitle")} />
<div className="flex items-center gap-2 mb-4">
<div className="flex items-center gap-2 mb-6">
<div className="relative flex-1">
<Search size={18} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
<input
@@ -165,8 +158,6 @@ export function ExploreClient({ initialPublicFolders }: ExploreClientProps) {
</CircleButton>
</div>
<div className="mt-4">
<CardList>
{loading ? (
<div className="p-8 text-center">
<div className="w-8 h-8 border-2 border-gray-200 border-t-gray-400 rounded-full animate-spin mx-auto mb-3"></div>
@@ -180,17 +171,17 @@ export function ExploreClient({ initialPublicFolders }: ExploreClientProps) {
<p className="text-sm">{t("noFolders")}</p>
</div>
) : (
publicFolders.map((folder) => (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{publicFolders.map((folder) => (
<PublicFolderCard
key={folder.id}
folder={folder}
currentUserId={currentUserId}
onFavoriteChange={refreshFolders}
/>
))
)}
</CardList>
))}
</div>
)}
</PageLayout>
);
}