fix: desktop homepage responsive polish and nav tweaks
- Banner: scale down and center on desktop (md:max-w-[680px] lg:max-w-[800px]) so it no longer fills the whole screen. - Align section widths to one responsive container (820/1080/1180): wrap the Official row and match Popular to Latest, fixing left-edge/width mismatches. - RecommendedCard: stop the carousel card from shrinking back to 246.4px at xl. - Popular download button now matches the file bubble's filled round DownloadCloud button for visual consistency. - Header nav vertical padding py-1 -> py-0.5; swap Favorites before Popular across desktop nav and mobile menu to match the bottom tab order. - Official carousel: hide the left arrow at the start and the right arrow at the end instead of always showing both. All changes are md/lg/xl-scoped; mobile layout is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -301,7 +301,7 @@ export function FigmaBanner() {
|
|||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative md:mx-auto md:max-w-[680px] lg:max-w-[800px]">
|
||||||
<div
|
<div
|
||||||
ref={scrollerRef}
|
ref={scrollerRef}
|
||||||
onPointerDown={handlePointerDown}
|
onPointerDown={handlePointerDown}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Archive,
|
Archive,
|
||||||
Download,
|
|
||||||
File,
|
File,
|
||||||
FileText,
|
FileText,
|
||||||
Image as ImageIcon,
|
Image as ImageIcon,
|
||||||
@@ -11,6 +10,7 @@ import {
|
|||||||
Video,
|
Video,
|
||||||
type LucideIcon,
|
type LucideIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { DownloadCloudIcon } from "./icons/DownloadCloudIcon";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { assetUrl, type Category } from "../api";
|
import { assetUrl, type Category } from "../api";
|
||||||
@@ -173,12 +173,12 @@ function PopularRankRow({
|
|||||||
disabled={isDownloading}
|
disabled={isDownloading}
|
||||||
aria-label={t("download")}
|
aria-label={t("download")}
|
||||||
title={t("download")}
|
title={t("download")}
|
||||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-neutral-300 outline-none transition hover:bg-white/5 hover:text-ark-gold focus-visible:ring-2 focus-visible:ring-ark-gold/70 disabled:opacity-60"
|
className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#191921] text-white outline-none transition hover:bg-[#22232D] focus-visible:ring-2 focus-visible:ring-ark-gold/70 disabled:cursor-wait"
|
||||||
>
|
>
|
||||||
{isDownloading ? (
|
{isDownloading ? (
|
||||||
<LoaderCircle className="h-[18px] w-[18px] animate-spin" />
|
<LoaderCircle className="h-5 w-5 animate-spin" strokeWidth={2.3} />
|
||||||
) : (
|
) : (
|
||||||
<Download className="h-[18px] w-[18px]" />
|
<DownloadCloudIcon className="h-6 w-6" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -224,7 +224,7 @@ export function PopularRankList({
|
|||||||
const placeholderCount = Math.max(0, MAX_ITEMS - items.length);
|
const placeholderCount = Math.max(0, MAX_ITEMS - items.length);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto flex max-w-[760px] flex-col gap-2.5 px-4 md:gap-3 md:px-0">
|
<div className="mx-auto flex max-w-full flex-col gap-2.5 px-4 md:max-w-[820px] md:gap-3 md:px-0 lg:max-w-[1080px] xl:max-w-[1180px]">
|
||||||
{items.map((post, index) => (
|
{items.map((post, index) => (
|
||||||
<PopularRankRow
|
<PopularRankRow
|
||||||
key={post.id}
|
key={post.id}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const CARD_HOVER_SPRING = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const CARD_CAROUSEL_SIZE_CLASS =
|
const CARD_CAROUSEL_SIZE_CLASS =
|
||||||
"w-[208px] md:w-[240px] lg:w-[246.4px] min-[1100px]:max-xl:w-[273px] xl:w-[246.4px]";
|
"w-[208px] md:w-[240px] lg:w-[246.4px] min-[1100px]:w-[273px]";
|
||||||
|
|
||||||
const CARD_GRID_SIZE_CLASS = "w-full max-w-[360px] md:max-w-none";
|
const CARD_GRID_SIZE_CLASS = "w-full max-w-[360px] md:max-w-none";
|
||||||
|
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ export function PublicLayout() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav
|
<nav
|
||||||
className="header-nav-scroll hidden min-w-0 flex-1 items-center justify-center gap-4 overflow-x-auto overflow-y-hidden py-1 min-[1200px]:flex lg:gap-5"
|
className="header-nav-scroll hidden min-w-0 flex-1 items-center justify-center gap-4 overflow-x-auto overflow-y-hidden py-0.5 min-[1200px]:flex lg:gap-5"
|
||||||
aria-label={t("mainNav")}
|
aria-label={t("mainNav")}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
@@ -560,13 +560,6 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("latest")}
|
{t("latest")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to={popularHref}
|
|
||||||
className={navClassName(na("browsePopular"))}
|
|
||||||
aria-current={na("browsePopular") ? "page" : undefined}
|
|
||||||
>
|
|
||||||
{t("popular")}
|
|
||||||
</Link>
|
|
||||||
<Link
|
<Link
|
||||||
to="/favorites"
|
to="/favorites"
|
||||||
className={navClassName(na("favorites"))}
|
className={navClassName(na("favorites"))}
|
||||||
@@ -574,6 +567,13 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("favorites")}
|
{t("favorites")}
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={popularHref}
|
||||||
|
className={navClassName(na("browsePopular"))}
|
||||||
|
aria-current={na("browsePopular") ? "page" : undefined}
|
||||||
|
>
|
||||||
|
{t("popular")}
|
||||||
|
</Link>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
|
<div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
|
||||||
@@ -667,14 +667,6 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("latest")}
|
{t("latest")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to={popularHref}
|
|
||||||
className={mobileMenuNavClassName(na("browsePopular"))}
|
|
||||||
aria-current={na("browsePopular") ? "page" : undefined}
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
>
|
|
||||||
{t("popular")}
|
|
||||||
</Link>
|
|
||||||
<Link
|
<Link
|
||||||
to="/favorites"
|
to="/favorites"
|
||||||
className={mobileMenuNavClassName(na("favorites"))}
|
className={mobileMenuNavClassName(na("favorites"))}
|
||||||
@@ -683,6 +675,14 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("favorites")}
|
{t("favorites")}
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={popularHref}
|
||||||
|
className={mobileMenuNavClassName(na("browsePopular"))}
|
||||||
|
aria-current={na("browsePopular") ? "page" : undefined}
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
>
|
||||||
|
{t("popular")}
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -221,6 +221,9 @@ export function Home() {
|
|||||||
Math.round(recScroll.progress * (recommendedDotCount - 1)),
|
Math.round(recScroll.progress * (recommendedDotCount - 1)),
|
||||||
)
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
// Hide the arrow that points to an edge we're already at.
|
||||||
|
const recAtStart = recScroll.progress <= 0.01;
|
||||||
|
const recAtEnd = recScroll.progress >= 0.99;
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return (
|
return (
|
||||||
@@ -333,14 +336,15 @@ export function Home() {
|
|||||||
|
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<section id="official" className="scroll-mt-16 md:scroll-mt-24">
|
<section id="official" className="scroll-mt-16 md:scroll-mt-24">
|
||||||
<div className="px-4 md:px-0">
|
<div className="mx-auto max-w-full md:max-w-[820px] lg:max-w-[1080px] xl:max-w-[1180px]">
|
||||||
<SectionHeader
|
<div className="px-4 md:px-0">
|
||||||
title={t("officialSection")}
|
<SectionHeader
|
||||||
viewAllTo="/official-recommendations"
|
title={t("officialSection")}
|
||||||
viewAllLabel={t("viewAll")}
|
viewAllTo="/official-recommendations"
|
||||||
/>
|
viewAllLabel={t("viewAll")}
|
||||||
</div>
|
/>
|
||||||
<div className="relative">
|
</div>
|
||||||
|
<div className="relative">
|
||||||
<div
|
<div
|
||||||
ref={recRowRef}
|
ref={recRowRef}
|
||||||
className="mt-2.5 flex gap-3 overflow-x-auto overflow-y-hidden px-4 pb-0 pr-4 scroll-smooth [-ms-overflow-style:none] [scrollbar-width:none] md:mt-7 md:gap-4 md:px-0 md:pr-0 md:pb-5 [&::-webkit-scrollbar]:hidden"
|
className="mt-2.5 flex gap-3 overflow-x-auto overflow-y-hidden px-4 pb-0 pr-4 scroll-smooth [-ms-overflow-style:none] [scrollbar-width:none] md:mt-7 md:gap-4 md:px-0 md:pr-0 md:pb-5 [&::-webkit-scrollbar]:hidden"
|
||||||
@@ -386,26 +390,27 @@ export function Home() {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{canScrollRec ? (
|
{canScrollRec && !recAtStart ? (
|
||||||
<>
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
onClick={() => scrollRec(-1)}
|
||||||
onClick={() => scrollRec(-1)}
|
className="absolute left-0 top-[45%] hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-lg border border-ark-line bg-[#292a31]/95 text-neutral-200 shadow-lg backdrop-blur transition hover:border-ark-gold hover:text-ark-gold md:flex"
|
||||||
className="absolute left-0 top-[45%] hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-lg border border-ark-line bg-[#292a31]/95 text-neutral-200 shadow-lg backdrop-blur transition hover:border-ark-gold hover:text-ark-gold md:flex"
|
aria-label="Previous recommendations"
|
||||||
aria-label="Previous recommendations"
|
>
|
||||||
>
|
<ChevronLeft className="h-5 w-5" />
|
||||||
<ChevronLeft className="h-5 w-5" />
|
</button>
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => scrollRec(1)}
|
|
||||||
className="absolute right-0 top-[45%] hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-lg border border-ark-line bg-[#292a31]/95 text-neutral-200 shadow-lg backdrop-blur transition hover:border-ark-gold hover:text-ark-gold md:flex"
|
|
||||||
aria-label="Next recommendations"
|
|
||||||
>
|
|
||||||
<ChevronRight className="h-5 w-5" />
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
) : null}
|
) : null}
|
||||||
|
{canScrollRec && !recAtEnd ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => scrollRec(1)}
|
||||||
|
className="absolute right-0 top-[45%] hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-lg border border-ark-line bg-[#292a31]/95 text-neutral-200 shadow-lg backdrop-blur transition hover:border-ark-gold hover:text-ark-gold md:flex"
|
||||||
|
aria-label="Next recommendations"
|
||||||
|
>
|
||||||
|
<ChevronRight className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
|
|||||||
Reference in New Issue
Block a user