Skip to content

Gizmo kb controls#539

Merged
tracygardner merged 10 commits intoflipcomputing:mainfrom
lawsie:gizmo-kb-controls
Apr 16, 2026
Merged

Gizmo kb controls#539
tracygardner merged 10 commits intoflipcomputing:mainfrom
lawsie:gizmo-kb-controls

Conversation

@lawsie
Copy link
Copy Markdown
Contributor

@lawsie lawsie commented Apr 15, 2026

Summary

A yellow circle 'cursor' (canvasCircle) is implemented to be controlled by the keyboard within the canvas in place of the mouse cursor, for placing objects, selecting objects to colour etc. This code has been moved to its own module so that it can be reused whenever a canvasCircle is needed. There can only ever be one canvasCircle active at one time.

  • canvasCircle is used to place objects
  • canvasCircle is used to select objects to colour in using the colour picker
  • If the canvasCircle is currently hovering over an invalid placement, change the cursor to a 'no entry' cursor 🚫. This is context-dependent - the sky is an invalid place for object placement, but not invalid for colour picker fill.

This will be helpful in the future for other gizmos which need to use the canvasCircle.

Claude Sonnet 4.6 was used as a pair programmer collaborator, but all decisions and design were made by a human.

Summary by CodeRabbit

  • New Features

    • Added a visual canvas selector indicator that appears during keyboard-based placement and color-picking workflows, with real-time validation feedback and animations for invalid placement attempts.
  • Refactor

    • Consolidated multiple keyboard navigation implementations into a unified, reusable canvas utilities system for consistent interaction patterns across placement and selection operations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

Warning

Rate limit exceeded

@lawsie has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 21 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 28 minutes and 21 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 65853d0a-a026-4b0e-8947-0b93cac3ffa3

📥 Commits

Reviewing files that changed from the base of the PR and between aff0ee8 and b1853e4.

📒 Files selected for processing (1)
  • ui/gizmos.js
📝 Walkthrough

Walkthrough

This pull request consolidates keyboard placement and color-picking modes from multiple files into a shared canvas-utils.js module. The changes add CSS styling for a canvas selector circle indicator and refactor addmenu.js and gizmos.js to delegate their keyboard navigation logic to the new utility API.

Changes

Cohort / File(s) Summary
Canvas Selector Styling
style.css
Adds CSS rules for a fixed-position yellow circle (.canvas-selector-circle) with transform-based centering, shadow effects, and an invalid-state modifier class (.canvas-selector-circle--no-hit) that includes a rotated diagonal bar pseudo-element and red shadow. Defines a circle-invalid-flash keyframe animation applied when invalid placement is attempted.
Shared Keyboard Navigation Module
ui/canvas-utils.js
New module providing centralized canvas selector circle management with keyboard navigation support. Exports functions to create/destroy the circle, update position (with canvas boundary clamping), and enable keyboard mode with arrow keys (shift for larger steps), Enter/Space to select, and Escape to exit. Includes optional hit-validation predicate and invalid-press flash animation triggering.
Keyboard Mode Refactoring
ui/addmenu.js, ui/gizmos.js
Both files remove local keyboard placement/color-picking implementations (state variables, handlers, circle rendering) and delegate to startCanvasKeyboardMode() / stopCanvasKeyboardMode() from the new shared module. Menu navigation gating in addmenu.js is simplified by removing the local keyboardPlacementMode state check.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A circle dances on the canvas bright,
No more duplicated code in sight!
Keyboard arrows now share the way,
One module rules them all today. ✨
From yellow dot to validated click,
Refactoring magic does the trick!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Gizmo kb controls' is vague and generic. It uses abbreviated terminology ('kb' for keyboard, 'gizmo') without clearly conveying the actual changes: introducing a reusable canvas selector circle module for keyboard-controlled object placement and color picking. Clarify the title to describe the main change more specifically, such as 'Extract canvas selector circle to shared keyboard-navigation module' or 'Add reusable keyboard-controlled canvas selector for placement and color picking'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lawsie lawsie marked this pull request as ready for review April 16, 2026 09:24
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ui/gizmos.js (1)

140-168: ⚠️ Potential issue | 🟠 Major

Tear down the window click picker on every exit path.

