fix: make entire candidate row draggable instead of handle-only

Remove dragControls/dragListener pattern which prevented onReorder
from firing. The whole row is now the drag target with visual feedback
(scale + shadow). Grip icon remains as a visual indicator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 18:46:52 +02:00
parent 684cfd3789
commit 27c36b6b9a

View File

@@ -1,4 +1,4 @@
import { Reorder, useDragControls } from "framer-motion"; import { Reorder } from "framer-motion";
import { useFormatters } from "../hooks/useFormatters"; import { useFormatters } from "../hooks/useFormatters";
import type { CandidateDelta } from "../hooks/useImpactDeltas"; import type { CandidateDelta } from "../hooks/useImpactDeltas";
import { LucideIcon } from "../lib/iconData"; import { LucideIcon } from "../lib/iconData";
@@ -56,7 +56,6 @@ export function CandidateListItem({
delta, delta,
onDragEnd, onDragEnd,
}: CandidateListItemProps) { }: CandidateListItemProps) {
const controls = useDragControls();
const { weight, price } = useFormatters(); const { weight, price } = useFormatters();
const openCandidateEditPanel = useUIStore((s) => s.openCandidateEditPanel); const openCandidateEditPanel = useUIStore((s) => s.openCandidateEditPanel);
const openConfirmDeleteCandidate = useUIStore( const openConfirmDeleteCandidate = useUIStore(
@@ -70,16 +69,11 @@ export function CandidateListItem({
const innerContent = ( const innerContent = (
<> <>
{/* Drag handle */} {/* Drag handle indicator */}
{isActive && ( {isActive && (
<button <span className="text-gray-300 shrink-0">
type="button"
onPointerDown={(e) => controls.start(e)}
className="cursor-grab active:cursor-grabbing text-gray-300 hover:text-gray-500 touch-none shrink-0"
title="Drag to reorder"
>
<LucideIcon name="grip-vertical" size={16} /> <LucideIcon name="grip-vertical" size={16} />
</button> </span>
)} )}
{/* Rank badge */} {/* Rank badge */}
@@ -217,12 +211,15 @@ export function CandidateListItem({
return ( return (
<Reorder.Item <Reorder.Item
value={candidate} value={candidate}
dragControls={controls}
dragListener={false}
onDragEnd={onDragEnd} onDragEnd={onDragEnd}
layout="position" layout="position"
whileDrag={{
scale: 1.02,
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
cursor: "grabbing",
}}
transition={{ layout: { duration: 0.15, ease: "easeOut" } }} transition={{ layout: { duration: 0.15, ease: "easeOut" } }}
style={{ marginBottom: 8 }} style={{ marginBottom: 8, cursor: "grab" }}
className={sharedClassName} className={sharedClassName}
> >
{innerContent} {innerContent}