feat: replace hover clipboard icon with interactive copy button and clipboard functionality for info panel values
This commit is contained in:
@@ -890,10 +890,21 @@ export class UIManager {
|
||||
const clickableClass = item.clickable ? 'clickable-row' : '';
|
||||
// Only show dropdown arrow for actual dropdowns, not actions like zoom
|
||||
const dropdownIcon = (item.clickable && item.clickable !== 'zoom') ? '<span class="dropdown-indicator" style="margin-left: 4px; opacity: 0.6; font-size: 10px;">▼</span>' : '';
|
||||
// Show copy button for string values that are long enough to be worth copying
|
||||
const rawValue = String(item.value || '');
|
||||
const showCopyBtn = !item.clickable && rawValue.length > 3 && typeof item.value === 'string';
|
||||
const copyBtnHtml = showCopyBtn ? `
|
||||
<button class="copy-btn" data-copy-value="${rawValue.replace(/"/g, '"')}" title="Copy to clipboard">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
</button>` : '';
|
||||
return `
|
||||
<div class="info-row ${clickableClass}" ${clickableAttr} ${nodeIdAttr} style="${item.clickable ? 'cursor: pointer;' : ''}">
|
||||
<span class="info-label">${item.label}</span>
|
||||
<span class="info-value ${valueClass}" ${valueAttributes}>${value}${dropdownIcon}</span>
|
||||
${copyBtnHtml}
|
||||
</div>`;
|
||||
}).join('')}
|
||||
</div>
|
||||
@@ -943,6 +954,27 @@ export class UIManager {
|
||||
(row as HTMLElement).style.background = '';
|
||||
});
|
||||
});
|
||||
|
||||
// Add click handlers for copy buttons
|
||||
const copyButtons = this.elements.content.querySelectorAll('.copy-btn');
|
||||
copyButtons.forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const value = (btn as HTMLElement).dataset.copyValue || '';
|
||||
navigator.clipboard.writeText(value).then(() => {
|
||||
// Show success feedback
|
||||
btn.classList.add('copied');
|
||||
const originalHtml = btn.innerHTML;
|
||||
btn.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = originalHtml;
|
||||
btn.classList.remove('copied');
|
||||
}, 1500);
|
||||
}).catch(err => {
|
||||
console.error('Failed to copy:', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+41
-7
@@ -690,15 +690,49 @@
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Copy to clipboard functionality */
|
||||
.info-value[title]:hover::after {
|
||||
content: '📋';
|
||||
/* Copy button for values */
|
||||
.info-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 12px;
|
||||
right: 4px;
|
||||
top: 8px;
|
||||
background: var(--comfy-input-bg, rgba(60, 60, 70, 0.8));
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.7;
|
||||
transition: all 0.15s ease;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.info-row:hover .copy-btn {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.copy-btn:hover {
|
||||
opacity: 1;
|
||||
background: rgba(80, 80, 90, 0.9);
|
||||
}
|
||||
|
||||
.copy-btn svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
.copy-btn.copied {
|
||||
border-color: #22c55e;
|
||||
}
|
||||
|
||||
.copy-btn.copied svg {
|
||||
stroke: #22c55e;
|
||||
}
|
||||
|
||||
/* Smooth loading states */
|
||||
|
||||
@@ -638,10 +638,20 @@ class UIManager {
|
||||
const nodeIdAttr = item.nodeId !== void 0 ? `data-node-id="${item.nodeId}"` : "";
|
||||
const clickableClass = item.clickable ? "clickable-row" : "";
|
||||
const dropdownIcon = item.clickable && item.clickable !== "zoom" ? '<span class="dropdown-indicator" style="margin-left: 4px; opacity: 0.6; font-size: 10px;">▼</span>' : "";
|
||||
const rawValue = String(item.value || "");
|
||||
const showCopyBtn = !item.clickable && rawValue.length > 3 && typeof item.value === "string";
|
||||
const copyBtnHtml = showCopyBtn ? `
|
||||
<button class="copy-btn" data-copy-value="${rawValue.replace(/"/g, """)}" title="Copy to clipboard">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
</button>` : "";
|
||||
return `
|
||||
<div class="info-row ${clickableClass}" ${clickableAttr} ${nodeIdAttr} style="${item.clickable ? "cursor: pointer;" : ""}">
|
||||
<span class="info-label">${item.label}</span>
|
||||
<span class="info-value ${valueClass}" ${valueAttributes}>${value}${dropdownIcon}</span>
|
||||
${copyBtnHtml}
|
||||
</div>`;
|
||||
}).join("")}
|
||||
</div>
|
||||
@@ -683,6 +693,24 @@ class UIManager {
|
||||
row.style.background = "";
|
||||
});
|
||||
});
|
||||
const copyButtons = this.elements.content.querySelectorAll(".copy-btn");
|
||||
copyButtons.forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const value = btn.dataset.copyValue || "";
|
||||
navigator.clipboard.writeText(value).then(() => {
|
||||
btn.classList.add("copied");
|
||||
const originalHtml = btn.innerHTML;
|
||||
btn.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = originalHtml;
|
||||
btn.classList.remove("copied");
|
||||
}, 1500);
|
||||
}).catch((err) => {
|
||||
console.error("Failed to copy:", err);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Update section expansion states.
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user