feat(ui): one CountBadge for all counters; counters on tab corners
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m30s

- CountBadge component (accent / muted, inline / corner, 99+, showZero);
  used in the nav bar, task list and list tabs, admin organizations and
  numeric badges of the mobile menu; old badge-count removed
- Counters sit on the top right corner of tabs; "Alle Aufgaben" gets one
  (desktop tab and mobile menu)
- Open/done task counters include tasks in shared lists, matching what
  "Alle Aufgaben" shows (nav counter was too low)
- Theme template derives --accent-dim/--accent-border from the accent
- Docs: ui-patterns counters section

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-28 22:54:15 +01:00
1 parent a354f3d008
commit a62b204e14
12 files changed
+167 -55

No files matched your search

@@ -14,6 +14,7 @@ import { ListItem, SharedList, ListShare, Team, User, WSMessage } from '../../li
import { api, buildWebSocketURL, triggerHaptic, createRealtimeConnection, RealtimeTransport } from '../../lib/api';
import { UnifiedShareModal } from '../../components/UnifiedShareModal';
import { AvatarStack, AvatarPerson } from '../../components/AvatarStack';
import { CountBadge } from '../../components/CountBadge';
import { useMobileActions } from '../../context/MobileActionContext';
interface SharedListsViewProps {
@@ -842,8 +843,8 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
<div className="w-full space-y-3">
{/* Top Header: List Tabs & Actions (Desktop) */}
<div className="hidden sm:flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2 !mt-0">
{/* List Tabs */}
<div className="flex flex-wrap items-center gap-1">
{/* List Tabs (counters sit on the top right corner, hence the extra gap) */}
<div className="flex flex-wrap items-center gap-x-3 gap-y-3 pt-2">
{lists.map((lst) => {
const openCount = deduplicateItems(lst.items || []).filter((i) => !i.isCompleted).length;
const isSelected = activeList?.id === lst.id;
@@ -860,9 +861,6 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
>
<span>{lst.icon}</span>
<span>{lst.title}</span>
{openCount > 0 && (
<span className="ml-1 badge-count">{openCount}</span>
)}
<AvatarStack
people={otherMembers(lst)}
size="xxs"
@@ -870,6 +868,7 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
className="ml-0.5"
/>
</button>
<CountBadge count={openCount} position="corner" />
{isSelected && lists.length > 1 && (
<button
onClick={() => handleDeleteList(lst.id)}