Merge pull request #1287 from bilawalsidhu/codex/shared-sliders

refactor(ui): unify ordinary slider components and styling
This commit is contained in:
Mazeyar Moeini Feizabadi authored and GitHub committed 2026-10-21 14:19:55 +02:00
commit 5a1598fd9e
20 files changed
+200 -229

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
- Give ordinary sliders a shared native control and consistent track, thumb,
value, focus and disabled styling while preserving feature behavior and
specialized controls (mazy1998, #1287).
+9
View File
@@ -1224,6 +1224,15 @@ The application supplies actions and retains effect settings, restore claims and
rendering. Native keyboard editing, model modes and current defaults are preserved.
Destroying the UI removes these listeners before asynchronous teardown.
Ordinary sliders share the native range component in `ui/slider.js` and the
`gev-quantitative-slider` surface in `ui/styles/slider.css`. Display, shader
parameters, volume, replay speed, weather settings/history, imagery opacity and
Street View's date filter use the same rail, thumb, value styling, keyboard focus and disabled state.
Generated controls use `createSlider`; static templates apply the same class.
Feature owners retain bounds, steps, formatted values, input/change timing and
listener cleanup. The radio tuning dial, imagery comparison divider and event
comparison/progression controls keep their specialized presentation and behavior.
## Segmented selectors
Segmented selectors use the controlled DOM adapter in `ui/segmentedControl.js`
+1
View File
@@ -304,6 +304,7 @@
"src/ui/styles/status.css",
"src/ui/styles/layers.css",
"src/ui/styles/controls.css",
"src/ui/styles/slider.css",
"src/ui/styles/cctv.css",
"src/ui/styles/foundation.css",
"src/ui/styles/first-run.css",
+5
View File
@@ -422,6 +422,7 @@
"src/ui/visualInput.js",
"src/ui/applicationShortcuts.js",
"src/ui/styleParameters.js",
"src/ui/slider.js",
"src/i18n/index.js",
"src/i18n/locale.js",
"src/i18n/locales/es.json",
@@ -480,6 +481,7 @@
"src/ui/weatherPanel.js",
"src/ui/railCards.js",
"src/ui/railCardBlocks.js",
"src/ui/slider.js",
"src/ui/chipGroup.js",
"src/ui/rowList.js",
"src/ui/railTimeline.js",
@@ -740,6 +742,7 @@
"src/ui/shellElements.js",
"src/ui/shellFeedback.js",
"src/ui/styleParameters.js",
"src/ui/slider.js",
"src/ui/surfaceKeyboard.js",
"src/ui/uiLifetime.js",
"src/ui/visualEffects.js",
@@ -2216,6 +2219,7 @@
"src/ui/shellElements.js",
"src/ui/shellFeedback.js",
"src/ui/styleParameters.js",
"src/ui/slider.js",
"src/ui/surfaceKeyboard.js",
"src/ui/uiLifetime.js",
"src/ui/visualEffects.js",
@@ -3209,6 +3213,7 @@
"src/ui/applicationShortcuts.js",
"src/ui/effects.js",
"src/ui/styleParameters.js",
"src/ui/slider.js",
"src/ui/uiLifetime.js",
"src/ui/visualEffects.js",
"src/ui/visualInput.js",
+32
View File
@@ -183,6 +183,38 @@ try {
return manager.bloomEnabled !== before;
}),
);
const sliders = await page.evaluate(() => {
const ordinary = [
...document.querySelectorAll('input[type="range"]'),
].filter(
(input) => !input.matches('#radio-tuner-slider, .bhote-event-range'),
);
return {
count: ordinary.length,
shared: ordinary.every((input) =>
input.classList.contains('gev-quantitative-slider'),
),
surface: ordinary.every((input) => {
const style = getComputedStyle(input);
return (
style.height === '18px' &&
style.appearance === 'none' &&
style.padding === '0px' &&
style.borderWidth === '0px' &&
(!input.disabled ||
(style.opacity === '0.42' && style.cursor === 'not-allowed'))
);
}),
tunerSeparate: !document
.getElementById('radio-tuner-slider')
.classList.contains('gev-quantitative-slider'),
};
});
check(
'ordinary sliders share one native surface',
sliders.count > 10 && sliders.shared && sliders.surface,
);
check('radio tuning keeps its specialized control', sliders.tunerSeparate);
fs.mkdirSync('qa-shots/visual-input', { recursive: true });
await page.screenshot({ path: 'qa-shots/visual-input/desktop.png' });
await page.setViewport({ width: 620, height: 900 });
+1 -1
View File
@@ -29,5 +29,5 @@ test('the first-run checkbox keeps its native visible label', () => {
test('generated style sliders use the visible parameter label as their name', () => {
assert.match(parameters, /label\.textContent\s*=\s*t\(metadata\.label\);/);
assert.match(parameters, /slider\.setAttribute\(['"]aria-label['"],\s*t\(metadata\.label\)\)/);
assert.match(parameters, /ariaLabel:\s*t\(metadata\.label\)/);
});
+6 -6
View File
@@ -2,6 +2,7 @@ import { t } from '../i18n/index.js';
import { syncChipGroup } from './chipGroup.js';
import { syncRowList } from './rowList.js';
import { formatScaleLabel, unitLabel } from './unitLabels.js';
import { createSlider } from './slider.js';
const set = (node, key, value) => {
if (node[key] !== value) node[key] = value;
@@ -90,12 +91,11 @@ export function createRailCardBlocks({ container, cardId, onParams }) {
'rail-card-setting-range-label',
block.rangeRow,
);
block.rangeInput = make(
'input',
'rail-card-setting-range',
block.rangeRow,
);
block.rangeInput.type = 'range';
block.rangeInput = createSlider({
documentRef: document,
className: 'rail-card-setting-range',
});
block.rangeRow.appendChild(block.rangeInput);
block.rangeValue = make(
'span',
'rail-card-setting-range-value',
+10 -8
View File
@@ -1,4 +1,5 @@
import { formatUtcDayMonth, t } from '../i18n/index.js';
import { createSlider } from './slider.js';
const set = (node, key, value) => {
if (node[key] !== value) node[key] = value;
};
@@ -43,14 +44,15 @@ export function createRailTimeline({
return node;
};
const previous = makeButton('‹', t('Earlier observation'), row);
const slider = document.createElement('input');
slider.type = 'range';
slider.className = `gev-quantitative-slider${sliderClassName ? ` ${sliderClassName}` : ''}`;
slider.min = '0';
slider.max = '0';
slider.step = '1';
slider.value = '0';
slider.setAttribute('aria-label', t('Observed history'));
const slider = createSlider({
documentRef: document,
className: sliderClassName,
min: '0',
max: '0',
step: '1',
value: '0',
ariaLabel: t('Observed history'),
});
row.appendChild(slider);
const next = makeButton('›', t('Later observation'), row);
const controls = document.createElement('div');
+7 -5
View File
@@ -12,6 +12,7 @@ import { formatNumber, msg, t, tn, translateKnown } from '../i18n/index.js';
import { createRailCardBlocks } from './railCardBlocks.js';
import { createRailCards } from './railCards.js';
import { createImagerySplit } from './imagerySplit.js';
import { createSlider } from './slider.js';
import { createSegmentedControl } from './segmentedControl.js';
import {
PRODUCTS,
@@ -328,16 +329,17 @@ export function createRecentImageryPanel({
const opacityLabel = el('label', 'ri-opacity-label', controls);
el('span', '', opacityLabel, t('OPACITY'));
const opacityValue = el('span', 'ri-opacity-value', opacityLabel, '100%');
const opacity = el('input', 'ri-opacity', controls);
opacity.id = 'ri-opacity';
Object.assign(opacity, {
type: 'range',
const opacity = createSlider({
documentRef: document,
className: 'ri-opacity',
min: '0',
max: '100',
step: '1',
value: '100',
ariaLabel: t('Imagery opacity'),
});
opacity.setAttribute('aria-label', t('Imagery opacity'));
opacity.id = 'ri-opacity';
controls.appendChild(opacity);
opacityLabel.htmlFor = 'ri-opacity';
// Its slot is always there; it is only usable while a swipe is live.
const swap = el('button', 'data-toggle-chip ri-swap', controls, t('SWAP'));
+32
View File
@@ -0,0 +1,32 @@
/**
* Build the shared native slider. Feature owners retain their input/change
* listeners, formatting and teardown; this component installs no handlers.
* Static sliders use the same gev-quantitative-slider class in their template.
* @param {object} options
* @param {Document} [options.documentRef] Document that owns the input.
* @param {string} [options.className] Additional feature/layout hooks.
* @param {number|string} [options.min]
* @param {number|string} [options.max]
* @param {number|string} [options.step]
* @param {number|string} [options.value]
* @param {string} [options.ariaLabel] Already translated accessible name.
* @returns {HTMLInputElement}
*/
export function createSlider({
documentRef = globalThis.document,
className = '',
min,
max,
step,
value,
ariaLabel,
} = {}) {
const input = documentRef.createElement('input');
input.type = 'range';
input.className = `gev-quantitative-slider${className ? ` ${className}` : ''}`;
for (const [key, setting] of Object.entries({ min, max, step, value })) {
if (setting !== undefined) input[key] = setting;
}
if (ariaLabel !== undefined) input.setAttribute('aria-label', ariaLabel);
return input;
}
+10 -8
View File
@@ -1,4 +1,5 @@
import { formatNumber, t } from '../i18n/index.js';
import { createSlider } from './slider.js';
/** A slider value in the UI language: 0.85 in English, 0,85 in Spanish. */
const formatParam = (value, digits) =>
@@ -41,14 +42,15 @@ export function createStyleParameters({
const label = documentRef.createElement('span');
label.className = 'param-label';
label.textContent = t(metadata.label);
const slider = documentRef.createElement('input');
slider.type = 'range';
slider.className = 'param-slider';
slider.setAttribute('aria-label', t(metadata.label));
slider.min = metadata.min;
slider.max = metadata.max;
slider.step = metadata.max <= 1 ? '0.01' : '0.1';
slider.value = readValue(name);
const slider = createSlider({
documentRef,
className: 'param-slider',
ariaLabel: t(metadata.label),
min: metadata.min,
max: metadata.max,
step: metadata.max <= 1 ? '0.01' : '0.1',
value: readValue(name),
});
const digits = metadata.max <= 1 ? 2 : 1;
const valueDisplay = documentRef.createElement('span');
valueDisplay.className = 'param-value';
-152
View File
@@ -532,110 +532,7 @@ html:not([lang='en']) .panel-collapse-btn {
.pp-slider {
flex: 1;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255, 255, 255, 0.08);
border-radius: 2px;
outline: none;
cursor: pointer;
min-width: 60px;
}
.pp-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.pp-slider::-moz-range-thumb {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--accent);
border: none;
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.pp-slider-value {
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.5px;
color: var(--accent);
min-width: 28px;
text-align: right;
flex-shrink: 0;
}
/* Quantitative companion sliders share Display / Sharpen's visible rail,
* circular thumb, glow, and value treatment while retaining a taller hit area. */
.gev-quantitative-slider {
width: 100%;
min-width: 0;
height: 18px;
margin: 0;
-webkit-appearance: none;
appearance: none;
background: transparent;
outline: none;
cursor: pointer;
}
.gev-quantitative-slider::-webkit-slider-runnable-track {
height: 3px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.08);
}
.gev-quantitative-slider::-webkit-slider-thumb {
width: 10px;
height: 10px;
margin-top: -3.5px;
border: 0;
border-radius: 50%;
-webkit-appearance: none;
appearance: none;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.gev-quantitative-slider::-moz-range-track,
.gev-quantitative-slider::-moz-range-progress {
height: 3px;
border: 0;
border-radius: 2px;
background: rgba(255, 255, 255, 0.08);
}
.gev-quantitative-slider::-moz-range-thumb {
width: 10px;
height: 10px;
border: 0;
border-radius: 50%;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.gev-quantitative-slider:focus-visible {
border-radius: 4px;
outline: 1px solid color-mix(in srgb, var(--accent) 80%, transparent);
outline-offset: 2px;
}
.gev-quantitative-slider:disabled {
opacity: 0.42;
cursor: not-allowed;
}
.gev-slider-value {
min-width: 28px;
color: var(--accent);
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.5px;
text-align: right;
flex-shrink: 0;
}
.pp-slider-mini-label {
@@ -1012,12 +909,6 @@ body.gev-geo-import-drag #cesiumContainer {
box-shadow: inset 0 0 0 4px #061014;
}
.pp-slider:focus-visible,
.param-slider:focus-visible {
outline: 2px solid var(--text-primary);
outline-offset: 4px;
}
#clean-view-toggle {
width: var(--pp-expanded-width);
}
@@ -1224,47 +1115,4 @@ html:not([lang='en']) .param-slider-row {
.param-slider {
flex: 1;
min-width: 0;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255, 255, 255, 0.08);
border-radius: 2px;
outline: none;
cursor: pointer;
}
.param-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
transition: box-shadow var(--transition-fast);
}
.param-slider::-webkit-slider-thumb:hover {
box-shadow: 0 0 12px var(--accent-glow);
}
.param-slider::-moz-range-thumb {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent);
border: none;
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.param-value {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.5px;
color: var(--accent);
min-width: 32px;
text-align: right;
flex-shrink: 0;
}
-10
View File
@@ -422,16 +422,6 @@ html:not([lang='en']) .recent-imagery-readout .ri-opacity-label {
}
.recent-imagery-readout .ri-opacity-value {
font-variant-numeric: tabular-nums;
color: var(--text-secondary);
}
.recent-imagery-readout .ri-opacity {
width: 100%;
min-width: 0;
margin: 0;
accent-color: var(--accent);
}
.recent-imagery-readout .ri-opacity:disabled {
opacity: 0.35;
}
.recent-imagery-readout .ri-swap {
width: 40px;
+70
View File
@@ -0,0 +1,70 @@
/* Shared ordinary slider surface; feature classes only own surrounding layout.
* Native range inputs retain keyboard, pointer, bounds and step behavior. */
.gev-quantitative-slider {
width: 100%;
min-width: 0;
height: 18px;
margin: 0;
padding: 0;
border: 0;
-webkit-appearance: none;
appearance: none;
background: transparent;
outline: none;
cursor: pointer;
}
.gev-quantitative-slider::-webkit-slider-runnable-track {
height: 3px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.08);
}
.gev-quantitative-slider::-webkit-slider-thumb {
width: 10px;
height: 10px;
margin-top: -3.5px;
border: 0;
border-radius: 50%;
-webkit-appearance: none;
appearance: none;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.gev-quantitative-slider::-moz-range-track,
.gev-quantitative-slider::-moz-range-progress {
height: 3px;
border: 0;
border-radius: 2px;
background: rgba(255, 255, 255, 0.08);
}
.gev-quantitative-slider::-moz-range-thumb {
width: 10px;
height: 10px;
border: 0;
border-radius: 50%;
background: var(--accent);
box-shadow: 0 0 6px var(--accent-glow);
cursor: pointer;
}
.gev-quantitative-slider:focus-visible {
border-radius: 4px;
outline: 1px solid color-mix(in srgb, var(--accent) 80%, transparent);
outline-offset: 2px;
}
.gev-quantitative-slider:disabled {
opacity: 0.42;
cursor: not-allowed;
}
.pp-slider-value,
.param-value,
.ri-opacity-value,
.rail-card-setting-range-value,
.gev-slider-value {
min-width: 28px;
color: var(--accent);
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.5px;
text-align: right;
flex-shrink: 0;
}
-13
View File
@@ -236,19 +236,6 @@ html:not([lang='en']) .sl-meta-row .sl-nearest-btn {
gap: 4px 10px;
}
.sl-range {
width: 100%;
min-width: 0;
margin: 0;
accent-color: var(--sl-green);
cursor: pointer;
}
.sl-range:focus-visible {
outline: 1px solid var(--accent);
outline-offset: 3px;
}
.sl-since-note {
grid-column: 2;
font-family: var(--font-mono);
-13
View File
@@ -362,22 +362,9 @@ html:not([lang='en']) .rail-card-setting {
font: 8px var(--font-mono);
white-space: nowrap;
}
.rail-card-setting-range {
width: 100%;
min-width: 0;
accent-color: var(--accent);
cursor: pointer;
}
.rail-card-setting-range:focus-visible {
outline: 2px solid var(--text-primary);
outline-offset: 3px;
}
.rail-card-setting-range-value {
flex: 0 0 4ch;
white-space: nowrap;
color: var(--text-primary);
font: 9px var(--font-mono);
text-align: right;
}
.rail-card-result {
display: grid;
+11 -11
View File
@@ -27,27 +27,27 @@
<output id="cyber-sonar-status" class="cyber-sonar-control" role="status"></output>
<div class="pp-slider-row cyber-sonar-control cyber-sonar-setting" id="cyber-sonar-rings-row">
<label class="pp-slider-mini-label" for="cyber-sonar-rings" data-i18n>Rings</label>
<input type="range" class="pp-slider" id="cyber-sonar-rings" min="3" max="12" step="1" value="8" aria-label="Sonar ring count" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="cyber-sonar-rings" min="3" max="12" step="1" value="8" aria-label="Sonar ring count" data-i18n-aria-label />
<span class="pp-slider-value" id="cyber-sonar-rings-value">8</span>
</div>
<div class="pp-slider-row cyber-sonar-control cyber-sonar-setting" id="cyber-sonar-range-row">
<label class="pp-slider-mini-label" for="cyber-sonar-range" data-i18n>Range</label>
<input type="range" class="pp-slider" id="cyber-sonar-range" min="60" max="120" step="1" value="100" aria-label="Sonar ring range" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="cyber-sonar-range" min="60" max="120" step="1" value="100" aria-label="Sonar ring range" data-i18n-aria-label />
<span class="pp-slider-value" id="cyber-sonar-range-value">100%</span>
</div>
<div class="pp-slider-row cyber-sonar-control cyber-sonar-setting" id="cyber-sonar-intensity-row">
<label class="pp-slider-mini-label" for="cyber-sonar-intensity" data-i18n>Power</label>
<input type="range" class="pp-slider" id="cyber-sonar-intensity" min="0" max="100" step="1" value="70" aria-label="Sonar intensity" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="cyber-sonar-intensity" min="0" max="100" step="1" value="70" aria-label="Sonar intensity" data-i18n-aria-label />
<span class="pp-slider-value" id="cyber-sonar-intensity-value">70%</span>
</div>
<div class="pp-slider-row cyber-sonar-control cyber-sonar-setting" id="cyber-sonar-opacity-row">
<label class="pp-slider-mini-label" for="cyber-sonar-opacity" data-i18n>Opacity</label>
<input type="range" class="pp-slider" id="cyber-sonar-opacity" min="35" max="100" step="1" value="84" aria-label="Cyber contact and label opacity" title="Minimum opacity for map dots, icons, models, brackets, and labels between sonar passes" data-i18n-aria-label data-i18n-title />
<input type="range" class="gev-quantitative-slider pp-slider" id="cyber-sonar-opacity" min="35" max="100" step="1" value="84" aria-label="Cyber contact and label opacity" title="Minimum opacity for map dots, icons, models, brackets, and labels between sonar passes" data-i18n-aria-label data-i18n-title />
<span class="pp-slider-value" id="cyber-sonar-opacity-value">84%</span>
</div>
<div class="pp-slider-row cyber-sonar-control cyber-sonar-setting" id="cyber-sonar-sector-row">
<label class="pp-slider-mini-label" for="cyber-sonar-sector" data-i18n>Sector</label>
<input type="range" class="pp-slider" id="cyber-sonar-sector" min="8" max="60" step="1" value="24" aria-label="Sonar sector width" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="cyber-sonar-sector" min="8" max="60" step="1" value="24" aria-label="Sonar sector width" data-i18n-aria-label />
<span class="pp-slider-value" id="cyber-sonar-sector-value">24°</span>
</div>
</div>
@@ -58,7 +58,7 @@
</button>
<div class="pp-slider-row detection-slider-row" id="detection-slider-row">
<label class="pp-slider-mini-label" for="detection-density-slider" data-i18n>Density</label>
<input type="range" class="pp-slider" id="detection-density-slider" min="0" max="100" step="25" value="50" aria-label="Detection label density" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="detection-density-slider" min="0" max="100" step="25" value="50" aria-label="Detection label density" data-i18n-aria-label />
<span class="pp-slider-value" id="detection-density-value">50%</span>
</div>
<div class="pp-slider-row detection-allocation-row" id="detection-allocation-row">
@@ -70,12 +70,12 @@
</div>
<div class="pp-slider-row detection-fade-row" id="detection-fade-row">
<label class="pp-slider-mini-label" for="detection-fade-slider" data-i18n>Fade</label>
<input type="range" class="pp-slider" id="detection-fade-slider" min="0" max="40" step="1" value="7" aria-label="Detection fade distance" title="World-overlay fade distance outside the keyhole as a percentage of its radius" data-i18n-aria-label data-i18n-title />
<input type="range" class="gev-quantitative-slider pp-slider" id="detection-fade-slider" min="0" max="40" step="1" value="7" aria-label="Detection fade distance" title="World-overlay fade distance outside the keyhole as a percentage of its radius" data-i18n-aria-label data-i18n-title />
<span class="pp-slider-value" id="detection-fade-value">7%</span>
</div>
<div class="pp-slider-row detection-opacity-row" id="detection-opacity-row">
<label class="pp-slider-mini-label" for="detection-opacity-slider" data-i18n>Outside</label>
<input type="range" class="pp-slider" id="detection-opacity-slider" min="0" max="100" step="1" value="1" aria-label="Detection opacity outside the keyhole" title="World-overlay label and card opacity beyond the fade distance" data-i18n-aria-label data-i18n-title />
<input type="range" class="gev-quantitative-slider pp-slider" id="detection-opacity-slider" min="0" max="100" step="1" value="1" aria-label="Detection opacity outside the keyhole" title="World-overlay label and card opacity beyond the fade distance" data-i18n-aria-label data-i18n-title />
<span class="pp-slider-value" id="detection-opacity-value">1%</span>
</div>
</div>
@@ -117,7 +117,7 @@
mirrors SCOPE_FEATHER_RATIO_DEFAULT in src/scopeMask.js. Feather
softens the black mask edge; label fading is the separate Fade
slider. -->
<input type="range" class="pp-slider" id="scope-feather-slider" min="0" max="100" value="11" aria-label="Scope edge feather" title="Scope edge feather as a percentage of the keyhole radius" data-i18n-aria-label data-i18n-title />
<input type="range" class="gev-quantitative-slider pp-slider" id="scope-feather-slider" min="0" max="100" value="11" aria-label="Scope edge feather" title="Scope edge feather as a percentage of the keyhole radius" data-i18n-aria-label data-i18n-title />
<span class="pp-slider-value" id="scope-feather-value">11%</span>
</div>
</div>
@@ -172,7 +172,7 @@
<span class="pp-label" data-i18n>Bloom</span>
</button>
<div class="pp-slider-row" id="bloom-slider-row">
<input type="range" class="pp-slider" id="bloom-intensity-slider" min="0" max="200" value="0" aria-label="Bloom intensity" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="bloom-intensity-slider" min="0" max="200" value="0" aria-label="Bloom intensity" data-i18n-aria-label />
<span class="pp-slider-value" id="bloom-intensity-value">0%</span>
</div>
</div>
@@ -182,7 +182,7 @@
<span class="pp-label" data-i18n>Sharpen</span>
</button>
<div class="pp-slider-row" id="sharpen-slider-row">
<input type="range" class="pp-slider" id="sharpen-intensity-slider" min="0" max="100" value="49" aria-label="Sharpen intensity" data-i18n-aria-label />
<input type="range" class="gev-quantitative-slider pp-slider" id="sharpen-intensity-slider" min="0" max="100" value="49" aria-label="Sharpen intensity" data-i18n-aria-label />
<span class="pp-slider-value" id="sharpen-intensity-value">49%</span>
</div>
</div>
+1 -1
View File
@@ -126,7 +126,7 @@
</div>
<div id="sl-since-row" class="sl-since">
<label class="cctv-summary-label" for="sl-since" data-i18n>SINCE</label>
<input id="sl-since" class="sl-range" type="range" min="0" max="8" step="1" value="0" aria-valuetext="ANY DATE" aria-describedby="sl-since-label sl-since-note" />
<input id="sl-since" class="gev-quantitative-slider sl-range" type="range" min="0" max="8" step="1" value="0" aria-valuetext="ANY DATE" aria-describedby="sl-since-label sl-since-note" />
<output id="sl-since-label" class="sl-since-label" for="sl-since" data-i18n>ANY DATE</output>
<small id="sl-since-note" class="sl-since-note" hidden></small>
</div>
+1 -1
View File
@@ -176,7 +176,7 @@ test('parameter rows preserve labels, bounds, precision and initial values', ()
assert.equal(label.textContent, '<Amount>');
assert.equal(slider.attributes.get('aria-label'), '<Amount>');
assert.equal(slider.type, 'range');
assert.equal(slider.className, 'param-slider');
assert.equal(slider.className, 'gev-quantitative-slider param-slider');
assert.equal(slider.min, 0);
assert.equal(slider.max, 1);
assert.equal(slider.step, '0.01');
+1
View File
@@ -1,5 +1,6 @@
/* Preserve component and responsive rule order in one stylesheet entry. */
@import './src/ui/styles/foundation.css';
@import './src/ui/styles/slider.css';
@import './src/ui/styles/controls.css';
@import './src/ui/styles/location.css';
@import './src/ui/styles/status.css';