refactor(ui): clarify shared field CSS ownership

This commit is contained in:
Mazeyar Moeini Feizabadi committed 2026-10-21 18:41:17 +02:00
1 parent a20673e78d
commit 7103c29194
6 files changed
+53 -18

No files matched your search

+8
View File
@@ -749,6 +749,14 @@ teardown. CCTV effective-pose conversion and tuner/device operations remain
feature responsibilities. A Vue replacement can reuse this contract and CSS; feature responsibilities. A Vue replacement can reuse this contract and CSS;
it replaces DOM construction, rather than adding a second state owner. it replaces DOM construction, rather than adding a second state owner.
The shared stylesheet owns field surfaces and disabled opacity; feature and theme
palettes use `--gev-field-background`, `--gev-field-border-color`,
`--gev-field-color` and `--gev-field-disabled-opacity`. Radio retains its own
compact density and arrow space. CCTV owns calibration editor width in
`cctv.css`; the shared inline density does not impose a feature-specific width.
Cyber supplies a shared-field palette explicitly and keeps its legacy native
field rules separate, so Radio's palette remains an intentional exception.
### Read-only status badges ### Read-only status badges
`src/ui/statusBadge.js` constructs/updates ordinary badges without listeners, `src/ui/statusBadge.js` constructs/updates ordinary badges without listeners,
+11
View File
@@ -1233,6 +1233,17 @@ Feature owners retain bounds, steps, formatted values, input/change timing and
listener cleanup. The radio tuning dial, imagery comparison divider and event listener cleanup. The radio tuning dial, imagery comparison divider and event
comparison/progression controls keep their specialized presentation and behavior. comparison/progression controls keep their specialized presentation and behavior.
## Shared control CSS ownership
Shared styles own ordinary control surfaces and interaction states; feature CSS
owns surrounding layout and context-specific sizing. CCTV's calibration editor
width lives in `ui/styles/cctv.css`, while the shared inline field variant owns
only density and spinner treatment. Radio supplies its field palette and disabled
opacity through the `--gev-field-*` variables, retaining compact typography and
arrow space locally. Cyber supplies shared-field palette variables explicitly;
its legacy native-field palette rules exclude `.gev-field`. These ownership
boundaries preserve the current Tactical/Cyber appearance and native behavior.
## Ordinary status badges ## Ordinary status badges
CCTV source/frame labels, calibration provenance and Weather coverage labels use CCTV source/frame labels, calibration provenance and Weather coverage labels use
+4
View File
@@ -109,6 +109,10 @@ html:not([lang='en']) .cctv-controls .scene-btn {
gap: 5px; gap: 5px;
} }
.cctv-cal-input {
width: 58px;
}
.cctv-cal-value { .cctv-cal-value {
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 9px; font-size: 9px;
+10 -1
View File
@@ -544,12 +544,21 @@
text-shadow: none; text-shadow: none;
} }
:root[data-ui-theme='cyber'] :where(.pp-select, select, input, textarea) { :root[data-ui-theme='cyber']
:where(.pp-select, select, input, textarea):where(:not(.gev-field)) {
border-color: rgba(206, 222, 226, 0.24); border-color: rgba(206, 222, 226, 0.24);
background-color: rgba(26, 35, 39, 0.96); background-color: rgba(26, 35, 39, 0.96);
color: var(--text-primary); color: var(--text-primary);
} }
/* Shared fields consume theme palettes through their own surface rule.
Feature palettes (Radio) retain precedence without restyling native fields. */
:root[data-ui-theme='cyber'] .gev-field {
--gev-field-border-color: rgba(206, 222, 226, 0.24);
--gev-field-background: rgba(26, 35, 39, 0.96);
--gev-field-color: var(--text-primary);
}
:root[data-ui-theme='cyber'] :root[data-ui-theme='cyber']
:where( :where(
.panel-title, .panel-title,
+10 -11
View File
@@ -1,11 +1,11 @@
/* Native selects and numeric inputs. Features own options, constraints and /* Native selects and numeric inputs. This file owns the field surface/states;
commit timing; density variants do not introduce custom keyboard behavior. */ features and themes supply palette variables and retain their own layout. */
.gev-field { .gev-field {
min-width: 0; min-width: 0;
background: rgba(255, 255, 255, 0.06); background: var(--gev-field-background, rgba(255, 255, 255, 0.06));
border: 1px solid rgba(255, 255, 255, 0.14); border: 1px solid var(--gev-field-border-color, rgba(255, 255, 255, 0.14));
border-radius: 7px; border-radius: 7px;
color: var(--text-primary); color: var(--gev-field-color, var(--text-primary));
padding: 6px 8px; padding: 6px 8px;
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: 12px; font-size: 12px;
@@ -18,7 +18,7 @@
} }
.gev-field:disabled { .gev-field:disabled {
opacity: 0.45; opacity: var(--gev-field-disabled-opacity, 0.45);
} }
.gev-field--compact { .gev-field--compact {
@@ -30,15 +30,14 @@
padding: 2px 6px; padding: 2px 6px;
} }
/* Effective-pose editors must fit inside CCTV value chips. Retain their /* Compact inline editors share density and hide native number spinners.
existing spinner-free surface; calibration conversion stays with the owner. */ Their containing feature sets width to fit the surrounding readout. */
.gev-field--inline { .gev-field--inline {
width: 58px;
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 9px; font-size: 9px;
letter-spacing: 0.7px; letter-spacing: 0.7px;
background: rgba(0, 212, 255, 0.1); --gev-field-background: rgba(0, 212, 255, 0.1);
border-color: rgba(0, 212, 255, 0.5); --gev-field-border-color: rgba(0, 212, 255, 0.5);
border-radius: 4px; border-radius: 4px;
padding: 1px 3px; padding: 1px 3px;
-moz-appearance: textfield; -moz-appearance: textfield;
+10 -6
View File
@@ -49,13 +49,15 @@
min-height: 36px; min-height: 36px;
} }
#radio-filter { #radio-filter {
min-width: 0; /* Radio owns its compact density and arrow space; shared fields paint the
palette and disabled state, including this intentional theme exception. */
padding: 7px 24px 7px 8px; padding: 7px 24px 7px 8px;
border: 1px solid rgba(65, 220, 231, 0.28);
border-radius: 5px; border-radius: 5px;
color: #c5faff;
background: rgba(5, 24, 31, 0.88);
font: 9px/1.2 var(--font-mono); font: 9px/1.2 var(--font-mono);
--gev-field-border-color: rgba(65, 220, 231, 0.28);
--gev-field-color: #c5faff;
--gev-field-background: rgba(5, 24, 31, 0.88);
--gev-field-disabled-opacity: 0.42;
} }
.radio-station-card { .radio-station-card {
display: grid; display: grid;
@@ -273,11 +275,13 @@ html:not([lang='en']) .radio-transport button {
color: #fff; color: #fff;
outline: none; outline: none;
} }
.radio-transport button:disabled, .radio-transport button:disabled {
#radio-filter:disabled {
opacity: 0.42; opacity: 0.42;
cursor: not-allowed; cursor: not-allowed;
} }
#radio-filter:disabled {
cursor: not-allowed;
}
#radio-play-btn.active { #radio-play-btn.active {
color: #fff; color: #fff;
border-color: rgba(101, 247, 255, 0.8); border-color: rgba(101, 247, 255, 0.8);