From 11b78433a99f8cca0829117adc3d4145fe89f437 Mon Sep 17 00:00:00 2001 From: tuyenio Date: Tue, 23 Jun 2026 16:30:05 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20thi=E1=BA=BFt=20k=E1=BA=BF=20l=E1=BA=A1?= =?UTF-8?q?i=20b=E1=BB=99=20l=E1=BB=8Dc=20/di-tich=20+=20marquee=20cu?= =?UTF-8?q?=E1=BB=99n=20li=C3=AAn=20t=E1=BB=A5c=20(lu=C3=B4n=20b=E1=BA=ADt?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bộ lọc cao cấp: ô tìm kiếm bo tròn full-width có nút xóa, tóm tắt số kết quả, 3 hàng lọc có nhãn + chip kèm số đếm, tóm tắt bộ lọc đang áp dụng + xóa tất cả - Marquee tên di tích: animation luôn bật (gỡ cổng no-preference khiến đứng yên), vẫn cuộn chậm nhẹ dưới reduced-motion Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landing/CulturalSpaceExplorer.tsx | 227 +++++++++++------- src/app/globals.css | 16 +- 2 files changed, 154 insertions(+), 89 deletions(-) diff --git a/src/app/components/landing/CulturalSpaceExplorer.tsx b/src/app/components/landing/CulturalSpaceExplorer.tsx index 26fe998..52b72bd 100644 --- a/src/app/components/landing/CulturalSpaceExplorer.tsx +++ b/src/app/components/landing/CulturalSpaceExplorer.tsx @@ -2,7 +2,7 @@ import Image from "next/image"; import Link from "next/link"; -import { ArrowRight, Search, SlidersHorizontal } from "lucide-react"; +import { ArrowRight, Search, SlidersHorizontal, X } from "lucide-react"; import { useMemo, useState } from "react"; import type { HeritageSite } from "@/app/content"; @@ -38,74 +38,98 @@ export function CulturalSpaceExplorer({ sites }: { sites: HeritageSite[] }) { }); }, [query, sites, status, level, type]); + const count = (key: "status" | "level" | "type", value: string) => { + if (value === "Tất cả") return sites.length; + return sites.filter((s) => s[key] === value).length; + }; + + const hasActiveFilters = + query.trim().length > 0 || status !== "Tất cả" || level !== "Tất cả" || type !== "Tất cả"; + + const resetAll = () => { + setQuery(""); + setStatus("Tất cả"); + setLevel("Tất cả"); + setType("Tất cả"); + }; + return (
-
-
-
); } -function FilterGroup({ +function FilterRow({ label, options, value, onChange, + count, }: { label: string; options: T; value: T[number]; onChange: (value: T[number]) => void; + count: (option: T[number]) => number; }) { return ( -
- {label} -
- {options.map((option) => ( - - ))} +
+ + {label} + +
+ {options.map((option) => { + const active = value === option; + return ( + + ); + })}
); } + +function ActiveChip({ label, onClear }: { label: string; onClear: () => void }) { + return ( + + {label} + + + ); +} diff --git a/src/app/globals.css b/src/app/globals.css index 5ef08ee..845959c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1430,15 +1430,19 @@ a { white-space: nowrap; will-change: transform; transform: translate3d(0, 0, 0); + /* Cuộn liên tục phải -> trái, luôn bật (di chuyển nhẹ ngay cả khi giảm chuyển động). */ + animation: heritage-marquee 42s linear infinite; } -@media (prefers-reduced-motion: no-preference) { - .heritage-marquee-track { - animation: heritage-marquee 42s linear infinite; - } +.heritage-marquee:hover .heritage-marquee-track { + animation-play-state: paused; +} - .heritage-marquee:hover .heritage-marquee-track { - animation-play-state: paused; +/* Ghi đè khối reduce toàn cục: vẫn cuộn nhưng chậm, nhẹ nhàng. */ +@media (prefers-reduced-motion: reduce) { + .heritage-marquee-track { + animation-duration: 90s !important; + animation-iteration-count: infinite !important; } }