homepage: add topic chips + date filters to Industry News section (matches /news page UX)
This commit is contained in:
@@ -26,7 +26,21 @@ interface ArticleItem {
|
||||
|
||||
|
||||
|
||||
const ALL_CATEGORIES = ["All", "BROADCAST", "POST PRODUCTION", "ANIMATION"];
|
||||
// Match the topic list on /news for a consistent filter experience sitewide.
|
||||
const ALL_CATEGORIES = [
|
||||
"All",
|
||||
"Cloud",
|
||||
"AI",
|
||||
"IP Workflows",
|
||||
"Live Production",
|
||||
"Streaming",
|
||||
"Audio",
|
||||
"Cameras",
|
||||
"NAB 2026",
|
||||
"EAS",
|
||||
"Sports Broadcasting",
|
||||
"Ad Tech",
|
||||
];
|
||||
const SOURCE_FILTERS = ["All", "Live", "Imported"] as const;
|
||||
type SourceFilter = typeof SOURCE_FILTERS[number];
|
||||
type FeedMode = "pagination" | "infinite";
|
||||
@@ -141,7 +155,8 @@ export default function ArticleFeed() {
|
||||
|
||||
// Filter articles
|
||||
const filtered = allArticles.filter((a) => {
|
||||
const matchCat = activeCategory === "All" || a.category === activeCategory;
|
||||
const matchCat = activeCategory === "All"
|
||||
|| (a.category || "").toLowerCase().includes(activeCategory.toLowerCase());
|
||||
const matchSource =
|
||||
sourceFilter === "All" ||
|
||||
(sourceFilter === "Imported" && a.source === "imported") ||
|
||||
@@ -337,10 +352,39 @@ export default function ArticleFeed() {
|
||||
<span className="font-body text-xs text-[#555]">{sortedFiltered.length?.toLocaleString()} article{sortedFiltered.length !== 1 ? "s" : ""}</span>
|
||||
</div>
|
||||
|
||||
{/* Filters only — site-wide search lives in the top-right header */}
|
||||
{/* Filters — topic chips + date range visible by default, advanced (author + source) behind toggle */}
|
||||
<div className="mb-4 space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Advanced filters toggle button */}
|
||||
{/* Row: date range + advanced toggle */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<input
|
||||
type="date"
|
||||
value={dateFrom}
|
||||
onChange={(e) => { setDateFrom(e.target.value); setPage(1); }}
|
||||
max={dateTo || undefined}
|
||||
className="bg-[#1a1a1a] border border-[#2a2a2a] text-[#888] text-xs font-body px-3 py-2 rounded-sm focus:outline-none focus:border-[#3b82f6] transition-colors [color-scheme:dark]"
|
||||
title="From date"
|
||||
aria-label="Filter articles from date"
|
||||
/>
|
||||
<span className="text-[#444] text-xs">–</span>
|
||||
<input
|
||||
type="date"
|
||||
value={dateTo}
|
||||
onChange={(e) => { setDateTo(e.target.value); setPage(1); }}
|
||||
min={dateFrom || undefined}
|
||||
className="bg-[#1a1a1a] border border-[#2a2a2a] text-[#888] text-xs font-body px-3 py-2 rounded-sm focus:outline-none focus:border-[#3b82f6] transition-colors [color-scheme:dark]"
|
||||
title="To date"
|
||||
aria-label="Filter articles to date"
|
||||
/>
|
||||
{(dateFrom || dateTo) && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { setDateFrom(""); setDateTo(""); setPage(1); }}
|
||||
className="text-[#666] hover:text-[#aaa] text-xs font-body underline"
|
||||
aria-label="Clear date range">
|
||||
clear dates
|
||||
</button>
|
||||
)}
|
||||
<div className="flex-1" />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowAdvanced((v) => !v)}
|
||||
@@ -354,13 +398,37 @@ export default function ArticleFeed() {
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M1 3h10M3 6h6M5 9h2" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||
</svg>
|
||||
Filters
|
||||
More
|
||||
{hasAdvancedActive && (
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#3b82f6] inline-block ml-0.5" aria-label="Active filters" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Row: topic chips */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="text-[#555] text-[10px] font-body uppercase tracking-wider shrink-0">Topics:</span>
|
||||
<div className="flex gap-1.5 flex-wrap">
|
||||
{ALL_CATEGORIES.map((cat) => {
|
||||
const isActive = activeCategory === cat;
|
||||
return (
|
||||
<button
|
||||
key={cat}
|
||||
type="button"
|
||||
onClick={() => { setActiveCategory(cat); setPage(1); }}
|
||||
aria-pressed={isActive}
|
||||
className={`px-3 py-1.5 rounded-sm font-body text-[11px] font-semibold uppercase tracking-wide transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] ${
|
||||
isActive
|
||||
? "bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/50"
|
||||
: "bg-[#111] text-[#888] border border-[#2a2a2a] hover:text-[#ccc] hover:border-[#3a3a3a]"
|
||||
}`}>
|
||||
{cat}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Advanced filters panel */}
|
||||
{showAdvanced && (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user