5105ac224c
* feat: add anchored range selection to multi-select reducer * feat: cmd+click and shift+click multi-select on kanban board * feat: add cmd/shift multi-select to sidebar task list * test: e2e coverage for cmd/shift multi-select * fix: harden multi-select selection lifecycle from review feedback * test: scope multi-select e2e helpers to active containers * fix: add sidebar multi-select hook tests and tighten bulk-action lifecycle * fix: prune hidden sidebar selections and order bulk moves by view * test: cover visible-order bulk move and anchor realignment * fix: harden sidebar bulk-move scope and keyboard selection parity * fix: order kanban bulk moves by board position * test: cover multi-select helpers and fix stale-id sort fallback * fix: order kanban card context-menu moves by board position * feat: sidebar multi-select shows only bulk-valid actions with bulk pin and delete * fix: harden multi-select bulk ordering, selection clearing, and a11y * fix: gate kanban card move-to-step for mixed-workflow selections * fix: unpin fully pinned sidebar selections * refactor: keep sidebar task components under limits * test: restore sidebar selection console spy safely
50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
import { IconChevronDown } from "@tabler/icons-react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
export function TaskSwitcherSkeleton() {
|
|
return (
|
|
<div className="animate-pulse">
|
|
<div className="h-10 bg-foreground/5" />
|
|
<div className="h-10 bg-foreground/5 mt-px" />
|
|
<div className="h-10 bg-foreground/5 mt-px" />
|
|
<div className="h-10 bg-foreground/5 mt-px" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function GroupHeader({
|
|
label,
|
|
groupKey,
|
|
count,
|
|
isCollapsed,
|
|
onToggle,
|
|
}: {
|
|
label: string;
|
|
groupKey: string;
|
|
count: number;
|
|
isCollapsed: boolean;
|
|
onToggle: () => void;
|
|
}) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={onToggle}
|
|
data-testid="sidebar-group-header"
|
|
data-group-key={groupKey}
|
|
data-group-label={label}
|
|
className="flex w-full items-center gap-2 bg-background px-3 py-1.5 cursor-pointer hover:bg-foreground/[0.03]"
|
|
>
|
|
<span className="flex-1 truncate text-left text-[12px] font-medium text-foreground/80">
|
|
{label}
|
|
</span>
|
|
<span className="text-[11px] text-muted-foreground/50">{count}</span>
|
|
<IconChevronDown
|
|
className={cn(
|
|
"h-3 w-3 text-muted-foreground/40 transition-transform",
|
|
isCollapsed && "-rotate-90",
|
|
)}
|
|
/>
|
|
</button>
|
|
);
|
|
}
|