feat(board): Mehrfachauswahl fuer Status, Tags und Loeschen
Kaestchen auf jeder Karte, darunter eine Leiste am unteren Rand. Fest verankert, weil sie bei einer langen Liste oben laengst aus dem Blick gescrollt waere, waehrend man noch auswaehlt. Ein eigener Endpunkt statt vieler einzelner PATCHes: eine Transaktion statt zwanzig Rundgaengen, und der Verlauf bekommt je Projekt genau einen Eintrag statt eines Schwalls. Was der Filter ausblendet, faellt aus der Auswahl - sonst traefe eine Massenaenderung Projekte, die man gar nicht mehr vor Augen hat. Fremde IDs sammelt der Server wegen der Besitzerbedingung erst gar nicht ein und meldet sie als uebergangen. Das Kaestchen ist gedaempft, aber immer sichtbar. Erst beim Ueberfahren einzublenden waere auf einem Touchgeraet nicht erreichbar - und wer es nie sieht, weiss nicht, dass es die Auswahl gibt. Ansicht, Sortierung und Archivschalter ueberdauern nun das Neuladen. Wer sein Brett von Hand anordnet, will es beim naechsten Aufruf auch sehen. Der Suchbegriff bleibt aussen vor: eine Suche von gestern wiederherzustellen waere eher verwirrend. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,17 @@ const PROVIDER_LABEL: Record<string, string> = {
|
||||
* Karte im Board. Die gesamte Flaeche ist ein Link (per "stretched link"),
|
||||
* interaktive Elemente liegen darueber und bekommen pointer-events zurueck.
|
||||
*/
|
||||
export function ProjectCard({ project, index = 0 }: { project: ProjectListItem; index?: number }) {
|
||||
export function ProjectCard({
|
||||
project,
|
||||
index = 0,
|
||||
selected = false,
|
||||
onToggleSelect,
|
||||
}: {
|
||||
project: ProjectListItem;
|
||||
index?: number;
|
||||
selected?: boolean;
|
||||
onToggleSelect?: (id: string, selected: boolean) => void;
|
||||
}) {
|
||||
const accent = accentOf(project.accent);
|
||||
const priority = PRIORITY_META[project.priority] ?? PRIORITY_META[2];
|
||||
// Auf der Karte ist nur fuer eines Platz: das fuehrende. Wie viele es
|
||||
@@ -60,7 +70,10 @@ export function ProjectCard({ project, index = 0 }: { project: ProjectListItem;
|
||||
|
||||
return (
|
||||
<article
|
||||
className="glass card-glow fade-up group relative overflow-hidden p-5"
|
||||
className={cn(
|
||||
"glass card-glow fade-up group relative overflow-hidden p-5",
|
||||
selected && "ring-1 ring-violet-400/60",
|
||||
)}
|
||||
style={
|
||||
{
|
||||
"--accent-from": accent.from,
|
||||
@@ -81,6 +94,21 @@ export function ProjectCard({ project, index = 0 }: { project: ProjectListItem;
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Gedaempft, aber immer da. Nur beim Ueberfahren einzublenden
|
||||
waere auf einem Touchgeraet gar nicht erreichbar – und wer
|
||||
es nie sieht, weiss nicht, dass es die Auswahl gibt. */}
|
||||
{onToggleSelect ? (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selected}
|
||||
onChange={(event) => onToggleSelect(project.id, event.target.checked)}
|
||||
aria-label={`${project.name} auswaehlen`}
|
||||
className={cn(
|
||||
"pointer-events-auto h-3.5 w-3.5 shrink-0 accent-violet-500 transition-opacity",
|
||||
!selected && "opacity-35 group-hover:opacity-100 focus-visible:opacity-100",
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
<h3 className="truncate text-base font-semibold text-white transition-colors group-hover:text-violet-200">
|
||||
{project.name}
|
||||
</h3>
|
||||
|
||||
Reference in New Issue
Block a user