From d410fa5c805037633cefbce4f2a9b700d085faa2 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sun, 8 Mar 2026 07:14:24 -0700 Subject: [PATCH] fix(avocet): restore drag aura color feedback via updateAura in useCardAnimation --- web/src/components/EmailCardStack.test.ts | 1 + web/src/components/EmailCardStack.vue | 5 ++- web/src/composables/useCardAnimation.test.ts | 38 ++++++++++++++++++++ web/src/composables/useCardAnimation.ts | 19 +++++++++- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/web/src/components/EmailCardStack.test.ts b/web/src/components/EmailCardStack.test.ts index 84c7a4c..42dd9e3 100644 --- a/web/src/components/EmailCardStack.test.ts +++ b/web/src/components/EmailCardStack.test.ts @@ -8,6 +8,7 @@ vi.mock('../composables/useCardAnimation', () => ({ setDragPosition: vi.fn(), snapBack: vi.fn(), animateDismiss: vi.fn(), + updateAura: vi.fn(), })), })) diff --git a/web/src/components/EmailCardStack.vue b/web/src/components/EmailCardStack.vue index 122cc7f..ddef4c5 100644 --- a/web/src/components/EmailCardStack.vue +++ b/web/src/components/EmailCardStack.vue @@ -54,7 +54,7 @@ const motion = useMotion() const cardEl = ref(null) const isExpanded = ref(false) -const { pickup, setDragPosition, snapBack, animateDismiss } = useCardAnimation(cardEl, motion) +const { pickup, setDragPosition, snapBack, animateDismiss, updateAura } = useCardAnimation(cardEl, motion) watch(() => props.dismissType, (type) => { if (type) animateDismiss(type) @@ -122,6 +122,7 @@ function onPointerMove(e: PointerEvent) { hoveredBucketName.value = bucketName emit('bucket-hover', bucketName) } + updateAura(hoveredZone.value, hoveredBucketName.value) } function onPointerUp(e: PointerEvent) { @@ -169,6 +170,7 @@ function onPointerUp(e: PointerEvent) { } else { // Snap back snapBack() + updateAura(null, null) hoveredZone.value = null hoveredBucketName.value = null } @@ -179,6 +181,7 @@ function onPointerCancel(e: PointerEvent) { ;(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId) isHeld.value = false snapBack() + updateAura(null, null) hoveredZone.value = null hoveredBucketName.value = null velocityBuf = [] diff --git a/web/src/composables/useCardAnimation.test.ts b/web/src/composables/useCardAnimation.test.ts index 04005c1..fb11a25 100644 --- a/web/src/composables/useCardAnimation.test.ts +++ b/web/src/composables/useCardAnimation.test.ts @@ -101,4 +101,42 @@ describe('useCardAnimation', () => { animateDismiss('label') expect(mockAnimate).not.toHaveBeenCalled() }) + + describe('updateAura', () => { + it('sets red background for discard zone', () => { + const el = makeEl() + const cardEl = ref(el) + const motion = { rich: ref(true) } + const { updateAura } = useCardAnimation(cardEl, motion) + updateAura('discard', null) + expect(mockSet).toHaveBeenCalledWith(el, expect.objectContaining({ background: 'rgba(244, 67, 54, 0.25)' })) + }) + + it('sets orange background for skip zone', () => { + const el = makeEl() + const cardEl = ref(el) + const motion = { rich: ref(true) } + const { updateAura } = useCardAnimation(cardEl, motion) + updateAura('skip', null) + expect(mockSet).toHaveBeenCalledWith(el, expect.objectContaining({ background: 'rgba(255, 152, 0, 0.25)' })) + }) + + it('sets blue background for bucket hover', () => { + const el = makeEl() + const cardEl = ref(el) + const motion = { rich: ref(true) } + const { updateAura } = useCardAnimation(cardEl, motion) + updateAura(null, 'interview_scheduled') + expect(mockSet).toHaveBeenCalledWith(el, expect.objectContaining({ background: 'rgba(42, 96, 128, 0.20)' })) + }) + + it('sets transparent background when no zone/bucket', () => { + const el = makeEl() + const cardEl = ref(el) + const motion = { rich: ref(true) } + const { updateAura } = useCardAnimation(cardEl, motion) + updateAura(null, null) + expect(mockSet).toHaveBeenCalledWith(el, expect.objectContaining({ background: 'transparent' })) + }) + }) }) diff --git a/web/src/composables/useCardAnimation.ts b/web/src/composables/useCardAnimation.ts index 00a2f8b..28bd0b0 100644 --- a/web/src/composables/useCardAnimation.ts +++ b/web/src/composables/useCardAnimation.ts @@ -63,5 +63,22 @@ export function useCardAnimation( } } - return { pickup, setDragPosition, snapBack, animateDismiss } + const AURA_COLORS = { + discard: 'rgba(244, 67, 54, 0.25)', + skip: 'rgba(255, 152, 0, 0.25)', + bucket: 'rgba(42, 96, 128, 0.20)', + none: 'transparent', + } as const + + function updateAura(zone: 'discard' | 'skip' | null, bucket: string | null) { + if (!cardEl.value) return + const color = + zone === 'discard' ? AURA_COLORS.discard : + zone === 'skip' ? AURA_COLORS.skip : + bucket ? AURA_COLORS.bucket : + AURA_COLORS.none + utils.set(cardEl.value, { background: color }) + } + + return { pickup, setDragPosition, snapBack, animateDismiss, updateAura } }