Files
kite/.planning/milestones/v0.2-phases/10-ux-interaction/10-11-SUMMARY.md
T
curo1305andClaude Sonnet 4.6 123ae5b29b chore: archive v0.2 phase directories to milestones/v0.2-phases/
Moves phases 08–11 execution artifacts from .planning/phases/ to
.planning/milestones/v0.2-phases/ to keep .planning/phases/ clean
for the next milestone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:34:52 +02:00

5.0 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
10-ux-interaction 11 frontend/interaction
drag-to-move
teleport
dropdown
click-guard
ux
requires provides affects
10-06
10-09
10-10
10-05
UX-11-complete
UX-13-complete
StorageBrowser.vue
DocumentCard.vue
FolderRow.vue
added patterns
Teleport to body + getBoundingClientRect for overflow-safe dropdown positioning
nextTick-deferred draggingFile reset to prevent click-after-drag navigation
created modified
frontend/src/components/storage/StorageBrowser.vue
frontend/src/components/documents/DocumentCard.vue
frontend/src/components/folders/FolderRow.vue
frontend/src/components/storage/__tests__/StorageBrowser.dragmove.test.js
frontend/src/components/ui/__tests__/dropdown.test.js
D-18 scope confirmed: DocumentCard.vue has no draggable attribute in Phase 10; the dragend-then-click guard (D-18 goal) is correctly implemented on StorageBrowser file rows which are the actual drag sources. No additional drag handle needed in DocumentCard.
Folder picker file ID stored in folderPickerFileId reactive ref; trigger button tracked in Map for scroll repositioning
nextTick deferred reset chosen over synchronous reset to reliably suppress the browser's click event that fires after dragend
duration completed tasks_completed tasks_total files_changed
~20 minutes 2026-06-16 4 4 5

Phase 10 Plan 11: Drag-to-Move Click Guard + Teleported Dropdowns Summary

One-liner: Click-after-drag guard with nextTick reset in StorageBrowser; all three dropdown menus (StorageBrowser folder picker, DocumentCard folder picker, FolderRow three-dot menu) teleported to body with getBoundingClientRect positioning.

What Was Built

UX-11: Drag-to-Move Completion

The drag-to-move highlight and drop handlers were already wired from plan 10-06. This plan added the missing pieces:

  1. Click-after-drag guard — file-row @click now checks draggingFile ? null : $emit('file-open', file). While a drag is in progress, clicks on file rows are suppressed.

  2. onFileDragEnd() handler — defers draggingFile = null via nextTick() instead of synchronously resetting. This ensures the click event fired by the browser immediately after dragend still sees draggingFile as non-null and gets suppressed.

  3. onDropDocOnFolder updated — also uses await nextTick() before clearing draggingFile for the drop-on-folder case.

UX-13: Teleported Dropdowns

Three dropdowns replaced their position: absolute approach with <Teleport to="body"> + getBoundingClientRect fixed positioning:

  • StorageBrowser folder picker — single shared teleport block; trigger mapped by fileId in a Map for scroll repositioning. openFolderPicker(fileId, $event) captures the trigger and computes initial position.
  • DocumentCard folder pickerpickerTriggerEl ref on the button; updatePickerPosition() called on toggle, scroll, and resize.
  • FolderRow three-dot menumenuTriggerEl ref on the button; updateMenuPosition() called on toggle, scroll, and resize. Menu anchored to right edge of trigger via rect.right - 160.

All three follow the scroll-reposition pattern from SearchableModelSelect.vue.

Tests

File Tests Result
StorageBrowser.dragmove.test.js 6 All pass
dropdown.test.js 4 All pass
Full suite 208 All pass (3 pre-existing todos in skeleton test)

Commits

Hash Type Description
f20420a test Promote stub tests to real tests (RED phase)
f9ddda8 feat Click-after-drag guard + teleport folder picker in StorageBrowser
e0606b4 feat Teleport DocumentCard folder picker
892abca feat Teleport FolderRow three-dot menu

Deviations from Plan

None — plan executed exactly as written.

D-18 Scope Decision

Per the plan's locked decision and confirmed during implementation: DocumentCard.vue does NOT have draggable="true" in Phase 10. It is not a drag source. The dragend-then-click guard (D-18's protection goal) is fully satisfied by the onFileDragEnd + click guard implemented on StorageBrowser file rows, which ARE the drag sources.

If DocumentCard.vue gains draggable="true" in a future phase, it will need its own drag handle at that time.

Known Stubs

None.

Threat Flags

None — no new network endpoints, auth paths, file access patterns, or schema changes introduced.

Self-Check: PASSED

Files exist:

  • frontend/src/components/storage/StorageBrowser.vue — FOUND
  • frontend/src/components/documents/DocumentCard.vue — FOUND
  • frontend/src/components/folders/FolderRow.vue — FOUND
  • frontend/src/components/storage/__tests__/StorageBrowser.dragmove.test.js — FOUND
  • frontend/src/components/ui/__tests__/dropdown.test.js — FOUND

Commits exist: f20420a, f9ddda8, e0606b4, 892abca — all verified in git log.

Test suite: 208 passed, 0 failed.