mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 12:52:10 -03:00
543 lines
22 KiB
HTML
543 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Canvas View CSS Test - All Button Styles</title>
|
|
<link rel="stylesheet" href="src/css/canvas_view.css">
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background: #2a2a2a;
|
|
color: #ffffff;
|
|
margin: 20px;
|
|
line-height: 1.6;
|
|
}
|
|
.test-section {
|
|
margin: 30px 0;
|
|
padding: 20px;
|
|
background: #353535;
|
|
border-radius: 8px;
|
|
border: 1px solid #444;
|
|
}
|
|
.test-section h2 {
|
|
color: #4a90e2;
|
|
margin-top: 0;
|
|
border-bottom: 1px solid #555;
|
|
padding-bottom: 10px;
|
|
}
|
|
.test-section h3 {
|
|
color: #ffffff;
|
|
margin: 20px 0 10px 0;
|
|
}
|
|
.demo-row {
|
|
margin: 15px 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.demo-label {
|
|
min-width: 150px;
|
|
color: #cccccc;
|
|
font-size: 14px;
|
|
}
|
|
.test-controls {
|
|
margin: 20px 0;
|
|
}
|
|
.test-controls button {
|
|
margin: 5px;
|
|
padding: 8px 16px;
|
|
background: #4a6cd4;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
}
|
|
.test-controls button:hover {
|
|
background: #5a7ce4;
|
|
}
|
|
|
|
/* Custom Slider Styles to match ComfyUI aesthetic */
|
|
input[type="range"] {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 80px; /* Default width from painter-slider-container */
|
|
height: 7px;
|
|
background: #222;
|
|
border-radius: 5px;
|
|
outline: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="range"]::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 16px;
|
|
height: 16px;
|
|
background: #cccccc;
|
|
border-radius: 50%;
|
|
border: 2px solid #555;
|
|
cursor: pointer;
|
|
margin-top: -4.5px; /* Center thumb on track */
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
input[type="range"]::-moz-range-thumb {
|
|
width: 16px;
|
|
height: 16px;
|
|
background: #cccccc;
|
|
border-radius: 50%;
|
|
border: 2px solid #555;
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="range"]::-webkit-slider-thumb:hover {
|
|
background: #e0e0e0;
|
|
}
|
|
input[type="range"]::-moz-range-thumb:hover {
|
|
background: #e0e0e0;
|
|
}
|
|
|
|
input[type="range"]::-webkit-slider-runnable-track {
|
|
width: 100%;
|
|
height: 7px;
|
|
background: #222;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
input[type="range"]::-moz-range-track {
|
|
width: 100%;
|
|
height: 7px;
|
|
background: #222;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Canvas View CSS Test Page</h1>
|
|
<p>This page demonstrates all button styles from <code>src/css/canvas_view.css</code></p>
|
|
|
|
<div class="test-controls">
|
|
<button onclick="toggleLoadingState()">Toggle Loading State</button>
|
|
<button onclick="toggleDisabledState()">Toggle Disabled State</button>
|
|
<button onclick="toggleClipboardSwitch()">Toggle Clipboard Switch</button>
|
|
</div>
|
|
|
|
<!-- CanvasView Full Control Panel -->
|
|
<div class="test-section">
|
|
<h2>CanvasView Control Panel Layout</h2>
|
|
<div class="painter-controls" style="position: relative; flex-wrap: wrap; padding: 10px; background: #383838;">
|
|
|
|
<!-- Group 1: Main Controls -->
|
|
<div class="painter-button-group">
|
|
<button class="painter-button icon-button" title="Open in Editor">⛶</button>
|
|
<button class="painter-button icon-button" title="Show shortcuts">?</button>
|
|
<button class="painter-button primary">Add Image</button>
|
|
<button class="painter-button primary">Import Input</button>
|
|
<div class="painter-clipboard-group">
|
|
<button class="painter-button primary">Paste Image</button>
|
|
<label class="clipboard-switch" id="test-clipboard-switch">
|
|
<input type="checkbox">
|
|
<span class="switch-track"></span>
|
|
<span class="switch-labels">
|
|
<span class="text-clipspace">Clipspace</span>
|
|
<span class="text-system">System</span>
|
|
</span>
|
|
<span class="switch-knob">
|
|
<span class="switch-icon">
|
|
<img src="" alt="clipboard icon" style="width: 20px; height: 20px;">
|
|
</span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="painter-separator"></div>
|
|
|
|
<!-- Group 2: Layer Management -->
|
|
<div class="painter-button-group">
|
|
<button class="painter-button">Output Area Size</button>
|
|
<button class="painter-button requires-selection">Remove Layer</button>
|
|
<button class="painter-button requires-selection">Layer Up</button>
|
|
<button class="painter-button requires-selection">Layer Down</button>
|
|
<button class="painter-button requires-selection">Fuse</button>
|
|
</div>
|
|
|
|
<div class="painter-separator"></div>
|
|
|
|
<!-- Group 3: Transformations -->
|
|
<div class="painter-button-group">
|
|
<button class="painter-button requires-selection">Rotate +90°</button>
|
|
<button class="painter-button requires-selection">Scale +5%</button>
|
|
<button class="painter-button requires-selection">Scale -5%</button>
|
|
<button class="painter-button requires-selection">Mirror H</button>
|
|
<button class="painter-button requires-selection">Mirror V</button>
|
|
</div>
|
|
|
|
<div class="painter-separator"></div>
|
|
|
|
<!-- Group 4: Tools -->
|
|
<div class="painter-button-group">
|
|
<button class="painter-button matting-button requires-selection">Matting<div class="matting-spinner"></div></button>
|
|
<button class="painter-button">Undo</button>
|
|
<button class="painter-button">Redo</button>
|
|
</div>
|
|
|
|
<div class="painter-separator"></div>
|
|
|
|
<!-- Group 5: Masking -->
|
|
<div class="painter-button-group" id="test-mask-controls">
|
|
<label class="clipboard-switch mask-switch" title="Toggle mask overlay visibility" style="min-width: 56px; max-width: 56px; width: 56px;">
|
|
<input type="checkbox" checked="">
|
|
<span class="switch-track"></span>
|
|
<span class="switch-labels" style="font-size: 11px;">
|
|
<span class="text-clipspace" style="padding-right: 22px;">On</span>
|
|
<span class="text-system" style="padding-left: 20px;">Off</span>
|
|
</span>
|
|
<span class="switch-knob">
|
|
<span class="switch-icon" style="display: flex; align-items: center; justify-content: center; width: 16px; height: 16px;">
|
|
<!-- Icon would be loaded here by JS -->
|
|
</span>
|
|
</span>
|
|
</label>
|
|
<button class="painter-button">Edit Mask</button>
|
|
<button class="painter-button" id="test-mask-mode-btn" onclick="toggleTestMaskControls()">Draw Mask</button>
|
|
<div class="painter-slider-container mask-control" style="display: none;">
|
|
<label>Size:</label>
|
|
<input type="range" min="1" max="200" value="20">
|
|
<div class="slider-value">20px</div>
|
|
</div>
|
|
<div class="painter-slider-container mask-control" style="display: none;">
|
|
<label>Strength:</label>
|
|
<input type="range" min="0" max="1" step="0.05" value="0.5">
|
|
<div class="slider-value">50%</div>
|
|
</div>
|
|
<div class="painter-slider-container mask-control" style="display: none;">
|
|
<label>Hardness:</label>
|
|
<input type="range" min="0" max="1" step="0.05" value="0.5">
|
|
<div class="slider-value">50%</div>
|
|
</div>
|
|
<button class="painter-button mask-control" style="display: none;">Clear Mask</button>
|
|
</div>
|
|
|
|
<div class="painter-separator"></div>
|
|
|
|
<!-- Group 6: Dev/Debug -->
|
|
<div class="painter-button-group">
|
|
<button class="painter-button success">Run GC</button>
|
|
<button class="painter-button danger">Clear Cache</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Basic Buttons -->
|
|
<div class="test-section">
|
|
<h2>Basic Painter Buttons</h2>
|
|
|
|
<div class="demo-row">
|
|
<span class="demo-label">Normal Button:</span>
|
|
<button class="painter-button">Normal Button</button>
|
|
<button class="painter-button">Another Button</button>
|
|
<button class="painter-button">Third Button</button>
|
|
</div>
|
|
|
|
<div class="demo-row">
|
|
<span class="demo-label">Primary Button:</span>
|
|
<button class="painter-button primary">Primary Button</button>
|
|
<button class="painter-button primary">Save</button>
|
|
<button class="painter-button primary">Apply</button>
|
|
</div>
|
|
|
|
<div class="demo-row">
|
|
<span class="demo-label">Disabled Buttons:</span>
|
|
<button class="painter-button" disabled>Disabled Normal</button>
|
|
<button class="painter-button primary" disabled>Disabled Primary</button>
|
|
</div>
|
|
|
|
<div class="demo-row">
|
|
<span class="demo-label">Matting Buttons:</span>
|
|
<button class="painter-button matting-button" id="mattingBtn1">
|
|
Matting Tool
|
|
<div class="matting-spinner"></div>
|
|
</button>
|
|
<button class="painter-button matting-button" id="mattingBtn2">
|
|
Process Image
|
|
<div class="matting-spinner"></div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Button Groups -->
|
|
<div class="test-section">
|
|
<h2>Button Groups and Controls</h2>
|
|
|
|
<h3>Painter Controls Container</h3>
|
|
<div class="painter-controls">
|
|
<button class="painter-button">Tool 1</button>
|
|
<button class="painter-button">Tool 2</button>
|
|
<button class="painter-button primary">Active Tool</button>
|
|
<div class="painter-separator"></div>
|
|
<button class="painter-button">Option A</button>
|
|
<button class="painter-button">Option B</button>
|
|
</div>
|
|
|
|
<h3>Button Group</h3>
|
|
<div class="painter-button-group">
|
|
<button class="painter-button">Group 1</button>
|
|
<button class="painter-button">Group 2</button>
|
|
<button class="painter-button primary">Group 3</button>
|
|
</div>
|
|
|
|
<h3>Clipboard Group</h3>
|
|
<div class="painter-clipboard-group">
|
|
<button class="painter-button">Copy</button>
|
|
<button class="painter-button">Paste</button>
|
|
<button class="painter-button primary">Clear</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clipboard Switch -->
|
|
<div class="test-section">
|
|
<h2>Clipboard Switch</h2>
|
|
|
|
<div class="demo-row">
|
|
<span class="demo-label">Clipboard Switch:</span>
|
|
<label class="clipboard-switch" id="clipboardSwitch">
|
|
<input type="checkbox">
|
|
<span class="switch-track"></span>
|
|
<span class="switch-knob">
|
|
<span class="switch-icon">
|
|
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgMTZIMTVWMTBIOVYxNloiIGZpbGw9IiM0YTkwZTIiLz4KPHBhdGggZD0iTTcgMTZIMTdWMTBIN1YxNloiIHN0cm9rZT0iIzRhOTBlMiIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIi8+Cjwvc3ZnPgo=" alt="clipboard">
|
|
</span>
|
|
</span>
|
|
<span class="switch-labels">
|
|
<span class="text-system">System</span>
|
|
<span class="text-clipspace">Clipspace</span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sliders -->
|
|
<div class="test-section">
|
|
<h2>Sliders and Controls</h2>
|
|
|
|
<div class="painter-controls">
|
|
<div class="painter-slider-container">
|
|
<label>Opacity:</label>
|
|
<input type="range" min="0" max="100" value="50">
|
|
<span>50%</span>
|
|
</div>
|
|
<div class="painter-separator"></div>
|
|
<div class="painter-slider-container">
|
|
<label>Size:</label>
|
|
<input type="range" min="1" max="100" value="25">
|
|
<span>25px</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Container Examples -->
|
|
<div class="test-section">
|
|
<h2>Container Examples</h2>
|
|
|
|
<h3>Normal Container</h3>
|
|
<div class="painter-container" style="padding: 20px; margin: 10px 0;">
|
|
<p>This is a normal painter container</p>
|
|
<button class="painter-button">Button inside container</button>
|
|
</div>
|
|
|
|
<h3>Container with Focus</h3>
|
|
<div class="painter-container has-focus" style="padding: 20px; margin: 10px 0;">
|
|
<p>This container has focus (white border)</p>
|
|
<button class="painter-button primary">Focused container button</button>
|
|
</div>
|
|
|
|
<h3>Drag Over Container</h3>
|
|
<div class="painter-container drag-over" style="padding: 20px; margin: 10px 0;">
|
|
<p>This container is in drag-over state (green dashed border)</p>
|
|
<button class="painter-button">Drag target button</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Example -->
|
|
<div class="test-section">
|
|
<h2>Modal and Dialog</h2>
|
|
|
|
<button onclick="showModal()" class="painter-button primary">Show Modal Example</button>
|
|
|
|
<h3>Dialog Example</h3>
|
|
<div class="painter-dialog" style="display: inline-block; margin: 10px 0;">
|
|
<h4>Sample Dialog</h4>
|
|
<p>Enter values:</p>
|
|
<input type="text" placeholder="Width" value="100">
|
|
<input type="text" placeholder="Height" value="100">
|
|
<br>
|
|
<button>OK</button>
|
|
<button>Cancel</button>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Hidden Modal -->
|
|
<div class="painter-modal-backdrop" id="testModal" style="display: none;">
|
|
<div class="painter-modal-content">
|
|
<div class="painterMainContainer">
|
|
<div class="painter-controls">
|
|
<button class="painter-button" onclick="hideModal()">Close Modal</button>
|
|
<button class="painter-button primary">Save</button>
|
|
<div class="painter-separator"></div>
|
|
<button class="painter-button">Option 1</button>
|
|
<button class="painter-button">Option 2</button>
|
|
</div>
|
|
<div class="painterCanvasContainer" style="padding: 20px; display: flex; align-items: center; justify-content: center;">
|
|
<div>
|
|
<h3>Modal Content Area</h3>
|
|
<p>This is the main content area of the modal.</p>
|
|
<div class="painter-button-group">
|
|
<button class="painter-button">Action 1</button>
|
|
<button class="painter-button">Action 2</button>
|
|
<button class="painter-button primary">Primary Action</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- This is where the tooltip will be rendered -->
|
|
<div class="painter-tooltip" id="live-tooltip" style="display: none;"></div>
|
|
|
|
<script>
|
|
// Toggle loading state for matting buttons
|
|
function toggleLoadingState() {
|
|
const mattingBtns = document.querySelectorAll('.matting-button');
|
|
mattingBtns.forEach(btn => {
|
|
btn.classList.toggle('loading');
|
|
});
|
|
}
|
|
|
|
// Toggle disabled state for all buttons
|
|
function toggleDisabledState() {
|
|
const buttons = document.querySelectorAll('.painter-button:not(.matting-button)');
|
|
buttons.forEach(btn => {
|
|
btn.disabled = !btn.disabled;
|
|
});
|
|
}
|
|
|
|
// Toggle clipboard switch
|
|
function toggleClipboardSwitch() {
|
|
const checkbox = document.querySelector('#clipboardSwitch input[type="checkbox"]');
|
|
checkbox.checked = !checkbox.checked;
|
|
}
|
|
|
|
// Show modal
|
|
function showModal() {
|
|
document.getElementById('testModal').style.display = 'flex';
|
|
}
|
|
|
|
// Hide modal
|
|
function hideModal() {
|
|
document.getElementById('testModal').style.display = 'none';
|
|
}
|
|
|
|
// --- Live Tooltip Logic ---
|
|
const tooltipButton = document.querySelector('button[title="Show shortcuts"]');
|
|
const tooltipContainer = document.getElementById('live-tooltip');
|
|
let shortcutsHtml = '';
|
|
|
|
// Pre-fetch the shortcuts content
|
|
fetch('src/templates/standard_shortcuts.html')
|
|
.then(response => response.text())
|
|
.then(html => {
|
|
shortcutsHtml = html;
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching shortcuts:', error);
|
|
shortcutsHtml = '<p>Error loading shortcuts.</p>';
|
|
});
|
|
|
|
tooltipButton.addEventListener('mouseenter', (e) => {
|
|
if (!shortcutsHtml || !tooltipContainer) return;
|
|
|
|
tooltipContainer.innerHTML = shortcutsHtml;
|
|
tooltipContainer.style.visibility = 'hidden';
|
|
tooltipContainer.style.display = 'block';
|
|
|
|
const buttonRect = e.target.getBoundingClientRect();
|
|
const tooltipRect = tooltipContainer.getBoundingClientRect();
|
|
|
|
let left = buttonRect.left;
|
|
let top = buttonRect.bottom + 5;
|
|
|
|
// Adjust position to stay within viewport
|
|
if (left + tooltipRect.width > window.innerWidth) {
|
|
left = window.innerWidth - tooltipRect.width - 10;
|
|
}
|
|
if (top + tooltipRect.height > window.innerHeight) {
|
|
top = buttonRect.top - tooltipRect.height - 5;
|
|
}
|
|
if (left < 10) left = 10;
|
|
if (top < 10) top = 10;
|
|
|
|
tooltipContainer.style.left = `${left}px`;
|
|
tooltipContainer.style.top = `${top}px`;
|
|
tooltipContainer.style.visibility = 'visible';
|
|
});
|
|
|
|
tooltipButton.addEventListener('mouseleave', () => {
|
|
if (tooltipContainer) {
|
|
tooltipContainer.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// Close modal when clicking backdrop
|
|
document.getElementById('testModal').addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
hideModal();
|
|
}
|
|
});
|
|
|
|
// --- Icon Loading and Interactive Logic ---
|
|
|
|
const icons = {
|
|
system: `data:image/svg+xml;charset=utf-8,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0S9.6.84 9.18 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm5 15H7v-2h10v2zm0-4H7v-2h10v2zm0-4H7V7h10v2z"/></svg>')}`,
|
|
clipspace: `data:image/svg+xml;charset=utf-8,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff"><path d="M17 7H7c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 12H7V9h10v10z"/><path d="M19 3H9c-1.1 0-2 .9-2 2v2h2V5h10v10h-2v2h2c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></svg>')}`
|
|
};
|
|
|
|
function updateClipboardIcon(switchElement) {
|
|
const isChecked = switchElement.querySelector('input').checked;
|
|
const iconImg = switchElement.querySelector('.switch-icon img');
|
|
iconImg.src = isChecked ? icons.clipspace : icons.system;
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const clipboardSwitch = document.getElementById('test-clipboard-switch');
|
|
if (clipboardSwitch) {
|
|
updateClipboardIcon(clipboardSwitch);
|
|
clipboardSwitch.querySelector('input').addEventListener('change', () => {
|
|
updateClipboardIcon(clipboardSwitch);
|
|
});
|
|
}
|
|
});
|
|
|
|
// Function to toggle mask controls in the test layout
|
|
function toggleTestMaskControls() {
|
|
const maskBtn = document.getElementById('test-mask-mode-btn');
|
|
const maskControlsContainer = document.getElementById('test-mask-controls');
|
|
const controls = maskControlsContainer.querySelectorAll('.mask-control');
|
|
|
|
const isActive = maskBtn.classList.toggle('primary');
|
|
|
|
controls.forEach(control => {
|
|
control.style.display = isActive ? 'flex' : 'none';
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|