onPickMesh only unregisters itself when the user clicks outside the canvas. If Escape or disableGizmos() ends color-picking, this window listener survives, so later clicks can still repaint meshes after the mode was cancelled. Re-entering the mode will also stack another listener.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/gizmos.js` around lines 140 - 168, The window click listener added in
pickMeshFromCanvas (onPickMesh) is only removed when clicking outside the
canvas, causing leaked listeners when color-picking is cancelled via Escape or
disableGizmos(); fix by centralizing cleanup: create a cleanup function that
removes window.removeEventListener("click", onPickMesh), clears any pending
setTimeout handle, calls stopCanvasKeyboardMode(), and restores cursors, then
ensure this cleanup is invoked both from onPickMesh's outside-canvas branch and
passed into startCanvasKeyboardMode's cancel/escape handler (and also called
whenever disableGizmos() cancels the mode); also remove any pre-existing
onPickMesh listener before adding to avoid stacking.
🧹 Nitpick comments (1)
ui/canvas-utils.js (1)

3-4: Trim the narration comments in this module.

Most of these comments just restate the next line and make a small utility file harder to scan. Please keep only the ones that add non-obvious context.

As per coding guidelines, "Comments should be infrequent" and "Comments should be genuinely noteworthy".

Also applies to: 11-11, 16-16, 24-24, 28-28, 33-33, 42-42, 49-49, 72-74, 81-81, 88-88, 107-107, 120-120, 124-124, 131-131, 167-168, 184-184

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/canvas-utils.js` around lines 3 - 4, Remove trivial "narration" comments
that merely restate the next line and retain only comments that add non-obvious
context or API usage notes; specifically remove or shorten the
duplicate/descriptive comments (e.g., the "Create yellow circle for canvas
position indicator" style lines and the other occurrences called out at lines
11,16,24,28,33,42,49,72-74,81,88,107,120,124,131,167-168,184) so the helper file
is easier to scan, but keep concise JSDoc or explanatory notes for exported
functions and any comments that explain non-obvious behavior or important
tradeoffs in functions in this module.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/addmenu.js`:
- Around line 819-838: The call to startCanvasKeyboardMode uses
keyboardNavigationActive which has already been reset by callers (so
showCircleImmediately is effectively false); capture the pre-clear state into a
local variable (e.g. wasKeyboardNavigationActive) before
removeKeyboardNavigation() is called, and pass that variable as the second
argument to startCanvasKeyboardMode instead of reading keyboardNavigationActive
directly; update references in startPlacementKeyboardMode to use that saved
value so the visible circle is shown immediately when placement was started via
keyboard.

In `@ui/gizmos.js`:
- Around line 25-30: Remove the unused imports getCanvasCircle and
destroyCanvasCircle from the import list in the top-level import statement
(leave only startCanvasKeyboardMode and stopCanvasKeyboardMode), so ESLint no
longer flags them as dead code; alternatively, if those functions should be
used, add the missing references where appropriate, but the minimal fix is to
delete the two unused symbols from the import.

---

Outside diff comments:
In `@ui/gizmos.js`:
- Around line 140-168: The window click listener added in pickMeshFromCanvas
(onPickMesh) is only removed when clicking outside the canvas, causing leaked
listeners when color-picking is cancelled via Escape or disableGizmos(); fix by
centralizing cleanup: create a cleanup function that removes
window.removeEventListener("click", onPickMesh), clears any pending setTimeout
handle, calls stopCanvasKeyboardMode(), and restores cursors, then ensure this
cleanup is invoked both from onPickMesh's outside-canvas branch and passed into
startCanvasKeyboardMode's cancel/escape handler (and also called whenever
disableGizmos() cancels the mode); also remove any pre-existing onPickMesh
listener before adding to avoid stacking.

---

Nitpick comments:
In `@ui/canvas-utils.js`:
- Around line 3-4: Remove trivial "narration" comments that merely restate the
next line and retain only comments that add non-obvious context or API usage
notes; specifically remove or shorten the duplicate/descriptive comments (e.g.,
the "Create yellow circle for canvas position indicator" style lines and the
other occurrences called out at lines
11,16,24,28,33,42,49,72-74,81,88,107,120,124,131,167-168,184) so the helper file
is easier to scan, but keep concise JSDoc or explanatory notes for exported
functions and any comments that explain non-obvious behavior or important
tradeoffs in functions in this module.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 75064fba-6811-4bc5-80a3-4d785c555e45

📥 Commits

Reviewing files that changed from the base of the PR and between 68acfad and aff0ee8.

📒 Files selected for processing (4)
  • style.css
  • ui/addmenu.js
  • ui/canvas-utils.js
  • ui/gizmos.js

Comment thread ui/addmenu.js
Comment thread ui/gizmos.js
@tracygardner tracygardner merged commit 03ab56f into flipcomputing:main Apr 16, 2026
5 checks passed
@lawsie lawsie deleted the gizmo-kb-controls branch April 16, 2026 09:57
@lawsie lawsie mentioned this pull request Apr 16, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants