tasks.md 9.2 KB

Implementation Plan

  • 1. Stabilize the Editing User List
  • 1.1 Fix awareness state filter (undefined → skip) — Req 1.1, 1.4
  • [x] 1.2 Remove direct mutation of Yjs-managed awareness map — Req 1.2

  • [x] 2. Build the Rich Cursor Extension (Initial)

  • [x] 2.1 (P) Cursor widget DOM: name label, avatar image, initials fallback — Req 3.4, 3.5

  • [x] 2.2 (P) Broadcast local cursor position to awareness — Req 3.6, 3.7

  • [x] 2.3 (P) Render remote cursor decorations from awareness — Req 3.6, 3.7

  • [x] 3. Integrate Rich Cursor Extension into Editor Configuration — Req 1.3, 2.4, 3.6

  • [x] 4. Unit Tests for Core Behaviors (Initial)

  • [x] 4.1 (P) Awareness state filtering and mutation-free disconnect — Req 1.1, 1.2, 1.4

  • [x] 4.2 (P) Cursor widget construction, equality, avatar fallback — Req 3.4, 3.5

  • [x] 5. Integration Tests for Multi-Client Collaborative Scenarios

  • [x] 5.1 Awareness update flow to EditingUserList — Req 1.3, 2.1, 2.4

  • [x] 5.2 Cursor position broadcasting and remote rendering — Req 3.6, 3.7

  • [x] 6. Add baseTheme with Overlay Positioning, Hover, and Opacity Rules

  • [x] 6.1 (P) Cursor overlay CSS rules — Req 3.1, 3.2, 3.3, 3.8, 3.9

  • [x] 6.2 (P) Off-screen container and indicator styles — Req 4.5, 4.7

  • [x] 7. Rework RichCaretWidget for Overlay Avatar with Activity State

  • [x] 7.1 Widget DOM: overlay flag, avatar/initials, hover name label, isActive — Req 3.1–3.5, 3.10

  • [x] 7.2 Activity tracking with per-client timers (3s inactivity) — Req 3.10

  • [x] 8. Build Off-Screen Cursor Indicators

  • [x] 8.1 Persistent off-screen containers on editor DOM — Req 4.7

  • [x] 8.2 Classify cursors by visible range, render indicators — Req 4.1–4.6

  • [x] 9. Unit Tests for Updated Widget and Off-Screen Indicators

  • [x] 9.1 (P) Widget DOM structure, sizing, isActive, borderColor — Req 3.1–3.5, 3.10

  • [x] 9.2 (P) Off-screen indicator DOM, Material Symbols arrow, avatar fallback — Req 4.1, 4.2, 4.4, 4.9

  • [x] 10. Integration Tests for Viewport Classification and Activity Tracking

  • [x] 10.1 Off-screen exclusion from widget decorations — Req 4.3, 4.6

  • [x] 10.2 Activity tracking timer lifecycle (fake timers) — Req 3.10

  • [x] 12. Fix Off-Screen Visibility Classification

  • [x] 12.1 Multi-mode classification: rangedMode / coordsMode / degenerate — Req 4.1–4.3, 4.6

  • [x] 12.2 Integration test for render-buffer cursor → off-screen indicator — Req 4.3, 4.6

  • [ ]* 11. E2E Tests for Hover, Opacity, and Off-Screen Transitions (deferred)

  • [ ]* 11.1 (P) Hover behavior on cursor overlay flag — Req 3.3, 3.9

  • [ ]* 11.2 (P) Off-screen indicator visibility on scroll — Req 4.1–4.3, 4.6


