Skip to content

feat(core): floating image action panel in inspector#148

Merged
1weiho merged 3 commits into
mainfrom
feat/inspector-image-quick-actions
May 24, 2026
Merged

feat(core): floating image action panel in inspector#148
1weiho merged 3 commits into
mainfrom
feat/inspector-image-quick-actions

Conversation

@1weiho
Copy link
Copy Markdown
Owner

@1weiho 1weiho commented May 19, 2026

Summary

  • Adds a small floating toolbar below the inspector selection box when the selected element is an <img>, with quick-access Replace and Crop icon buttons (tooltips on hover).
  • Extracts AssetPickerDialog into its own module (asset-picker-dialog.tsx) so it can be mounted as a singleton at the provider level — mirrors how ImageCropDialog is already wired up.
  • Adds openReplace(anchor) to the inspector context. The floating toolbar and the side panel's ImageField now share the same flow (and the same objectFit / objectPosition defaults applied on first pick).

Why

Replace and Crop are the two image actions users reach for most. Surfacing them inline next to the selection — instead of forcing a trip to the side panel — makes the inspector feel a lot more direct.

Notes for reviewers

  • The floating panel is rendered inside InspectOverlay, uses the same morph transition as the selection box, and carries data-inspector-ui so clicks on it don't bubble back into the inspector's selection handler.
  • ImageField lost its local useState/AssetPickerDialog — it now calls openReplace(anchor) from context. The asset-pick handling (path resolution, default object-fit/position) moved into the provider unchanged.
  • No locale strings were added; the toolbar reuses t.inspector.replace and t.inspector.crop.

Test plan

  • Open inspector, click on an image — floating panel appears below the selection box.
  • Click Replace icon → AssetPickerDialog opens; picking an asset swaps the image.
  • Click Crop icon → ImageCropDialog opens and applies.
  • Side panel Replace/Crop buttons still work (they share the same flow now).
  • Double-click on an image still opens the crop dialog directly.
  • Floating panel tracks the selection box smoothly when switching between images.
  • pnpm typecheck, pnpm check, pnpm test all green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Floating image action panel appears when an image is selected, offering Replace and Crop actions beneath the inspector.
    • New asset picker dialog for choosing or uploading images (per-slide or global) with drag‑and‑drop, upload spinner, and error feedback.
  • Bug Fixes

    • Inspector hover/interaction now ignores pointer events from the inspector UI to prevent accidental hover changes while interacting.
  • Refactor

    • Internal inspector flows streamlined; replace/crop actions now use the centralized picker.

Review Change Stack

Show a small floating toolbar below the inspector selection box when an
image is selected, with quick-access Replace and Crop icons. Extract
AssetPickerDialog into its own module and add an openReplace callback
to the inspector context so the floating panel and the side panel share
the same flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
open-slide-demo Ready Ready Preview, Comment May 24, 2026 11:55am
open-slide-web Ready Ready Preview, Comment May 24, 2026 11:55am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Walkthrough

Adds a reusable AssetPickerDialog (image selection/upload with slide/global scopes), a floating Replace/Crop action panel in the inspector overlay, provider-level openReplace/replaceTarget wiring that buffers edit ops on selection, and refactors the inspector panel to use the new dialog.

Changes

Image Replace and Quick Actions

Layer / File(s) Summary
Asset Picker Dialog component
packages/core/src/app/components/inspector/asset-picker-dialog.tsx
New reusable dialog for selecting images from slide or global assets, with thumbnail grid, upload via file input and drag-and-drop, error handling, and refresh logic.
Image action panel UI in overlay
packages/core/src/app/components/inspector/inspect-overlay.tsx
Floating toolbar positioned below selected images showing Replace and Crop buttons with localized tooltips; uses inspector context handlers and prevents hover updates while interacting with inspector UI.
Inspector provider replace feature
packages/core/src/app/components/inspector/inspector-provider.tsx
Adds replaceTarget state and openReplace(anchor) to the InspectorCtx; renders AssetPickerDialog when set and buffers edit ops to update image src and optionally set objectFit/objectPosition.
Inspector panel refactoring
packages/core/src/app/components/inspector/inspector-panel.tsx
Removes in-file AssetPickerDialog, simplifies ImageField to accept only src and anchor, removes local picker state, and delegates picker behavior to the new AssetPickerDialog.
Changeset documentation
.changeset/inspector-image-quick-actions.md
Minor release-level bump for @open-slide/core documenting the new inspector quick-actions UI (Replace/Crop).

Sequence Diagram

sequenceDiagram
  participant User
  participant ImageActionPanel
  participant InspectorProvider
  participant AssetPickerDialog
  participant EditBuffer
  User->>ImageActionPanel: click Replace
  ImageActionPanel->>InspectorProvider: openReplace(anchor)
  InspectorProvider->>InspectorProvider: set replaceTarget(anchor)
  InspectorProvider->>AssetPickerDialog: render (slideId / scope)
  User->>AssetPickerDialog: select or upload image
  AssetPickerDialog->>InspectorProvider: onPick(asset, scope)
  InspectorProvider->>EditBuffer: bufferOps(set-attr-asset, optional style ops)
  InspectorProvider->>InspectorProvider: clear replaceTarget()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • 1weiho/open-slide#91: Overlaps inspector upload/replace flow wiring and use of uploadWithAutoRename + drag/drop behavior.
  • 1weiho/open-slide#114: Related to global-assets scope and picker behavior shared by the new AssetPickerDialog.

Poem

🐇 A rabbit hops to swap a pic,

