From ef5b0a42a6c9655982f7b6443694493e051357ec Mon Sep 17 00:00:00 2001 From: CODEX Date: Fri, 5 Jun 2026 17:04:11 +0300 Subject: [PATCH] feat: standardize Beam viewer environment settings --- frontend/dcViewer.css | 305 ++++++++++++++---- frontend/dcViewer.js | 4 +- frontend/index.html | 32 +- frontend/src/ui/settingsMenu.js | 105 +++--- frontend/src/ui/templatesMenu.js | 19 +- frontend/theme.js | 30 +- server/data/projects/index.json | 8 + ..._0a284bb5-1c82-48b1-a636-e204578a570a.json | 135 ++++++++ ..._0c1b26f3-020c-4ee9-926c-fedf08003304.json | 28 +- ..._605b2cad-e310-4967-a2ee-c16678255cc4.json | 28 +- ..._d992cce8-c689-49f8-be13-c3fee3247218.json | 28 +- ..._e5355c03-983b-4e2f-800c-f57638e9732f.json | 28 +- 12 files changed, 556 insertions(+), 194 deletions(-) create mode 100644 server/data/projects/proj_0a284bb5-1c82-48b1-a636-e204578a570a.json diff --git a/frontend/dcViewer.css b/frontend/dcViewer.css index de1e49e..01ff30e 100644 --- a/frontend/dcViewer.css +++ b/frontend/dcViewer.css @@ -6,8 +6,12 @@ --loading-top: #1c1c1c; --loading-bottom: #1c1c1c; --modal-bg: #1c1c1c; + --modal-bg-alpha: 100%; --modal-focus: #292929; - --modal-border: #292929; + --modal-focus-alpha: 35%; + --modal-border: #1c1c1c; + --modal-element: #262626; + --modal-element-outline: #262626; --modal-radius: 14px; --panel: #1c1c1c; --panel-2: #292929; @@ -21,27 +25,34 @@ --shadow: 0 18px 48px rgba(0, 0, 0, 0.35); --panel-alpha: 1; --panel-radius: 14px; - --toolbar-bg: #1c1c1c; - --toolbar-bg-active: #ffea00; - --toolbar-border: #233044; - --template-fill: #1c1c1c; - --template-outline: #233044; - --template-outline-hover: rgba(255, 234, 0, 0.7); + --toolbar-bg: #292929; + --toolbar-bg-active: #c4ff67; + --toolbar-border: #292929; + --toolbar-outline: #292929; + --template-fill: #292929; + --template-outline: #292929; + --template-outline-hover: #1c1c1c; + --project-btn-fill: #292929; + --project-btn-border: #292929; + --project-btn-hover: #1c1c1c; + --modal-btn-primary: #c4ff67; + --modal-btn-secondary: #292929; + --loader-color: #c4ff67; --template-glow-strength: 80%; - --highlight-color: #ffea00; + --highlight-color: #c4ff67; --cube-text: #242424; --cube-edges: #e0e7ff; - --cube-base: #ffea00; + --cube-base: #ffffff; --cube-hover: #ffffff; --cube-edge-color: #e0e7ff; --cube-edge-alpha: 0.6; - --plus-color: #ffea00; - --measure-line: #ffea00; - --measure-label: #ffea00; + --plus-color: #c4ff67; + --measure-line: #c4ff67; + --measure-label: #c4ff67; --measure-label-text: #292929; - --measure-dot: #ffea00; - --nodedc-glass-control-bg: var(--modal-focus); - --nodedc-glass-control-hover: color-mix(in srgb, var(--modal-focus) 86%, white 8%); + --measure-dot: #c4ff67; + --nodedc-glass-control-bg: var(--modal-element); + --nodedc-glass-control-hover: color-mix(in srgb, var(--modal-element) 86%, white 8%); --nodedc-glass-control-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.01); --tb-size: 25px; --tb-gap: 10px; @@ -341,6 +352,12 @@ header { .side-panel { position: fixed; + --env-control-h: 46px; + --env-button-radius: 17px; + --env-pill-radius: 999px; + --env-glass-control-bg: var(--nodedc-glass-control-bg); + --env-glass-control-hover: var(--nodedc-glass-control-hover); + --env-glass-control-shadow: var(--nodedc-glass-control-shadow); top: 170px; right: 12px; bottom: 12px; @@ -350,11 +367,11 @@ header { background: color-mix(in srgb, var(--modal-bg) var(--modal-bg-alpha, 100%), transparent); border: 1px solid var(--modal-border); border-radius: var(--modal-radius, 16px); - padding: 14px 14px 10px; + padding: 12px; box-shadow: var(--shadow); display: flex; flex-direction: column; - gap: 12px; + gap: 10px; z-index: 11; display: none; } @@ -364,52 +381,60 @@ header { } .inspector-panel-header { - display: flex; + position: sticky; + top: -12px; + z-index: 5; + flex: 0 0 auto; + display: grid; + grid-template-columns: minmax(0, 1fr) var(--env-control-h); align-items: center; - justify-content: space-between; - min-height: 28px; - margin: 0 0 8px; + gap: 10px; + height: calc(var(--env-control-h) + 20px); + min-height: var(--env-control-h); + margin: -12px -12px 0; + padding: 12px 12px 8px 16px; + background: color-mix(in srgb, var(--modal-bg) var(--modal-bg-alpha, 100%), transparent); + border-radius: var(--modal-radius, 16px) var(--modal-radius, 16px) 0 0; + color: var(--text); + font-weight: 700; } .inspector-panel-header h3 { margin: 0; + min-width: 0; + font-size: 13px; + line-height: 1.2; } .inspector-collapse-btn { - position: relative; display: grid; place-items: center; - width: 28px; - height: 28px; - margin: -2px -2px 0 8px; + width: var(--env-control-h); + height: var(--env-control-h); + margin: 0; padding: 0; border: 0; - border-radius: 10px; - background: transparent; - color: var(--modal-btn-primary, var(--accent)); + border-radius: var(--env-button-radius); + background: var(--env-glass-control-bg); + color: rgba(245, 245, 250, 0.78); + box-shadow: var(--env-glass-control-shadow); cursor: pointer; - font: inherit; - font-size: 0; - font-weight: 900; line-height: 1; outline: none; - transition: background 140ms ease, transform 100ms ease; + backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + -webkit-backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + transition: background 140ms ease, color 140ms ease, transform 100ms ease; } -.inspector-collapse-btn::before { - content: ""; - position: absolute; - left: 50%; - top: 38%; - width: 11px; - height: 2px; - border-radius: 999px; - background: currentColor; - transform: translate(-50%, -50%); +.inspector-collapse-btn svg { + display: block; + width: 16px; + height: 16px; } .inspector-collapse-btn:hover { - background: var(--nodedc-glass-control-hover); + background: var(--env-glass-control-hover); + color: #fff; } .inspector-collapse-btn:active { @@ -502,7 +527,7 @@ header { padding: 10px 12px; border-radius: var(--modal-radius, 10px); border: 1px solid var(--modal-border); - background: color-mix(in srgb, var(--modal-focus) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); color: var(--text); font-size: 14px; outline: none; @@ -625,7 +650,7 @@ header { } .tree { - background: color-mix(in srgb, var(--modal-element) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); border-radius: 10px; border: 1px solid var(--modal-element-outline, var(--modal-element)); height: 260px; @@ -722,7 +747,7 @@ header { vertical-align: -1px; border: 0; border-radius: 4px; - background: color-mix(in srgb, var(--modal-element) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); box-shadow: inset 0 0 0 1px var(--modal-element-outline, var(--modal-element)); cursor: pointer; transition: @@ -731,7 +756,7 @@ header { } .tree li > input[type="checkbox"]:checked { - background: var(--highlight-color, var(--accent)); + background: var(--modal-btn-primary, var(--accent)); box-shadow: none; } @@ -740,7 +765,7 @@ header { } .tree li > input[type="checkbox"]:checked:hover { - background: color-mix(in srgb, var(--highlight-color, var(--accent)) 86%, white 14%); + background: color-mix(in srgb, var(--modal-btn-primary, var(--accent)) 86%, white 14%); } .tree li > input[type="checkbox"]:focus, @@ -914,7 +939,7 @@ header { } .nodedc-dropdown-option.nodedc-select__option[data-selected="true"] { - background: var(--modal-focus); + background: var(--modal-element); color: rgba(255, 255, 255, 0.96); } @@ -935,12 +960,17 @@ header { } .templates-panel { position: fixed; + --env-control-h: 46px; + --env-button-radius: 17px; + --env-glass-control-bg: var(--nodedc-glass-control-bg); + --env-glass-control-hover: var(--nodedc-glass-control-hover); + --env-glass-control-shadow: var(--nodedc-glass-control-shadow); left: var(--templates-left, 72px); bottom: var(--templates-bottom, 12px); background: color-mix(in srgb, var(--modal-bg) var(--modal-bg-alpha, 100%), transparent); border: 1px solid var(--modal-border); border-radius: var(--modal-radius, 14px); - padding: 10px; + padding: 12px; display: grid; gap: 10px; width: var(--templates-width, 280px); @@ -957,28 +987,71 @@ header { } .templates-panel .templates-header { - display: flex; + position: sticky; + top: -12px; + z-index: 5; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; align-items: center; - justify-content: space-between; - padding: 6px 6px 0 6px; + gap: 10px; + height: calc(var(--env-control-h) + 20px); + min-height: var(--env-control-h); + margin: -12px -12px 0; + padding: 12px 12px 8px 16px; + border-radius: var(--modal-radius, 14px) var(--modal-radius, 14px) 0 0; + background: color-mix(in srgb, var(--modal-bg) var(--modal-bg-alpha, 100%), transparent); color: var(--text); font-weight: 700; } .templates-panel .templates-title { - font-size: 14px; + font-size: 13px; + line-height: 1.2; +} + +.templates-panel .templates-actions { + display: flex; + gap: 6px; } .templates-panel .templates-close { - width: 26px; - height: 26px; - border-radius: 8px; - border: 1px solid var(--template-outline); - background: color-mix(in srgb, var(--template-fill) var(--modal-focus-alpha, 100%), transparent); - color: var(--text); - cursor: pointer; display: grid; place-items: center; + width: var(--env-control-h); + height: var(--env-control-h); + padding: 0; + border: 0; + border-radius: var(--env-button-radius); + background: var(--env-glass-control-bg); + color: rgba(245, 245, 250, 0.78); + box-shadow: var(--env-glass-control-shadow); + cursor: pointer; + line-height: 1; + outline: none; + backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + -webkit-backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + transition: background 140ms ease, color 140ms ease, transform 100ms ease; +} + +.templates-panel .templates-close svg { + display: block; + width: 16px; + height: 16px; +} + +.templates-panel .templates-close:hover { + background: var(--env-glass-control-hover); + color: #fff; +} + +.templates-panel .templates-close:active { + transform: translateY(1px); +} + +.templates-panel .templates-close:focus, +.templates-panel .templates-close:focus-visible { + outline: none; + box-shadow: none; } .templates-panel .template-list { @@ -1155,7 +1228,7 @@ header { padding: 12px; border-radius: var(--modal-radius, 10px); border: 1px solid var(--modal-border); - background: color-mix(in srgb, var(--modal-focus) var(--modal-focus-alpha, 1), transparent); + background: var(--modal-element); color: var(--text); font-size: 14px; outline: none; @@ -1220,14 +1293,21 @@ header { } .settings-panel .settings-header { + position: sticky; + top: -12px; + z-index: 5; display: grid; grid-template-columns: minmax(0, 1fr) var(--env-control-h); align-items: center; gap: 10px; color: var(--text); font-weight: 700; + height: calc(var(--env-control-h) + 20px); min-height: var(--env-control-h); - padding: 0 0 0 4px; + margin: -12px -12px 0; + padding: 12px 12px 8px 16px; + background: color-mix(in srgb, var(--modal-bg) var(--modal-bg-alpha, 100%), transparent); + border-radius: var(--modal-radius, 14px) var(--modal-radius, 14px) 0 0; } .settings-panel .settings-title { @@ -1290,6 +1370,63 @@ header { margin-bottom: 2px; } +.settings-panel .checkbox-row { + display: grid; + grid-template-columns: minmax(0, 1fr) 26px; + align-items: center; + gap: 10px; + min-height: var(--env-control-h); + padding: 5px 7px 5px 18px; + border-radius: var(--env-pill-radius); + background: var(--env-glass-control-bg); + box-shadow: var(--env-glass-control-shadow); + cursor: pointer; + backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + -webkit-backdrop-filter: blur(24px) saturate(128%) brightness(1.05); +} + +.settings-panel .checkbox-row__label { + min-width: 0; + overflow: hidden; + color: rgba(255, 255, 255, 0.9); + font-size: 12px; + font-weight: 760; + line-height: 1; + text-overflow: ellipsis; + white-space: nowrap; +} + +.settings-panel .checkbox-row input[type="checkbox"] { + appearance: none; + -webkit-appearance: none; + width: 26px; + height: 26px; + margin: 0; + border: 0; + border-radius: 999px; + background: var(--modal-bg); + cursor: pointer; + transition: background 140ms ease, transform 100ms ease; +} + +.settings-panel .checkbox-row input[type="checkbox"]:checked { + background: var(--modal-btn-primary, var(--accent)); +} + +.settings-panel .checkbox-row:hover { + background: var(--env-glass-control-hover); +} + +.settings-panel .checkbox-row input[type="checkbox"]:active { + transform: scale(0.94); +} + +.settings-panel .checkbox-row input[type="checkbox"]:focus, +.settings-panel .checkbox-row input[type="checkbox"]:focus-visible { + outline: none; + box-shadow: none; +} + .settings-panel .color-row { display: grid; grid-template-columns: minmax(110px, 1fr) minmax(150px, 168px); @@ -1407,7 +1544,7 @@ header { top: 50%; z-index: 2; font-size: 12px; - font-weight: 760; + font-weight: 500; line-height: 1; transform: translateY(-50%); pointer-events: none; @@ -1659,13 +1796,47 @@ header { .settings-panel input[type="number"] { width: 100%; max-width: 86px; - background: color-mix(in srgb, var(--modal-element) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); border: 1px solid var(--modal-element-outline, var(--modal-element)); border-radius: 8px; color: var(--text); padding: 5px 6px; } +.settings-panel input.env-number-field[type="number"] { + width: 100%; + max-width: none; + height: var(--env-control-h); + border: 0; + border-radius: var(--env-pill-radius); + padding: 0 18px; + background: var(--env-glass-control-bg); + box-shadow: var(--env-glass-control-shadow); + color: rgba(255, 255, 255, 0.86); + font-size: 12px; + font-weight: 500; + line-height: 1; + text-align: center; + outline: none; + appearance: textfield; + -moz-appearance: textfield; + backdrop-filter: blur(24px) saturate(128%) brightness(1.05); + -webkit-backdrop-filter: blur(24px) saturate(128%) brightness(1.05); +} + +.settings-panel input.env-number-field[type="number"]::-webkit-outer-spin-button, +.settings-panel input.env-number-field[type="number"]::-webkit-inner-spin-button { + margin: 0; + appearance: none; + -webkit-appearance: none; +} + +.settings-panel input.env-number-field[type="number"]:focus, +.settings-panel input.env-number-field[type="number"]:focus-visible { + border: 0; + box-shadow: var(--env-glass-control-shadow); +} + .settings-panel .env-color-field .env-color-field__value input[type="text"] { width: 100%; max-width: none; @@ -1689,7 +1860,7 @@ header { } .log { - background: color-mix(in srgb, var(--modal-element) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); border: 1px solid var(--modal-element-outline, var(--modal-element)); } @@ -1810,7 +1981,7 @@ header { .transform-grid input { flex: 1; - background: color-mix(in srgb, var(--modal-element) var(--modal-focus-alpha, 100%), transparent); + background: var(--modal-element); border: 1px solid var(--modal-element-outline, var(--modal-element)); border-radius: 8px; padding: 6px 8px; diff --git a/frontend/dcViewer.js b/frontend/dcViewer.js index bac4cf9..3753381 100644 --- a/frontend/dcViewer.js +++ b/frontend/dcViewer.js @@ -3,8 +3,8 @@ const SDK_URL = "./lib/dc-camera-context.es.js"; import { createLogo } from "./src/ui/logo.js"; import { toolbarConfig, applyToolbarVars } from "./src/ui/toolbar.js"; -import { createTemplatesMenu } from "./src/ui/templatesMenu.js"; -import { createSettingsMenu } from "./src/ui/settingsMenu.js?v=2"; +import { createTemplatesMenu } from "./src/ui/templatesMenu.js?v=2"; +import { createSettingsMenu } from "./src/ui/settingsMenu.js?v=5"; import { createMeasurementModal } from "./src/ui/measurementModal.js"; import { createGlassSelect } from "./src/ui/glassSelect.js"; import { createSliderControl } from "./src/ui/controls/slider.js"; diff --git a/frontend/index.html b/frontend/index.html index dc5f2c9..f0c8a05 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -52,7 +52,9 @@ set("--toolbar-border", s.toolbarBorder); set("--toolbar-outline", s.toolbarOutline); set("--modal-bg", s.modalBg); + set("--modal-bg-alpha", s.modalBgAlpha !== undefined ? `${s.modalBgAlpha * 100}%` : undefined); set("--modal-focus", s.modalFocus); + set("--modal-focus-alpha", s.modalFocusAlpha !== undefined ? `${s.modalFocusAlpha * 100}%` : undefined); set("--modal-border", s.modalBorder); set("--modal-element", s.modalElement); set("--modal-element-outline", s.modalElementOutline); @@ -87,7 +89,7 @@ - +
@@ -125,17 +127,21 @@