diff --git a/js/CustomShapeMenu.js b/js/CustomShapeMenu.js index b5fad9c..0492f8f 100644 --- a/js/CustomShapeMenu.js +++ b/js/CustomShapeMenu.js @@ -61,10 +61,8 @@ export class CustomShapeMenu { featureContainer.id = 'shape-mask-feature-container'; featureContainer.className = 'feature-container'; // Add main auto-apply checkbox to the new container - const checkboxContainer = this._createCheckbox(() => `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`, () => { - // Always hide any active shape preview lines first to prevent them from getting stuck - this.canvas.maskTool.hideShapePreview(); - this.canvas.autoApplyShapeMask = !this.canvas.autoApplyShapeMask; + const checkboxContainer = this._createCheckbox('auto-apply-checkbox', () => this.canvas.autoApplyShapeMask, 'Auto-apply shape mask', (e) => { + this.canvas.autoApplyShapeMask = e.target.checked; if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.applyShapeMask(); log.info("Auto-apply shape mask enabled - mask applied automatically"); @@ -80,8 +78,8 @@ export class CustomShapeMenu { }, "Automatically applies a mask based on the custom output area shape. When enabled, the mask will be applied to all layers within the shape boundary."); featureContainer.appendChild(checkboxContainer); // Add expansion checkbox - const expansionContainer = this._createCheckbox(() => `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Expand/Contract mask`, () => { - this.canvas.shapeMaskExpansion = !this.canvas.shapeMaskExpansion; + const expansionContainer = this._createCheckbox('expansion-checkbox', () => this.canvas.shapeMaskExpansion, 'Expand/Contract mask', (e) => { + this.canvas.shapeMaskExpansion = e.target.checked; this._updateUI(); if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.hideShapePreview(); @@ -89,7 +87,6 @@ export class CustomShapeMenu { this.canvas.render(); } }, "Dilate (expand) or erode (contract) the shape mask. Positive values expand the mask outward, negative values shrink it inward."); - expansionContainer.id = 'expansion-checkbox'; featureContainer.appendChild(expansionContainer); // Add expansion slider container const expansionSliderContainer = document.createElement('div'); @@ -154,8 +151,8 @@ export class CustomShapeMenu { expansionSliderContainer.appendChild(expansionValueDisplay); featureContainer.appendChild(expansionSliderContainer); // Add feather checkbox - const featherContainer = this._createCheckbox(() => `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`, () => { - this.canvas.shapeMaskFeather = !this.canvas.shapeMaskFeather; + const featherContainer = this._createCheckbox('feather-checkbox', () => this.canvas.shapeMaskFeather, 'Feather edges', (e) => { + this.canvas.shapeMaskFeather = e.target.checked; this._updateUI(); if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.hideShapePreview(); @@ -163,7 +160,6 @@ export class CustomShapeMenu { this.canvas.render(); } }, "Softens the edges of the shape mask by creating a gradual transition from opaque to transparent."); - featherContainer.id = 'feather-checkbox'; featureContainer.appendChild(featherContainer); // Add feather slider container const featherSliderContainer = document.createElement('div'); @@ -219,30 +215,19 @@ export class CustomShapeMenu { extensionContainer.id = 'output-area-extension-container'; extensionContainer.className = 'feature-container'; // Add main extension checkbox - const extensionCheckboxContainer = this._createCheckbox(() => `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`, () => { - this.canvas.outputAreaExtensionEnabled = !this.canvas.outputAreaExtensionEnabled; + const extensionCheckboxContainer = this._createCheckbox('extension-checkbox', () => this.canvas.outputAreaExtensionEnabled, 'Extend output area', (e) => { + this.canvas.outputAreaExtensionEnabled = e.target.checked; if (this.canvas.outputAreaExtensionEnabled) { - // When enabling, capture current canvas size as the baseline - this.canvas.originalCanvasSize = { - width: this.canvas.width, - height: this.canvas.height - }; - // Restore last saved extensions instead of starting from zero + this.canvas.originalCanvasSize = { width: this.canvas.width, height: this.canvas.height }; this.canvas.outputAreaExtensions = { ...this.canvas.lastOutputAreaExtensions }; - log.info(`Captured current canvas size as baseline: ${this.canvas.width}x${this.canvas.height}`); - log.info(`Restored last extensions:`, this.canvas.outputAreaExtensions); } else { - // Save current extensions before disabling this.canvas.lastOutputAreaExtensions = { ...this.canvas.outputAreaExtensions }; - // Reset current extensions when disabled (but keep the saved ones) this.canvas.outputAreaExtensions = { top: 0, bottom: 0, left: 0, right: 0 }; - log.info(`Saved extensions for later:`, this.canvas.lastOutputAreaExtensions); } this._updateExtensionUI(); - this._updateCanvasSize(); // Update canvas size when toggling + this._updateCanvasSize(); this.canvas.render(); - log.info(`Output area extension ${this.canvas.outputAreaExtensionEnabled ? 'enabled' : 'disabled'}`); }, "Allows extending the output area boundaries in all directions without changing the custom shape."); extensionContainer.appendChild(extensionCheckboxContainer); // Create sliders container @@ -333,26 +318,28 @@ export class CustomShapeMenu { // Add viewport change listener to update shape preview when zooming/panning this._addViewportChangeListener(); } - _createCheckbox(textFn, clickHandler, tooltipText) { - const container = document.createElement('div'); + _createCheckbox(id, getChecked, text, clickHandler, tooltipText) { + const container = document.createElement('label'); container.className = 'checkbox-container'; - container.onmouseover = () => { - container.style.backgroundColor = '#555'; - }; - container.onmouseout = () => { - container.style.backgroundColor = 'transparent'; - }; - const updateText = () => { - container.textContent = textFn(); - }; - updateText(); + container.htmlFor = id; + const input = document.createElement('input'); + input.type = 'checkbox'; + input.id = id; + input.checked = getChecked(); + const customCheckbox = document.createElement('div'); + customCheckbox.className = 'custom-checkbox'; + const labelText = document.createElement('span'); + labelText.textContent = text; + container.appendChild(input); + container.appendChild(customCheckbox); + container.appendChild(labelText); + // Stop propagation to prevent menu from closing, but allow default checkbox behavior container.onclick = (e) => { - e.preventDefault(); e.stopPropagation(); - clickHandler(); - updateText(); }; - // Add tooltip if provided + input.onchange = (e) => { + clickHandler(e); + }; if (tooltipText) { this._addTooltip(container, tooltipText); } @@ -361,16 +348,23 @@ export class CustomShapeMenu { _updateUI() { if (!this.element) return; - // Toggle visibility of sub-options based on the main checkbox state - const expansionCheckbox = this.element.querySelector('#expansion-checkbox'); + const setChecked = (id, checked) => { + const input = this.element.querySelector(`#${id}`); + if (input) + input.checked = checked; + }; + setChecked('auto-apply-checkbox', this.canvas.autoApplyShapeMask); + setChecked('expansion-checkbox', this.canvas.shapeMaskExpansion); + setChecked('feather-checkbox', this.canvas.shapeMaskFeather); + setChecked('extension-checkbox', this.canvas.outputAreaExtensionEnabled); + const expansionCheckbox = this.element.querySelector('#expansion-checkbox')?.parentElement; if (expansionCheckbox) { - expansionCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none'; + expansionCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'flex' : 'none'; } - const featherCheckbox = this.element.querySelector('#feather-checkbox'); + const featherCheckbox = this.element.querySelector('#feather-checkbox')?.parentElement; if (featherCheckbox) { - featherCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none'; + featherCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'flex' : 'none'; } - // Update sliders visibility based on their respective checkboxes const expansionSliderContainer = this.element.querySelector('#expansion-slider-container'); if (expansionSliderContainer) { expansionSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskExpansion) ? 'block' : 'none'; @@ -379,22 +373,6 @@ export class CustomShapeMenu { if (featherSliderContainer) { featherSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskFeather) ? 'block' : 'none'; } - // Update checkbox texts - const checkboxes = this.element.querySelectorAll('div[style*="cursor: pointer"]'); - checkboxes.forEach((checkbox, index) => { - if (index === 0) { // Main checkbox - checkbox.textContent = `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`; - } - else if (index === 1) { // Expansion checkbox - checkbox.textContent = `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Dilate/Erode mask`; - } - else if (index === 2) { // Feather checkbox - checkbox.textContent = `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`; - } - else if (index === 3) { // Extension checkbox - checkbox.textContent = `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`; - } - }); } _updateExtensionUI() { if (!this.element) diff --git a/js/css/custom_shape_menu.css b/js/css/custom_shape_menu.css index a883f45..7f7d9d4 100644 --- a/js/css/custom_shape_menu.css +++ b/js/css/custom_shape_menu.css @@ -2,92 +2,165 @@ position: absolute; top: 0; left: 0; - background-color: #333; - color: white; - padding: 8px 15px; - border-radius: 10px; - box-shadow: 0 4px 15px rgba(0,0,0,0.5); + background-color: #2f2f2f; + color: #e0e0e0; + padding: 12px; + border-radius: 8px; + box-shadow: 0 5px 15px rgba(0,0,0,0.3); display: none; flex-direction: column; - gap: 4px; - font-family: sans-serif; - font-size: 12px; + gap: 10px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: 13px; z-index: 1001; - border: 1px solid #555; + border: 1px solid #202020; user-select: none; - min-width: 200px; + min-width: 220px; } #layerforge-custom-shape-menu .menu-line { - margin: 2px 0; - line-height: 18px; + font-weight: 600; + color: #4a90e2; + padding-bottom: 5px; + border-bottom: 1px solid #444; + margin-bottom: 5px; + display: flex; + align-items: center; + gap: 8px; } #layerforge-custom-shape-menu .feature-container { - background-color: #282828; + background-color: #3a3a3a; border-radius: 6px; - margin-top: 6px; - padding: 4px 0; - border: 1px solid #444; + padding: 10px; + border: 1px solid #4a4a4a; } #layerforge-custom-shape-menu .slider-container { - margin: 0 8px 6px 8px; - padding: 4px 8px; + margin-top: 10px; display: none; } #layerforge-custom-shape-menu .slider-label { - font-size: 11px; - margin-bottom: 4px; - color: #ccc; + font-size: 12px; + margin-bottom: 6px; + color: #e0e0e0; } #layerforge-custom-shape-menu input[type="range"] { + -webkit-appearance: none; width: 100%; height: 4px; background: #555; - outline: none; border-radius: 2px; + outline: none; + padding: 0; + margin: 0; +} +#layerforge-custom-shape-menu input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + background: #e0e0e0; + border-radius: 50%; + cursor: pointer; + border: 2px solid #555; + transition: background 0.2s; +} +#layerforge-custom-shape-menu input[type="range"]::-webkit-slider-thumb:hover { + background: #fff; +} +#layerforge-custom-shape-menu input[type="range"]::-moz-range-thumb { + width: 14px; + height: 14px; + background: #e0e0e0; + border-radius: 50%; + cursor: pointer; + border: 2px solid #555; } #layerforge-custom-shape-menu .slider-value-display { - font-size: 10px; + font-size: 11px; text-align: center; - margin-top: 2px; - color: #aaa; + margin-top: 4px; + color: #bbb; + min-height: 14px; } #layerforge-custom-shape-menu .extension-slider-container { - margin: 6px 0; + margin: 10px 0; } #layerforge-custom-shape-menu .checkbox-container { - margin: 6px 0 2px 0; - padding: 4px 8px; + display: flex; + align-items: center; + gap: 10px; + padding: 6px; border-radius: 5px; cursor: pointer; transition: background-color 0.2s; - line-height: 18px; + position: relative; } #layerforge-custom-shape-menu .checkbox-container:hover { - background-color: #555; + background-color: #4a4a4a; +} + +#layerforge-custom-shape-menu .checkbox-container input[type="checkbox"] { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; +} + +#layerforge-custom-shape-menu .checkbox-container .custom-checkbox { + height: 16px; + width: 16px; + background-color: #2a2a2a; + border: 1px solid #666; + border-radius: 3px; + transition: all 0.2s; + position: relative; + flex-shrink: 0; +} + +#layerforge-custom-shape-menu .checkbox-container input:checked ~ .custom-checkbox { + background-color: #3a76d6; + border-color: #3a76d6; +} + +#layerforge-custom-shape-menu .checkbox-container .custom-checkbox::after { + content: ""; + position: absolute; + display: none; + left: 5px; + top: 1px; + width: 4px; + height: 9px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +#layerforge-custom-shape-menu .checkbox-container input:checked ~ .custom-checkbox::after { + display: block; } .layerforge-tooltip { position: fixed; - background-color: #1a1a1a; - color: #ffffff; + background-color: #2f2f2f; + color: #e0e0e0; padding: 8px 12px; border-radius: 6px; font-size: 12px; - font-family: sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.4; max-width: 250px; word-wrap: break-word; - box-shadow: 0 4px 12px rgba(0,0,0,0.6); - border: 1px solid #444; + box-shadow: 0 4px 12px rgba(0,0,0,0.4); + border: 1px solid #202020; z-index: 10000; pointer-events: none; opacity: 0; diff --git a/src/CustomShapeMenu.ts b/src/CustomShapeMenu.ts index f93e320..a3ae796 100644 --- a/src/CustomShapeMenu.ts +++ b/src/CustomShapeMenu.ts @@ -86,13 +86,11 @@ export class CustomShapeMenu { // Add main auto-apply checkbox to the new container const checkboxContainer = this._createCheckbox( - () => `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`, - () => { - // Always hide any active shape preview lines first to prevent them from getting stuck - this.canvas.maskTool.hideShapePreview(); - - this.canvas.autoApplyShapeMask = !this.canvas.autoApplyShapeMask; - + 'auto-apply-checkbox', + () => this.canvas.autoApplyShapeMask, + 'Auto-apply shape mask', + (e) => { + this.canvas.autoApplyShapeMask = (e.target as HTMLInputElement).checked; if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.applyShapeMask(); log.info("Auto-apply shape mask enabled - mask applied automatically"); @@ -102,7 +100,6 @@ export class CustomShapeMenu { this.canvas.shapeMaskFeather = false; log.info("Auto-apply shape mask disabled - mask area removed and sub-options reset."); } - this._updateUI(); this.canvas.render(); }, @@ -112,11 +109,12 @@ export class CustomShapeMenu { // Add expansion checkbox const expansionContainer = this._createCheckbox( - () => `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Expand/Contract mask`, - () => { - this.canvas.shapeMaskExpansion = !this.canvas.shapeMaskExpansion; + 'expansion-checkbox', + () => this.canvas.shapeMaskExpansion, + 'Expand/Contract mask', + (e) => { + this.canvas.shapeMaskExpansion = (e.target as HTMLInputElement).checked; this._updateUI(); - if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.hideShapePreview(); this.canvas.maskTool.applyShapeMask(); @@ -125,7 +123,6 @@ export class CustomShapeMenu { }, "Dilate (expand) or erode (contract) the shape mask. Positive values expand the mask outward, negative values shrink it inward." ); - expansionContainer.id = 'expansion-checkbox'; featureContainer.appendChild(expansionContainer); // Add expansion slider container @@ -205,11 +202,12 @@ export class CustomShapeMenu { // Add feather checkbox const featherContainer = this._createCheckbox( - () => `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`, - () => { - this.canvas.shapeMaskFeather = !this.canvas.shapeMaskFeather; + 'feather-checkbox', + () => this.canvas.shapeMaskFeather, + 'Feather edges', + (e) => { + this.canvas.shapeMaskFeather = (e.target as HTMLInputElement).checked; this._updateUI(); - if (this.canvas.autoApplyShapeMask) { this.canvas.maskTool.hideShapePreview(); this.canvas.maskTool.applyShapeMask(); @@ -218,7 +216,6 @@ export class CustomShapeMenu { }, "Softens the edges of the shape mask by creating a gradual transition from opaque to transparent." ); - featherContainer.id = 'feather-checkbox'; featureContainer.appendChild(featherContainer); // Add feather slider container @@ -288,32 +285,21 @@ export class CustomShapeMenu { // Add main extension checkbox const extensionCheckboxContainer = this._createCheckbox( - () => `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`, - () => { - this.canvas.outputAreaExtensionEnabled = !this.canvas.outputAreaExtensionEnabled; - - if (this.canvas.outputAreaExtensionEnabled) { - // When enabling, capture current canvas size as the baseline - this.canvas.originalCanvasSize = { - width: this.canvas.width, - height: this.canvas.height - }; - // Restore last saved extensions instead of starting from zero + 'extension-checkbox', + () => this.canvas.outputAreaExtensionEnabled, + 'Extend output area', + (e) => { + this.canvas.outputAreaExtensionEnabled = (e.target as HTMLInputElement).checked; + if (this.canvas.outputAreaExtensionEnabled) { + this.canvas.originalCanvasSize = { width: this.canvas.width, height: this.canvas.height }; this.canvas.outputAreaExtensions = { ...this.canvas.lastOutputAreaExtensions }; - log.info(`Captured current canvas size as baseline: ${this.canvas.width}x${this.canvas.height}`); - log.info(`Restored last extensions:`, this.canvas.outputAreaExtensions); } else { - // Save current extensions before disabling this.canvas.lastOutputAreaExtensions = { ...this.canvas.outputAreaExtensions }; - // Reset current extensions when disabled (but keep the saved ones) this.canvas.outputAreaExtensions = { top: 0, bottom: 0, left: 0, right: 0 }; - log.info(`Saved extensions for later:`, this.canvas.lastOutputAreaExtensions); } - this._updateExtensionUI(); - this._updateCanvasSize(); // Update canvas size when toggling + this._updateCanvasSize(); this.canvas.render(); - log.info(`Output area extension ${this.canvas.outputAreaExtensionEnabled ? 'enabled' : 'disabled'}`); }, "Allows extending the output area boundaries in all directions without changing the custom shape." ); @@ -424,31 +410,41 @@ export class CustomShapeMenu { this._addViewportChangeListener(); } - private _createCheckbox(textFn: () => string, clickHandler: () => void, tooltipText?: string): HTMLDivElement { - const container = document.createElement('div'); + private _createCheckbox( + id: string, + getChecked: () => boolean, + text: string, + clickHandler: (e: Event) => void, + tooltipText?: string + ): HTMLLabelElement { + const container = document.createElement('label'); container.className = 'checkbox-container'; + container.htmlFor = id; - container.onmouseover = () => { - container.style.backgroundColor = '#555'; + const input = document.createElement('input'); + input.type = 'checkbox'; + input.id = id; + input.checked = getChecked(); + + const customCheckbox = document.createElement('div'); + customCheckbox.className = 'custom-checkbox'; + + const labelText = document.createElement('span'); + labelText.textContent = text; + + container.appendChild(input); + container.appendChild(customCheckbox); + container.appendChild(labelText); + + // Stop propagation to prevent menu from closing, but allow default checkbox behavior + container.onclick = (e: MouseEvent) => { + e.stopPropagation(); }; - container.onmouseout = () => { - container.style.backgroundColor = 'transparent'; + input.onchange = (e: Event) => { + clickHandler(e); }; - const updateText = () => { - container.textContent = textFn(); - }; - - updateText(); - container.onclick = (e: MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - clickHandler(); - updateText(); - }; - - // Add tooltip if provided if (tooltipText) { this._addTooltip(container, tooltipText); } @@ -458,19 +454,27 @@ export class CustomShapeMenu { private _updateUI(): void { if (!this.element) return; + + const setChecked = (id: string, checked: boolean) => { + const input = this.element!.querySelector(`#${id}`) as HTMLInputElement; + if (input) input.checked = checked; + }; - // Toggle visibility of sub-options based on the main checkbox state - const expansionCheckbox = this.element.querySelector('#expansion-checkbox') as HTMLElement; + setChecked('auto-apply-checkbox', this.canvas.autoApplyShapeMask); + setChecked('expansion-checkbox', this.canvas.shapeMaskExpansion); + setChecked('feather-checkbox', this.canvas.shapeMaskFeather); + setChecked('extension-checkbox', this.canvas.outputAreaExtensionEnabled); + + const expansionCheckbox = this.element.querySelector('#expansion-checkbox')?.parentElement as HTMLElement; if (expansionCheckbox) { - expansionCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none'; + expansionCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'flex' : 'none'; } - const featherCheckbox = this.element.querySelector('#feather-checkbox') as HTMLElement; + const featherCheckbox = this.element.querySelector('#feather-checkbox')?.parentElement as HTMLElement; if (featherCheckbox) { - featherCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none'; + featherCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'flex' : 'none'; } - // Update sliders visibility based on their respective checkboxes const expansionSliderContainer = this.element.querySelector('#expansion-slider-container') as HTMLElement; if (expansionSliderContainer) { expansionSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskExpansion) ? 'block' : 'none'; @@ -480,20 +484,6 @@ export class CustomShapeMenu { if (featherSliderContainer) { featherSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskFeather) ? 'block' : 'none'; } - - // Update checkbox texts - const checkboxes = this.element.querySelectorAll('div[style*="cursor: pointer"]'); - checkboxes.forEach((checkbox, index) => { - if (index === 0) { // Main checkbox - checkbox.textContent = `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`; - } else if (index === 1) { // Expansion checkbox - checkbox.textContent = `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Dilate/Erode mask`; - } else if (index === 2) { // Feather checkbox - checkbox.textContent = `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`; - } else if (index === 3) { // Extension checkbox - checkbox.textContent = `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`; - } - }); } private _updateExtensionUI(): void { diff --git a/src/css/custom_shape_menu.css b/src/css/custom_shape_menu.css index a883f45..7f7d9d4 100644 --- a/src/css/custom_shape_menu.css +++ b/src/css/custom_shape_menu.css @@ -2,92 +2,165 @@ position: absolute; top: 0; left: 0; - background-color: #333; - color: white; - padding: 8px 15px; - border-radius: 10px; - box-shadow: 0 4px 15px rgba(0,0,0,0.5); + background-color: #2f2f2f; + color: #e0e0e0; + padding: 12px; + border-radius: 8px; + box-shadow: 0 5px 15px rgba(0,0,0,0.3); display: none; flex-direction: column; - gap: 4px; - font-family: sans-serif; - font-size: 12px; + gap: 10px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: 13px; z-index: 1001; - border: 1px solid #555; + border: 1px solid #202020; user-select: none; - min-width: 200px; + min-width: 220px; } #layerforge-custom-shape-menu .menu-line { - margin: 2px 0; - line-height: 18px; + font-weight: 600; + color: #4a90e2; + padding-bottom: 5px; + border-bottom: 1px solid #444; + margin-bottom: 5px; + display: flex; + align-items: center; + gap: 8px; } #layerforge-custom-shape-menu .feature-container { - background-color: #282828; + background-color: #3a3a3a; border-radius: 6px; - margin-top: 6px; - padding: 4px 0; - border: 1px solid #444; + padding: 10px; + border: 1px solid #4a4a4a; } #layerforge-custom-shape-menu .slider-container { - margin: 0 8px 6px 8px; - padding: 4px 8px; + margin-top: 10px; display: none; } #layerforge-custom-shape-menu .slider-label { - font-size: 11px; - margin-bottom: 4px; - color: #ccc; + font-size: 12px; + margin-bottom: 6px; + color: #e0e0e0; } #layerforge-custom-shape-menu input[type="range"] { + -webkit-appearance: none; width: 100%; height: 4px; background: #555; - outline: none; border-radius: 2px; + outline: none; + padding: 0; + margin: 0; +} +#layerforge-custom-shape-menu input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + background: #e0e0e0; + border-radius: 50%; + cursor: pointer; + border: 2px solid #555; + transition: background 0.2s; +} +#layerforge-custom-shape-menu input[type="range"]::-webkit-slider-thumb:hover { + background: #fff; +} +#layerforge-custom-shape-menu input[type="range"]::-moz-range-thumb { + width: 14px; + height: 14px; + background: #e0e0e0; + border-radius: 50%; + cursor: pointer; + border: 2px solid #555; } #layerforge-custom-shape-menu .slider-value-display { - font-size: 10px; + font-size: 11px; text-align: center; - margin-top: 2px; - color: #aaa; + margin-top: 4px; + color: #bbb; + min-height: 14px; } #layerforge-custom-shape-menu .extension-slider-container { - margin: 6px 0; + margin: 10px 0; } #layerforge-custom-shape-menu .checkbox-container { - margin: 6px 0 2px 0; - padding: 4px 8px; + display: flex; + align-items: center; + gap: 10px; + padding: 6px; border-radius: 5px; cursor: pointer; transition: background-color 0.2s; - line-height: 18px; + position: relative; } #layerforge-custom-shape-menu .checkbox-container:hover { - background-color: #555; + background-color: #4a4a4a; +} + +#layerforge-custom-shape-menu .checkbox-container input[type="checkbox"] { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; +} + +#layerforge-custom-shape-menu .checkbox-container .custom-checkbox { + height: 16px; + width: 16px; + background-color: #2a2a2a; + border: 1px solid #666; + border-radius: 3px; + transition: all 0.2s; + position: relative; + flex-shrink: 0; +} + +#layerforge-custom-shape-menu .checkbox-container input:checked ~ .custom-checkbox { + background-color: #3a76d6; + border-color: #3a76d6; +} + +#layerforge-custom-shape-menu .checkbox-container .custom-checkbox::after { + content: ""; + position: absolute; + display: none; + left: 5px; + top: 1px; + width: 4px; + height: 9px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +#layerforge-custom-shape-menu .checkbox-container input:checked ~ .custom-checkbox::after { + display: block; } .layerforge-tooltip { position: fixed; - background-color: #1a1a1a; - color: #ffffff; + background-color: #2f2f2f; + color: #e0e0e0; padding: 8px 12px; border-radius: 6px; font-size: 12px; - font-family: sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.4; max-width: 250px; word-wrap: break-word; - box-shadow: 0 4px 12px rgba(0,0,0,0.6); - border: 1px solid #444; + box-shadow: 0 4px 12px rgba(0,0,0,0.4); + border: 1px solid #202020; z-index: 10000; pointer-events: none; opacity: 0;