Phase 2: Color-Matched Avatars & Click-to-Scroll (Requirements 5–6)

  • 13. Scroll callback infrastructure
  • [x] 13.1 (P) Create a Jotai atom for storing the scroll-to-remote-cursor callback

    • Define an atom that holds either a scroll function accepting a client ID or null
    • Export a reader hook and a setter hook, following the same pattern as the existing editing-clients atom
    • Requirements: 6.1
  • [x] 13.2 (P) Extend the collaborative editor mode hook to create and register a scroll-to-remote-cursor function

    • Add a new callback option to the hook's configuration that receives the scroll function when the provider and document are ready, and null on cleanup
    • The scroll function reads the target user's cursor position from awareness, resolves the Yjs relative position to an absolute document index, and dispatches a vertically centered scroll command to the CodeMirror editor view
    • Guard against missing cursor data and unmounted editor view by returning silently
    • Requirements: 6.1, 6.2, 6.3
  • [x] 14. (P) Update EditingUserList with color-matched borders and click-to-scroll

    • Replace the fixed blue border on each avatar with a wrapper element whose border color matches the user's cursor color from the awareness state
    • Accept a new click callback prop and wrap each avatar in a clickable element with pointer cursor styling
    • Replace the generic UserPictureList component in the overflow popover with inline rendering so that color-matched borders and click handling apply to all avatars consistently
    • Requirements: 5.1, 5.2, 5.3, 6.4, 6.5
  • [x] 15. Connect all components end-to-end

    • Bridge the scroll-ready callback through the main editor component's props into the collaborative editor mode hook
    • Wire the page editor to store the received scroll callback in the Jotai atom
    • Wire the editor navbar to read the atom and pass the scroll function to the editing user list as the click callback
    • Verify that clicking an avatar scrolls the editor to that user's remote cursor position; verify no-op for users without a cursor
    • Requirements: 6.1, 6.5
  • [x]* 16. Test coverage for color-matched borders and click-to-scroll

  • [x]* 16.1 (P) Unit tests for EditingUserList rendering and click behavior

    • Verify that each avatar renders a colored border matching the user's cursor color instead of the fixed blue
    • Verify that clicking an avatar invokes the callback with the correct client ID
    • Verify that overflow popover avatars also invoke the callback on click
    • Requirements: 5.1, 6.4, 6.5
  • [x]* 16.2 (P) Integration test for the scroll function in the collaborative editor mode hook

    • Verify that the configuration callback receives a function when the provider is set up
    • Verify that calling the scroll function with a valid remote client ID dispatches a centered scroll effect to the editor view
    • Verify that calling the scroll function for a client without a cursor position is a silent no-op
    • Requirements: 6.1, 6.2, 6.3

Phase 3: Off-Screen Indicator Click & Username Tooltip (Requirements 6.6–6.7, 7)

  • 17. Add click-to-scroll to off-screen cursor indicators
  • [x] 17.1 Extend the off-screen indicator to accept and fire a click callback

    • Add a user identifier and an optional click callback to the indicator creation options
    • Attach a click event listener on the indicator's root element that invokes the callback with the user identifier
    • Apply pointer cursor styling when a click handler is provided; omit it when not
    • Requirements: 6.6, 6.7
  • [x] 17.2 Wire the scroll function to off-screen indicators via a mutable ref in the editor mode hook

    • Accept a mutable ref option in the rich cursor extension factory for the indicator click callback
    • When building off-screen indicators, pass the ref's current value as the click handler for each indicator
    • In the collaborative editor mode hook, create the mutable ref alongside the extension, write the existing scroll function to it when the provider is ready, and clear it on cleanup
    • Requirements: 6.6
  • [x] 18. (P) Refactor the UserPicture component to eliminate the tooltip higher-order component

    • Remove the higher-order component that wraps the root element and tooltip in a React Fragment
    • Render the tooltip directly within the component's render body as a child of the root element, conditionally based on the noTooltip flag
    • Preserve the dynamic import for the tooltip component so that consumers who suppress tooltips never trigger the tooltip chunk load
    • Move the ref for tooltip targeting into the component body (unconditional call) and pass it to the root element via its existing forwardRef support
    • The root element is always a single span, making it safe inside flex containers
    • Requirements: 7.1, 7.3, 7.4, 7.5
  • [x] 19. Enable the native UserPicture tooltip in EditingUserList

    • Remove the tooltip-suppression flag from UserPicture in the avatar wrapper so the built-in tooltip renders automatically for all avatars
    • Both the first-four direct avatars and the overflow popover avatars use the same wrapper, so tooltips appear uniformly
    • Requirements: 7.2
    • Depends on: Task 18
  • [x]* 20. Test coverage for off-screen click and tooltip refactoring

  • [x]* 20.1 (P) Unit tests for off-screen indicator click behavior

    • Verify the indicator root has pointer cursor when a click handler is provided
    • Verify clicking the indicator calls the callback with the correct user identifier
    • Verify no click handler or pointer cursor when the callback is omitted
    • Requirements: 6.6, 6.7
  • [x]* 20.2 (P) Integration test for off-screen indicator scroll wiring

    • Verify that when the mutable ref holds a function and an off-screen indicator is clicked, the function is called with the correct user identifier
    • Verify that clicking when the ref is null does not throw
    • Requirements: 6.6
  • [x]* 20.3 (P) Unit tests for UserPicture tooltip refactoring

    • Verify that without the tooltip-suppression flag, the component renders a single root element containing the image and a portal tooltip
    • Verify that with the tooltip-suppression flag, only the image is rendered inside the root element
    • Verify tooltip content includes the username prefix and display name
    • Requirements: 7.1, 7.3, 7.4
  • [x]* 20.4 Unit tests for EditingUserList tooltip integration

    • Verify the avatar wrapper renders UserPicture without the tooltip-suppression flag
    • Verify tooltips are present for both direct avatars and overflow popover avatars
    • Requirements: 7.2