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:
TerryM
2026-05-31 02:04:26 +08:00
parent 9ac072e8d8
commit 320e09cc87
5 changed files with 55 additions and 50 deletions

View File

@@ -301,7 +301,7 @@ export function FigmaBanner() {
) : null;
return (
<div className="relative">
<div className="relative md:mx-auto md:max-w-[680px] lg:max-w-[800px]">
<div
ref={scrollerRef}
onPointerDown={handlePointerDown}

View File

@@ -1,6 +1,5 @@
import {
Archive,
Download,
File,
FileText,
Image as ImageIcon,
@@ -11,6 +10,7 @@ import {
Video,
type LucideIcon,
} from "lucide-react";
import { DownloadCloudIcon } from "./icons/DownloadCloudIcon";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { assetUrl, type Category } from "../api";
@@ -173,12 +173,12 @@ function PopularRankRow({
disabled={isDownloading}
aria-label={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 ? (
<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>
) : null}
@@ -224,7 +224,7 @@ export function PopularRankList({
const placeholderCount = Math.max(0, MAX_ITEMS - items.length);
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) => (
<PopularRankRow
key={post.id}

View File

@@ -28,7 +28,7 @@ const CARD_HOVER_SPRING = {
} as const;
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";

View File

@@ -529,7 +529,7 @@ export function PublicLayout() {
</div>
<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")}
>
<Link
@@ -560,13 +560,6 @@ export function PublicLayout() {
>
{t("latest")}
</Link>
<Link
to={popularHref}
className={navClassName(na("browsePopular"))}
aria-current={na("browsePopular") ? "page" : undefined}
>
{t("popular")}
</Link>
<Link
to="/favorites"
className={navClassName(na("favorites"))}
@@ -574,6 +567,13 @@ export function PublicLayout() {
>
{t("favorites")}
</Link>
<Link
to={popularHref}
className={navClassName(na("browsePopular"))}
aria-current={na("browsePopular") ? "page" : undefined}
>
{t("popular")}
</Link>
</nav>
<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")}
</Link>
<Link
to={popularHref}
className={mobileMenuNavClassName(na("browsePopular"))}
aria-current={na("browsePopular") ? "page" : undefined}
onClick={() => setOpen(false)}
>
{t("popular")}
</Link>
<Link
to="/favorites"
className={mobileMenuNavClassName(na("favorites"))}
@@ -683,6 +675,14 @@ export function PublicLayout() {
>
{t("favorites")}
</Link>
<Link
to={popularHref}
className={mobileMenuNavClassName(na("browsePopular"))}
aria-current={na("browsePopular") ? "page" : undefined}
onClick={() => setOpen(false)}
>
{t("popular")}
</Link>
</div>
) : null}
</header>

View File

@@ -221,6 +221,9 @@ export function Home() {
Math.round(recScroll.progress * (recommendedDotCount - 1)),
)
: 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) {
return (
@@ -333,6 +336,7 @@ export function Home() {
<Reveal>
<section id="official" className="scroll-mt-16 md:scroll-mt-24">
<div className="mx-auto max-w-full md:max-w-[820px] lg:max-w-[1080px] xl:max-w-[1180px]">
<div className="px-4 md:px-0">
<SectionHeader
title={t("officialSection")}
@@ -386,8 +390,7 @@ export function Home() {
/>
))}
</div>
{canScrollRec ? (
<>
{canScrollRec && !recAtStart ? (
<button
type="button"
onClick={() => scrollRec(-1)}
@@ -396,6 +399,8 @@ export function Home() {
>
<ChevronLeft className="h-5 w-5" />
</button>
) : null}
{canScrollRec && !recAtEnd ? (
<button
type="button"
onClick={() => scrollRec(1)}
@@ -404,9 +409,9 @@ export function Home() {
>
<ChevronRight className="h-5 w-5" />
</button>
</>
) : null}
</div>
</div>
</section>
</Reveal>