refactor: refine home and library visual hierarchy

This commit is contained in:
2026-02-28 21:11:07 +01:00
parent 83212434f2
commit 6ce8a6e38d
8 changed files with 55 additions and 46 deletions

View File

@@ -5,7 +5,6 @@ import { useRouter } from "next/navigation";
import { RefreshButton } from "@/components/library/RefreshButton";
import { PullToRefreshIndicator } from "@/components/common/PullToRefreshIndicator";
import { usePullToRefresh } from "@/hooks/usePullToRefresh";
import { useTranslate } from "@/hooks/useTranslate";
interface HomeClientWrapperProps {
children: ReactNode;
@@ -13,7 +12,6 @@ interface HomeClientWrapperProps {
export function HomeClientWrapper({ children }: HomeClientWrapperProps) {
const router = useRouter();
const { t } = useTranslate();
const [isRefreshing, setIsRefreshing] = useState(false);
const handleRefresh = async () => {
@@ -45,12 +43,16 @@ export function HomeClientWrapper({ children }: HomeClientWrapperProps) {
canRefresh={pullToRefresh.canRefresh}
isHiding={pullToRefresh.isHiding}
/>
<main className="container mx-auto px-4 py-8 space-y-12">
<div className="flex justify-between items-center">
<h1 className="text-3xl font-bold">{t("home.title")}</h1>
<RefreshButton libraryId="home" refreshLibrary={handleRefresh} />
<main className="relative isolate overflow-hidden">
<div className="pointer-events-none absolute inset-0 -z-10 bg-[linear-gradient(180deg,hsl(var(--background)/0.99)_0%,hsl(var(--background)/0.95)_28%,hsl(var(--background))_100%)]" />
<div className="pointer-events-none absolute inset-0 -z-10 bg-[linear-gradient(128deg,hsl(var(--primary)/0.14)_0%,transparent_36%),linear-gradient(235deg,hsl(185_82%_54%/0.1)_4%,transparent_34%),linear-gradient(320deg,hsl(332_82%_63%/0.08)_8%,transparent_32%)]" />
<div className="container mx-auto space-y-12 px-4 py-8">
<div className="flex justify-end">
<RefreshButton libraryId="home" refreshLibrary={handleRefresh} />
</div>
{children}
</div>
{children}
</main>
</>
);

View File

@@ -29,7 +29,17 @@ const optimizeBookData = (books: KomgaBook[]) => {
export function HomeContent({ data }: HomeContentProps) {
return (
<div className="space-y-12">
<div className="space-y-10 pb-2">
{data.ongoingBooks && data.ongoingBooks.length > 0 && (
<div className="rounded-2xl border border-primary/20 bg-[linear-gradient(145deg,hsl(var(--primary)/0.12),hsl(var(--background)/0.1)_45%)] p-4 sm:p-5">
<MediaRow
titleKey="home.sections.continue_reading"
items={optimizeBookData(data.ongoingBooks)}
iconName="BookOpen"
/>
</div>
)}
{data.ongoing && data.ongoing.length > 0 && (
<MediaRow
titleKey="home.sections.continue_series"
@@ -38,14 +48,6 @@ export function HomeContent({ data }: HomeContentProps) {
/>
)}
{data.ongoingBooks && data.ongoingBooks.length > 0 && (
<MediaRow
titleKey="home.sections.continue_reading"
items={optimizeBookData(data.ongoingBooks)}
iconName="BookOpen"
/>
)}
{data.onDeck && data.onDeck.length > 0 && (
<MediaRow
titleKey="home.sections.up_next"

View File

@@ -64,7 +64,12 @@ export function MediaRow({ titleKey, items, iconName }: MediaRowProps) {
if (!items.length) return null;
return (
<Section title={t(titleKey)} icon={icon}>
<Section
title={t(titleKey)}
icon={icon}
className="space-y-5"
headerClassName="border-b border-border/50 pb-2"
>
<ScrollContainer
showArrows={true}
scrollAmount={400}
@@ -106,7 +111,7 @@ function MediaCard({ item, onClick }: MediaCardProps) {
<Card
onClick={handleClick}
className={cn(
"flex-shrink-0 w-[200px] relative flex flex-col hover:bg-accent hover:text-accent-foreground transition-colors overflow-hidden",
"relative flex w-[188px] flex-shrink-0 flex-col overflow-hidden rounded-xl border border-border/60 bg-card/85 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-card hover:shadow-md sm:w-[200px]",
!isSeries && !isAccessible ? "cursor-not-allowed" : "cursor-pointer"
)}
>
@@ -114,11 +119,11 @@ function MediaCard({ item, onClick }: MediaCardProps) {
{isSeries ? (
<>
<SeriesCover series={item as KomgaSeries} alt={`Couverture de ${title}`} />
<div className="absolute inset-0 bg-black/60 opacity-0 hover:opacity-100 transition-opacity duration-200 flex flex-col justify-end p-3">
<h3 className="font-medium text-sm text-white line-clamp-2">{title}</h3>
<p className="text-xs text-white/80 mt-1">
{t("series.books", { count: item.booksCount })}
</p>
<div className="absolute inset-0 flex flex-col justify-end bg-gradient-to-t from-black/75 via-black/30 to-transparent p-3 opacity-0 transition-opacity duration-200 hover:opacity-100">
<h3 className="font-medium text-sm text-white line-clamp-2">{title}</h3>
<p className="text-xs text-white/80 mt-1">
{t("series.books", { count: item.booksCount })}
</p>
</div>
</>
) : (