diff --git a/css/icons.css b/css/icons.css index a3b8ca9..e808b3b 100644 --- a/css/icons.css +++ b/css/icons.css @@ -1,3 +1,34 @@ +.ui.inline-icon { + position: relative; + + display: flex; +} + +.ui.inline-icon::after { + content: ""; + display: block; + + position: absolute; + + box-sizing: border-box; + + margin: auto; + top: 15%; + bottom: 15%; + + mask-size: contain; + mask-repeat: no-repeat; + + max-height: 70%; + aspect-ratio: 1; + + left: 0; + right: 0; + + background-color: var(--c-text); +} + +.ui.inline-icon.icon-eye-off::after, .ui.icon > .icon-eye-off { -webkit-mask-image: url("../res/icons/eye-off.svg"); mask-image: url("../res/icons/eye-off.svg"); @@ -42,3 +73,57 @@ -webkit-mask-image: url("../res/icons/settings.svg"); mask-image: url("../res/icons/settings.svg"); } + +.ui.inline-icon.icon-grid::after, +.ui.icon > .icon-grid { + -webkit-mask-image: url("../res/icons/grid.svg"); + mask-image: url("../res/icons/grid.svg"); +} + +.ui.inline-icon.icon-venetian-mask::after, +.ui.icon > .icon-venetian-mask { + -webkit-mask-image: url("../res/icons/venetian-mask.svg"); + mask-image: url("../res/icons/venetian-mask.svg"); +} + +.ui.inline-icon.icon-brush::after, +.ui.icon > .icon-brush { + -webkit-mask-image: url("../res/icons/brush.svg"); + mask-image: url("../res/icons/brush.svg"); +} + +.ui.inline-icon.icon-paintbrush::after, +.ui.icon > .icon-paintbrush { + -webkit-mask-image: url("../res/icons/paintbrush.svg"); + mask-image: url("../res/icons/paintbrush.svg"); +} + +.ui.inline-icon.icon-expand::after, +.ui.icon > .icon-expand { + -webkit-mask-image: url("../res/icons/expand.svg"); + mask-image: url("../res/icons/expand.svg"); +} + +.ui.inline-icon.icon-pin::after, +.ui.icon > .icon-pin { + -webkit-mask-image: url("../res/icons/pin.svg"); + mask-image: url("../res/icons/pin.svg"); +} + +.ui.inline-icon.icon-box-select::after, +.ui.icon > .icon-box-select { + -webkit-mask-image: url("../res/icons/box-select.svg"); + mask-image: url("../res/icons/box-select.svg"); +} + +.ui.inline-icon.icon-maximize::after, +.ui.icon > .icon-maximize { + -webkit-mask-image: url("../res/icons/maximize.svg"); + mask-image: url("../res/icons/maximize.svg"); +} + +.ui.inline-icon.icon-clipboard-list::after, +.ui.icon > .icon-clipboard-list { + -webkit-mask-image: url("../res/icons/clipboard-list.svg"); + mask-image: url("../res/icons/clipboard-list.svg"); +} diff --git a/css/ui/generic.css b/css/ui/generic.css index 93caf35..801e2ba 100644 --- a/css/ui/generic.css +++ b/css/ui/generic.css @@ -37,6 +37,8 @@ /* Slider Input */ div.slider-wrapper { margin: 5px; + margin-left: 0; + margin-right: 0; } div.slider-wrapper { @@ -100,6 +102,83 @@ div.slider-wrapper > input.text { background-color: transparent; } +/* Checkbox Input */ +div.checkbox-array { + display: flex; + + margin-top: 5px; + margin-bottom: 5px; +} + +input.oo-checkbox[type="checkbox"] { + /* Hide original checkbox */ + -webkit-appearance: none; + appearance: none; + + flex: 1; + + margin: 0; + + min-width: 28px; + height: 28px; + + background-color: var(--c-primary); + + cursor: pointer; +} + +input.oo-checkbox[type="checkbox"]:disabled { + background-color: #666 !important; + cursor: default !important; +} + +input.oo-checkbox[type="checkbox"]:disabled:hover { + filter: none !important; +} + +input.oo-checkbox[type="checkbox"]:checked::after { + background-color: #66f; +} + +input.oo-checkbox[type="checkbox"]:hover { + background-color: var(--c-hover); +} + +input.oo-checkbox[type="checkbox"]:active { + filter: brightness(120%); +} + +input.oo-checkbox[type="checkbox"]:first-child { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} + +input.oo-checkbox[type="checkbox"]:last-child { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} + +/* Mask Inversion Checkbox */ +input.oo-checkbox[type="checkbox"].invert-mask-checkbox::after { + background-color: var(--c-text); +} + +input.oo-checkbox[type="checkbox"].invert-mask-checkbox:hover { + filter: brightness(120%); +} + +input.oo-checkbox[type="checkbox"].invert-mask-checkbox:active { + filter: brightness(140%); +} + +input.oo-checkbox[type="checkbox"].invert-mask-checkbox { + background-color: #922; +} + +input.oo-checkbox[type="checkbox"].invert-mask-checkbox:checked { + background-color: #229; +} + /* Bare Select */ .bareselector { diff --git a/js/lib/toolbar.js b/js/lib/toolbar.js index 232b0fe..10e48f8 100644 --- a/js/lib/toolbar.js +++ b/js/lib/toolbar.js @@ -145,17 +145,24 @@ const toolbar = { * Premade inputs for populating the context menus */ const _toolbar_input = { - checkbox: (state, dataKey, text, cb = null) => { + checkbox: (state, dataKey, text, classes, cb = null) => { if (state[dataKey] === undefined) state[dataKey] = false; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; + checkbox.classList.add("oo-checkbox", "ui", "inline-icon"); + + if (typeof classes === "string") classes = [classes]; + + if (classes) checkbox.classList.add(...classes); checkbox.checked = state[dataKey]; checkbox.onchange = () => { state[dataKey] = checkbox.checked; cb && cb(); }; + checkbox.title = text; + const label = document.createElement("label"); label.appendChild(checkbox); label.appendChild(new Text(text)); diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index 5786307..dc1d190 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -349,13 +349,16 @@ const colorBrushTool = () => state.ctxmenu = {}; // Affects Mask Checkbox + const array = document.createElement("div"); const affectMaskCheckbox = _toolbar_input.checkbox( state, "affectMask", - "Affect Mask" - ).label; + "Affect Mask", + "icon-venetian-mask" + ).checkbox; + array.appendChild(affectMaskCheckbox); - state.ctxmenu.affectMaskCheckbox = affectMaskCheckbox; + state.ctxmenu.affectMaskCheckbox = array; // Brush size slider const brushSizeSlider = _toolbar_input.slider( diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index f0e1fab..49dd376 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -1469,24 +1469,27 @@ const dreamTool = () => state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, "snapToGrid", - "Snap To Grid" - ).label; + "Snap To Grid", + "icon-grid" + ).checkbox; // Invert Mask Checkbox state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox( state, "invertMask", "Invert Mask", + ["icon-venetian-mask", "invert-mask-checkbox"], () => { setMask(state.invertMask ? "hold" : "clear"); } - ).label; + ).checkbox; // Keep Masked Content Checkbox state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox( state, "keepUnmasked", "Keep Unmasked", + "icon-pin", () => { if (state.keepUnmasked) { state.ctxmenu.keepUnmaskedBlurSlider.classList.remove( @@ -1496,7 +1499,7 @@ const dreamTool = () => state.ctxmenu.keepUnmaskedBlurSlider.classList.add("invisible"); } } - ).label; + ).checkbox; // Keep Masked Content Blur Slider state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider( @@ -1515,8 +1518,9 @@ const dreamTool = () => state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox( state, "preserveMasks", - "Preserve Brushed Masks" - ).label; + "Preserve Brushed Masks", + "icon-paintbrush" + ).checkbox; // Overmasking Slider state.ctxmenu.overMaskPxLabel = _toolbar_input.slider( @@ -1546,14 +1550,16 @@ const dreamTool = () => } menu.appendChild(state.ctxmenu.cursorSizeSlider); - menu.appendChild(state.ctxmenu.snapToGridLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.invertMaskLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.keepUnmaskedLabel); + const array = document.createElement("div"); + array.classList.add("checkbox-array"); + array.appendChild(state.ctxmenu.snapToGridLabel); + //menu.appendChild(document.createElement("br")); + array.appendChild(state.ctxmenu.invertMaskLabel); + array.appendChild(state.ctxmenu.preserveMasksLabel); + //menu.appendChild(document.createElement("br")); + array.appendChild(state.ctxmenu.keepUnmaskedLabel); + menu.appendChild(array); menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider); - menu.appendChild(state.ctxmenu.preserveMasksLabel); - menu.appendChild(document.createElement("br")); menu.appendChild(state.ctxmenu.overMaskPxLabel); menu.appendChild(state.ctxmenu.eagerGenerateCountLabel); }, @@ -1974,24 +1980,27 @@ const img2imgTool = () => state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, "snapToGrid", - "Snap To Grid" - ).label; + "Snap To Grid", + "icon-grid" + ).checkbox; // Invert Mask Checkbox state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox( state, "invertMask", "Invert Mask", + ["icon-venetian-mask", "invert-mask-checkbox"], () => { setMask(state.invertMask ? "hold" : "clear"); } - ).label; + ).checkbox; // Keep Masked Content Checkbox state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox( state, "keepUnmasked", "Keep Unmasked", + "icon-pin", () => { if (state.keepUnmasked) { state.ctxmenu.keepUnmaskedBlurSlider.classList.remove( @@ -2007,7 +2016,7 @@ const img2imgTool = () => ); } } - ).label; + ).checkbox; // Keep Masked Content Blur Slider state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider( @@ -2032,15 +2041,17 @@ const img2imgTool = () => state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox( state, "preserveMasks", - "Preserve Brushed Masks" - ).label; + "Preserve Brushed Masks", + "icon-paintbrush" + ).checkbox; // Inpaint Full Resolution Checkbox state.ctxmenu.fullResolutionLabel = _toolbar_input.checkbox( state, "fullResolution", - "Inpaint Full Resolution" - ).label; + "Inpaint Full Resolution", + "icon-expand" + ).checkbox; // Denoising Strength Slider state.ctxmenu.denoisingStrengthSlider = _toolbar_input.slider( @@ -2059,8 +2070,9 @@ const img2imgTool = () => state.ctxmenu.borderMaskGradientCheckbox = _toolbar_input.checkbox( state, "gradient", - "Border Mask Gradient" - ).label; + "Border Mask Gradient", + "icon-box-select" + ).checkbox; // Border Mask Size Slider state.ctxmenu.borderMaskSlider = _toolbar_input.slider( @@ -2107,20 +2119,22 @@ const img2imgTool = () => } menu.appendChild(state.ctxmenu.cursorSizeSlider); - menu.appendChild(state.ctxmenu.snapToGridLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.invertMaskLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.keepUnmaskedLabel); + const array = document.createElement("div"); + array.classList.add("checkbox-array"); + array.appendChild(state.ctxmenu.snapToGridLabel); + array.appendChild(state.ctxmenu.invertMaskLabel); + array.appendChild(state.ctxmenu.preserveMasksLabel); + array.appendChild(state.ctxmenu.keepUnmaskedLabel); + menu.appendChild(array); menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider); menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak); - menu.appendChild(state.ctxmenu.preserveMasksLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.fullResolutionLabel); - menu.appendChild(document.createElement("br")); menu.appendChild(state.ctxmenu.inpaintTypeSelect); menu.appendChild(state.ctxmenu.denoisingStrengthSlider); - menu.appendChild(state.ctxmenu.borderMaskGradientCheckbox); + const btnArray2 = document.createElement("div"); + btnArray2.classList.add("checkbox-array"); + btnArray2.appendChild(state.ctxmenu.fullResolutionLabel); + btnArray2.appendChild(state.ctxmenu.borderMaskGradientCheckbox); + menu.appendChild(btnArray2); menu.appendChild(state.ctxmenu.borderMaskSlider); menu.appendChild(state.ctxmenu.eagerGenerateCountLabel); }, diff --git a/js/ui/tool/select.js b/js/ui/tool/select.js index c62cf14..11eb700 100644 --- a/js/ui/tool/select.js +++ b/js/ui/tool/select.js @@ -633,23 +633,26 @@ const selectTransformTool = () => state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, "snapToGrid", - "Snap To Grid" - ).label; + "Snap To Grid", + "icon-grid" + ).checkbox; // Keep Aspect Ratio state.ctxmenu.keepAspectRatioLabel = _toolbar_input.checkbox( state, "keepAspectRatio", - "Keep Aspect Ratio" - ).label; + "Keep Aspect Ratio", + "icon-maximize" + ).checkbox; // Use Clipboard const clipboardCheckbox = _toolbar_input.checkbox( state, "useClipboard", - "Use clipboard" + "Use clipboard", + "icon-clipboard-list" ); - state.ctxmenu.useClipboardLabel = clipboardCheckbox.label; + state.ctxmenu.useClipboardLabel = clipboardCheckbox.checkbox; if (!(navigator.clipboard && navigator.clipboard.write)) clipboardCheckbox.checkbox.disabled = true; // Disable if not available @@ -760,11 +763,12 @@ const selectTransformTool = () => state.ctxmenu.actionArray = actionArray; state.ctxmenu.visibleActionArray = visibleActionArray; } - menu.appendChild(state.ctxmenu.snapToGridLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.keepAspectRatioLabel); - menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.useClipboardLabel); + const array = document.createElement("div"); + array.classList.add("checkbox-array"); + array.appendChild(state.ctxmenu.snapToGridLabel); + array.appendChild(state.ctxmenu.keepAspectRatioLabel); + array.appendChild(state.ctxmenu.useClipboardLabel); + menu.appendChild(array); menu.appendChild(state.ctxmenu.selectionPeekOpacitySlider); menu.appendChild(state.ctxmenu.actionArray); menu.appendChild(state.ctxmenu.visibleActionArray); diff --git a/js/ui/tool/stamp.js b/js/ui/tool/stamp.js index 74be4ad..fc1cb89 100644 --- a/js/ui/tool/stamp.js +++ b/js/ui/tool/stamp.js @@ -368,11 +368,17 @@ const stampTool = () => if (!state.ctxmenu) { state.ctxmenu = {}; // Snap To Grid Checkbox - state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( - state, - "snapToGrid", - "Snap To Grid" - ).label; + const array = document.createElement("div"); + array.classList.add("checkbox-array"); + array.appendChild( + _toolbar_input.checkbox( + state, + "snapToGrid", + "Snap To Grid", + "icon-grid" + ).checkbox + ); + state.ctxmenu.snapToGridLabel = array; // Create resource list const uploadButtonId = `upload-btn-${guid()}`; diff --git a/res/icons/clipboard-list.svg b/res/icons/clipboard-list.svg new file mode 100644 index 0000000..45bbcf5 --- /dev/null +++ b/res/icons/clipboard-list.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/icons/equal.svg b/res/icons/equal.svg new file mode 100644 index 0000000..6b5c5c8 --- /dev/null +++ b/res/icons/equal.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/res/icons/expand.svg b/res/icons/expand.svg new file mode 100644 index 0000000..6f5864a --- /dev/null +++ b/res/icons/expand.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/res/icons/grid.svg b/res/icons/grid.svg new file mode 100644 index 0000000..a7daf6d --- /dev/null +++ b/res/icons/grid.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/res/icons/maximize.svg b/res/icons/maximize.svg new file mode 100644 index 0000000..5c8a6e3 --- /dev/null +++ b/res/icons/maximize.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/res/icons/pin.svg b/res/icons/pin.svg new file mode 100644 index 0000000..aa858be --- /dev/null +++ b/res/icons/pin.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/res/icons/square.svg b/res/icons/square.svg new file mode 100644 index 0000000..ba8d095 --- /dev/null +++ b/res/icons/square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/res/icons/venetian-mask.svg b/res/icons/venetian-mask.svg new file mode 100644 index 0000000..6cd8962 --- /dev/null +++ b/res/icons/venetian-mask.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file