Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mcp-server/src/tools/hotspot-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const accessibilitySchema = {
export const hotspotTools = [
{
name: "create_hotspot",
description: "Add a hotspot (tap area) to a screen. Coordinates are percentages (0-100) of the screen image dimensions. If action is 'navigate' or 'modal' and targetScreenId is provided, a connection is automatically created.",
description: "Add a hotspot (tap area) to a screen. Coordinates are percentages (0-100) of the screen image dimensions. If action is 'navigate' or 'modal' and targetScreenId is provided, a connection is automatically created. Hotspots on a canonical component apply to every placement; hotspots on an instance are placement-specific additive interactions that do not modify or hide the canonical's hotspots.",
inputSchema: {
type: "object",
properties: {
Expand Down Expand Up @@ -120,7 +120,7 @@ export const hotspotTools = [
},
{
name: "list_hotspots",
description: "List all hotspots on a specific screen.",
description: "List all hotspots on a specific screen. On a canonical component, this returns the hotspots that apply to every placement. On an instance, this returns only the placement-specific (additive) hotspots — to see the canonical's hotspots, call this against the canonical screen.",
inputSchema: {
type: "object",
properties: {
Expand Down
4 changes: 1 addition & 3 deletions src/components/CanvasArea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT } from "../constants";
import { copyScreenForFigma, copyScreensForFigma, copyScreensForFigmaEditable, downloadScreenSvg } from "../utils/copyToFigma";
import { copyScreensAsImage } from "../utils/copyAsImage";
import { ScreenNode } from "./ScreenNode";
import { resolveInstanceVisuals, isResolvedInstance } from "../utils/resolveInstanceVisuals";
import { resolveInstanceVisuals } from "../utils/resolveInstanceVisuals";
import { ConnectionLines } from "./ConnectionLines";
import { ConditionalPrompt } from "./ConditionalPrompt";
import { ConnectionTypePrompt } from "./ConnectionTypePrompt";
Expand Down Expand Up @@ -163,12 +163,10 @@ export function CanvasArea({
))}
{screens.map((screen) => {
const visualScreen = resolveInstanceVisuals(screen, screens);
const instanceVisual = isResolvedInstance(screen) && visualScreen !== screen;
return (
<ScreenNode
key={screen.id}
screen={visualScreen}
isInstanceVisual={instanceVisual}
selected={selectedScreen === screen.id}
onSelect={(id) => { clearSelection(); setSelectedScreen(id); setSelectedStickyNote(null); }}
onDragStart={onDragStart}
Expand Down
16 changes: 5 additions & 11 deletions src/components/ScreenNode.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ export function ScreenNode({
selectedCommentId,
onCommentPinClick,
onDeselectComment,
// True when this is an instance whose image/hotspots are inherited from
// its canonical at render time. Hotspot edits are read-only here — users
// must edit the canonical instead.
isInstanceVisual,
}) {
const [imgLoaded, setImgLoaded] = useState(false);
const [isEditingDesc, setIsEditingDesc] = useState(false);
Expand Down Expand Up @@ -370,7 +366,7 @@ export function ScreenNode({
>
S+
</button>
{!isInstanceVisual && <button
<button
className="screen-btn"
onClick={(e) => { e.stopPropagation(); onAddHotspot(screen.id); }}
title="Add tap area / button link"
Expand All @@ -386,7 +382,7 @@ export function ScreenNode({
}}
>
+ Link
</button>}
</button>
<button
className="screen-btn"
onClick={(e) => { e.stopPropagation(); onRemoveScreen(screen.id); }}
Expand Down Expand Up @@ -434,7 +430,7 @@ export function ScreenNode({
}
}
onSelect(screen.id);
if (screen.imageData && !isInstanceVisual && onImageAreaMouseDown) {
if (screen.imageData && onImageAreaMouseDown) {
onImageAreaMouseDown(e, screen.id);
}
}}
Expand Down Expand Up @@ -463,12 +459,10 @@ export function ScreenNode({
className="hotspot-area"
onMouseDown={(e) => {
e.stopPropagation();
if (isInstanceVisual) return;
if (onHotspotMouseDown) onHotspotMouseDown(e, screen.id, hs.id);
}}
onDoubleClick={(e) => {
e.stopPropagation();
if (isInstanceVisual) return;
if (onHotspotDoubleClick) onHotspotDoubleClick(e, screen.id, hs.id);
}}
style={{
Expand Down Expand Up @@ -505,7 +499,7 @@ export function ScreenNode({
>
{hs.label || "TAP"}
{/* Drag handle for hotspot-to-screen connect */}
{isSelected && !isInstanceVisual && (
{isSelected && (
<div
className="hotspot-drag-handle"
onMouseDown={(e) => {
Expand All @@ -532,7 +526,7 @@ export function ScreenNode({
/>
)}
{/* Resize handles */}
{isSelected && !isInstanceVisual && ["nw","n","ne","e","se","s","sw","w"].map((handle) => {
{isSelected && ["nw","n","ne","e","se","s","sw","w"].map((handle) => {
const pos = {
nw: { left: -4, top: -4, cursor: "nwse-resize" },
n: { left: "50%", top: -4, cursor: "ns-resize", transform: "translateX(-50%)" },
Expand Down
Loading
Loading