Click Replace — the change is quick,
Crop it neat, align and play,
Assets chosen, bright as day,
Inspector hums and hops away.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main feature being introduced: a floating image action panel in the inspector with quick-access Replace and Crop buttons.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/inspector-image-quick-actions.md:
- Line 5: Update the changeset line that currently reads "Show a floating action
panel below the inspector selection box when an image is selected, with
quick-access Replace and Crop icons." to a present-tense descriptive sentence
(e.g., "Displays a floating action panel below the inspector selection box when
an image is selected, with quick-access Replace and Crop icons.") so the
one-line changeset uses present-tense description; edit the line containing the
original sentence to the new phrasing using the same wording scope.

In `@packages/core/src/app/components/inspector/inspect-overlay.tsx`:
- Around line 213-220: The ImageActionPanel is being mounted for any selected
element (rect && selectedAnchor) which leaves hidden but focusable buttons in
the DOM; change the render guard to mount ImageActionPanel only when the
selection is an image (e.g. add a check like selectedAnchor?.type === 'image' or
selectedAnchor?.kind === 'image' depending on the anchor shape used in your
code) so the component is not mounted for non-image selections; apply the same
conditional change to the other ImageActionPanel render sites in this file (the
block around lines 227-290) so invisible focusable controls are never present.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ac0641e2-5c4d-410d-bfae-1b28dc9dc8e2

📥 Commits

Reviewing files that changed from the base of the PR and between a8c702b and 2fcbecf.

📒 Files selected for processing (5)
  • .changeset/inspector-image-quick-actions.md
  • packages/core/src/app/components/inspector/asset-picker-dialog.tsx
  • packages/core/src/app/components/inspector/inspect-overlay.tsx
  • packages/core/src/app/components/inspector/inspector-panel.tsx
  • packages/core/src/app/components/inspector/inspector-provider.tsx

"@open-slide/core": minor
---

Show a floating action panel below the inspector selection box when an image is selected, with quick-access Replace and Crop icons.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use present-tense descriptive wording in the changeset line.

Line 5 reads like an imperative (“Show ...”) rather than a present-tense description. Please switch to descriptive present tense.

Suggested wording
-Show a floating action panel below the inspector selection box when an image is selected, with quick-access Replace and Crop icons.
+Displays a floating action panel below the inspector selection box for selected images with quick-access Replace and Crop icons.

As per coding guidelines, "Changeset descriptions must be short and direct: one line, present-tense, describing what changed from a user's perspective. No paragraphs, no rationale, no 'this PR…'."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Show a floating action panel below the inspector selection box when an image is selected, with quick-access Replace and Crop icons.
Displays a floating action panel below the inspector selection box for selected images with quick-access Replace and Crop icons.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/inspector-image-quick-actions.md at line 5, Update the changeset
line that currently reads "Show a floating action panel below the inspector
selection box when an image is selected, with quick-access Replace and Crop
icons." to a present-tense descriptive sentence (e.g., "Displays a floating
action panel below the inspector selection box when an image is selected, with
quick-access Replace and Crop icons.") so the one-line changeset uses
present-tense description; edit the line containing the original sentence to the
new phrasing using the same wording scope.

Comment thread packages/core/src/app/components/inspector/inspect-overlay.tsx Outdated
…quick-actions

# Conflicts:
#	packages/core/src/app/components/inspector/inspect-overlay.tsx
#	packages/core/src/app/components/inspector/inspector-provider.tsx
Tag tooltip content with data-inspector-ui (Radix portals it outside
the overlay) and clear hover when the pointer enters inspector UI,
matching the existing click/dblclick early-returns.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

🧹 Nitpick comments (1)
packages/core/src/app/components/inspector/inspect-overlay.tsx (1)

232-241: 💤 Low value

Consider tightening anchor prop type to HTMLImageElement.

Since ImageActionPanel is only rendered when imageAnchor (an HTMLImageElement) exists (line 218), the prop type could be HTMLImageElement instead of HTMLElement. This would eliminate the cast on line 285.

Proposed type tightening
 function ImageActionPanel({
   anchor,
   rect,
   visible,
   transition,
 }: {
-  anchor: HTMLElement;
+  anchor: HTMLImageElement;
   rect: RelRect;
   visible: boolean;
   transition: string;
 }) {

And remove the cast:

-                openCrop(anchor as HTMLImageElement);
+                openCrop(anchor);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/app/components/inspector/inspect-overlay.tsx` around lines
232 - 241, Tighten the ImageActionPanel prop type by changing the anchor
parameter from HTMLElement to HTMLImageElement and remove the runtime cast where
anchor is used (the cast referencing imageAnchor usage). Update the
ImageActionPanel function signature and any call sites (e.g., where imageAnchor
is passed) so the prop is typed as HTMLImageElement, ensuring TypeScript
recognizes image-specific properties without casting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/core/src/app/components/inspector/inspect-overlay.tsx`:
- Around line 232-241: Tighten the ImageActionPanel prop type by changing the
anchor parameter from HTMLElement to HTMLImageElement and remove the runtime
cast where anchor is used (the cast referencing imageAnchor usage). Update the
ImageActionPanel function signature and any call sites (e.g., where imageAnchor
is passed) so the prop is typed as HTMLImageElement, ensuring TypeScript
recognizes image-specific properties without casting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f6c2f67-def1-4727-8a63-540f6c195167

📥 Commits

Reviewing files that changed from the base of the PR and between 2fcbecf and e2e16a2.

📒 Files selected for processing (3)
  • packages/core/src/app/components/inspector/inspect-overlay.tsx
  • packages/core/src/app/components/inspector/inspector-panel.tsx
  • packages/core/src/app/components/inspector/inspector-provider.tsx

@1weiho 1weiho merged commit 78333bc into main May 24, 2026
8 checks passed
@github-actions github-actions Bot mentioned this pull request May 24, 2026
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.

1 participant