refactor: refine home and library visual hierarchy
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user