campaigns: collapse curated lists strip after first 5 pills

This commit is contained in:
mkfain
2026-06-02 00:16:14 +02:00
parent 399dc53395
commit d4cf4ba0d8
17 changed files with 89 additions and 17 deletions
@@ -4,6 +4,8 @@ import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import {
ArrowUpToLine,
ChevronDown,
ChevronUp,
MoreVertical,
Pencil,
Plus,
@@ -39,6 +41,9 @@ import { cn } from '@/lib/utils';
const DRAG_MIME = 'text/x-agora-campaign-list-coord';
/** How many pills to show before collapsing the rest behind a "Show more". */
const COLLAPSED_COUNT = 5;
/**
* Horizontal scrollable strip of moderator-curated campaign list pills.
*
@@ -69,6 +74,7 @@ export function CampaignListsStrip() {
const [editTarget, setEditTarget] = useState<ParsedCampaignList | null>(null);
const [deleteTarget, setDeleteTarget] = useState<ParsedCampaignList | null>(null);
const [optimisticOrder, setOptimisticOrder] = useState<readonly string[] | null>(null);
const [expanded, setExpanded] = useState(false);
const lists = useMemo(() => data?.lists ?? [], [data]);
const authoritativeCoords = useMemo(() => lists.map((l) => l.aTag), [lists]);
@@ -180,6 +186,28 @@ export function CampaignListsStrip() {
return null;
}
const visible = displayed.slice(0, COLLAPSED_COUNT);
const overflow = displayed.slice(COLLAPSED_COUNT);
const canExpand = overflow.length > 0;
const renderPill = (list: ParsedCampaignList, idx: number) => (
<ListPill
key={list.aTag}
list={list}
index={idx}
isMod={actions.isMod}
isMobile={isMobile}
onDropAt={(coord) => moveTo(coord, idx)}
onEdit={() => setEditTarget(list)}
onDelete={() => setDeleteTarget(list)}
onMoveUp={() => moveTo(list.aTag, Math.max(0, idx - 1))}
onMoveDown={() => moveTo(list.aTag, idx + 1)}
onMoveToStart={() => moveTo(list.aTag, 0)}
canMoveUp={idx > 0}
canMoveDown={idx < displayed.length - 1}
/>
);
return (
<>
<section
@@ -187,23 +215,35 @@ export function CampaignListsStrip() {
aria-label={t('campaigns.lists.stripAria')}
>
<div className="flex flex-wrap gap-2">
{displayed.map((list, idx) => (
<ListPill
key={list.aTag}
list={list}
index={idx}
isMod={actions.isMod}
isMobile={isMobile}
onDropAt={(coord) => moveTo(coord, idx)}
onEdit={() => setEditTarget(list)}
onDelete={() => setDeleteTarget(list)}
onMoveUp={() => moveTo(list.aTag, Math.max(0, idx - 1))}
onMoveDown={() => moveTo(list.aTag, idx + 1)}
onMoveToStart={() => moveTo(list.aTag, 0)}
canMoveUp={idx > 0}
canMoveDown={idx < displayed.length - 1}
/>
))}
{visible.map((list, i) => renderPill(list, i))}
{expanded &&
overflow.map((list, i) => renderPill(list, i + COLLAPSED_COUNT))}
{canExpand && (
<button
type="button"
onClick={() => setExpanded((v) => !v)}
aria-expanded={expanded}
className={cn(
'inline-flex items-center gap-1.5 rounded-full border px-3.5 py-2 text-sm whitespace-nowrap shrink-0',
'border-border bg-background hover:border-primary/40 hover:bg-primary/5 text-muted-foreground hover:text-foreground',
'motion-safe:transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
)}
>
{expanded ? (
<>
<ChevronUp className="size-4 shrink-0" aria-hidden />
<span>{t('campaigns.lists.showLess')}</span>
</>
) : (
<>
<ChevronDown className="size-4 shrink-0" aria-hidden />
<span>
{t('campaigns.lists.showMore', { count: overflow.length })}
</span>
</>
)}
</button>
)}
{actions.isMod && (
<button
type="button"
+2
View File
@@ -803,6 +803,8 @@
"lists": {
"stripAria": "قوائم مواضيع منتقاة للحملات",
"create": "قائمة جديدة",
"showMore": "إظهار {{count}} أخرى",
"showLess": "إظهار أقل",
"createDesc": "أنشئ قائمة مواضيع جديدة. ثم انتقِ إليها حملات من أي صفحة حملة.",
"createSubmit": "إنشاء القائمة",
"createFailed": "فشل إنشاء القائمة",
+2
View File
@@ -1247,6 +1247,8 @@
"lists": {
"stripAria": "Curated campaign topic lists",
"create": "New list",
"showMore": "Show {{count}} more",
"showLess": "Show less",
"createDesc": "Create a new topic list. Curate campaigns into it from any campaign page.",
"createSubmit": "Create list",
"createFailed": "Failed to create list",
+2
View File
@@ -817,6 +817,8 @@
"lists": {
"stripAria": "Listas temáticas de campañas curadas",
"create": "Nueva lista",
"showMore": "Mostrar {{count}} más",
"showLess": "Mostrar menos",
"createDesc": "Crea una nueva lista temática. Cura campañas en ella desde cualquier página de campaña.",
"createSubmit": "Crear lista",
"createFailed": "No se pudo crear la lista",
+2
View File
@@ -817,6 +817,8 @@
"lists": {
"stripAria": "فهرست‌های منتخب موضوعی کمپین‌ها",
"create": "فهرست جدید",
"showMore": "نمایش {{count}} مورد بیشتر",
"showLess": "نمایش کمتر",
"createDesc": "یک فهرست موضوعی جدید بسازید. از هر صفحهٔ کمپین، کمپین‌ها را به آن اضافه کنید.",
"createSubmit": "ساخت فهرست",
"createFailed": "ساخت فهرست ناموفق بود",
+2
View File
@@ -1248,6 +1248,8 @@
"lists": {
"stripAria": "Listes thématiques de campagnes",
"create": "Nouvelle liste",
"showMore": "Afficher {{count}} de plus",
"showLess": "Afficher moins",
"createDesc": "Créez une nouvelle liste thématique. Ajoutez-y des campagnes depuis n'importe quelle page de campagne.",
"createSubmit": "Créer la liste",
"createFailed": "Échec de la création de la liste",
+2
View File
@@ -1221,6 +1221,8 @@
"lists": {
"stripAria": "क्यूरेटेड कैंपेन टॉपिक सूचियाँ",
"create": "नई सूची",
"showMore": "{{count}} और दिखाएँ",
"showLess": "कम दिखाएँ",
"createDesc": "एक नई टॉपिक सूची बनाएँ। किसी भी कैंपेन पेज से कैंपेन उसमें जोड़कर क्यूरेट करें।",
"createSubmit": "सूची बनाएँ",
"createFailed": "सूची नहीं बनाई जा सकी",
+2
View File
@@ -1221,6 +1221,8 @@
"lists": {
"stripAria": "Daftar topik kampanye terkurasi",
"create": "Daftar baru",
"showMore": "Tampilkan {{count}} lagi",
"showLess": "Tampilkan lebih sedikit",
"createDesc": "Buat daftar topik baru. Kurasi kampanye ke dalamnya dari halaman kampanye mana pun.",
"createSubmit": "Buat daftar",
"createFailed": "Gagal membuat daftar",
+2
View File
@@ -817,6 +817,8 @@
"lists": {
"stripAria": "បញ្ជីប្រធានបទយុទ្ធនាការដែលបានសម្រិតសម្រាំង",
"create": "បញ្ជីថ្មី",
"showMore": "បង្ហាញ {{count}} ទៀត",
"showLess": "បង្ហាញតិច",
"createDesc": "បង្កើតបញ្ជីប្រធានបទថ្មី។ សម្រិតសម្រាំងយុទ្ធនាការទៅក្នុងវាពីទំព័រយុទ្ធនាការណាមួយ។",
"createSubmit": "បង្កើតបញ្ជី",
"createFailed": "បរាជ័យក្នុងការបង្កើតបញ្ជី",
+2
View File
@@ -819,6 +819,8 @@
"lists": {
"stripAria": "د کمپاین موضوعاتو ترتیب شوي لیستونه",
"create": "نوی لیست",
"showMore": "{{count}} نور وښایه",
"showLess": "لږ وښایه",
"createDesc": "د موضوع یو نوی لیست جوړ کړئ. د هر کمپاین له پاڼې څخه کمپاینونه پکې ترتیب کړئ.",
"createSubmit": "لیست جوړ کړئ",
"createFailed": "د لیست جوړول ناکام شول",
+2
View File
@@ -1251,6 +1251,8 @@
"lists": {
"stripAria": "Listas de tópicos de campanhas curadas",
"create": "Nova lista",
"showMore": "Mostrar mais {{count}}",
"showLess": "Mostrar menos",
"createDesc": "Crie uma nova lista de tópicos. Curadoria de campanhas para ela a partir de qualquer página de campanha.",
"createSubmit": "Criar lista",
"createFailed": "Falha ao criar lista",
+2
View File
@@ -1251,6 +1251,8 @@
"lists": {
"stripAria": "Кураторские тематические списки кампаний",
"create": "Новый список",
"showMore": "Показать ещё {{count}}",
"showLess": "Скрыть",
"createDesc": "Создайте новый тематический список. Добавляйте в него кампании с любой страницы кампании.",
"createSubmit": "Создать список",
"createFailed": "Не удалось создать список",
+2
View File
@@ -819,6 +819,8 @@
"lists": {
"stripAria": "Manjuriro emisoro yemishandirapamwe yakasarudzwa",
"create": "Rondedzero itsva",
"showMore": "Ratidza {{count}} dzimwe",
"showLess": "Ratidza zvishoma",
"createDesc": "Gadzira rondedzero itsva yemisoro. Sarudza mishandirapamwe muiri kubva papeji ipi neipi yemushandirapamwe.",
"createSubmit": "Gadzira rondedzero",
"createFailed": "Kugadzira rondedzero hakuna kubudirira",
+2
View File
@@ -1220,6 +1220,8 @@
"lists": {
"stripAria": "Orodha za mada za kampeni zilizoratibiwa",
"create": "Orodha mpya",
"showMore": "Onyesha {{count}} zaidi",
"showLess": "Onyesha kidogo",
"createDesc": "Tengeneza orodha mpya ya mada. Iratibu kampeni ndani yake kutoka ukurasa wowote wa kampeni.",
"createSubmit": "Tengeneza orodha",
"createFailed": "Imeshindikana kutengeneza orodha",
+2
View File
@@ -1222,6 +1222,8 @@
"lists": {
"stripAria": "Özenle seçilmiş kampanya konu listeleri",
"create": "Yeni liste",
"showMore": "{{count}} tane daha göster",
"showLess": "Daha az göster",
"createDesc": "Yeni bir konu listesi oluşturun. Herhangi bir kampanya sayfasından kampanyaları listeye ekleyin.",
"createSubmit": "Liste oluştur",
"createFailed": "Liste oluşturulamadı",
+2
View File
@@ -791,6 +791,8 @@
"lists": {
"stripAria": "精選活動主題清單",
"create": "新清單",
"showMore": "再顯示 {{count}} 個",
"showLess": "顯示較少",
"createDesc": "建立一個新的主題清單。可從任何活動頁面將活動加入其中。",
"createSubmit": "建立清單",
"createFailed": "無法建立清單",
+2
View File
@@ -819,6 +819,8 @@
"lists": {
"stripAria": "精选活动主题列表",
"create": "新建列表",
"showMore": "再显示 {{count}} 个",
"showLess": "显示较少",
"createDesc": "创建一个新的主题列表。可以从任意活动页面将活动收录其中。",
"createSubmit": "创建列表",
"createFailed": "创建列表失败",