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:
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user