mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
feat(street-level): one colour per imagery source
As more sources arrive, each one reads the same everywhere it appears: its PROVIDERS chip, coverage lines, overview points, image cones and a single legend swatch. The palette lives in one place, PROVIDER_COLORS in src/layers/streetLevel/policy.js: Mapillary green (#05cb63), Panoramax purple, Google Street View blue. Mapillary drops its age dimming and magenta panoramas: lines and overview points are Mapillary green, cones are green too and 360° images keep their ring shape; the 360°/FLAT filter still separates them, and the selected sequence stays GEV cyan. The provider contract loses `legend`: `colors.coverage` is the source's one colour, and the core composes the legend as one swatch per active source (its name, its colour) followed by Selected. The chip group takes an optional per-chip colour as a `--chip-color` CSS variable, written only when it changes; Street Level chips show it as a swatch dot and, while on, as the chip's border, text and a faint fill. The feature gate checks the legend has one swatch per source plus Selected and that the Mapillary chip carries #05cb63. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d5da45eacb
commit
0f2cac2ca2
21 files changed
+188
-99
No files matched your search
@@ -28,6 +28,17 @@ export function syncChipGroup(container, chips = [], { before = null } = {}) {
|
||||
`data-toggle-chip chip-${state}${chip.active ? ' active' : ''}`,
|
||||
);
|
||||
set(button, 'textContent', chip.label);
|
||||
// Optional per-chip colour (a Street Level source); CSS decides its use.
|
||||
const color = chip.color || '';
|
||||
if ((button.dataset.chipColor || '') !== color) {
|
||||
if (color) {
|
||||
button.style.setProperty('--chip-color', color);
|
||||
button.dataset.chipColor = color;
|
||||
} else {
|
||||
button.style.removeProperty('--chip-color');
|
||||
delete button.dataset.chipColor;
|
||||
}
|
||||
}
|
||||
set(button, 'title', chip.title || '');
|
||||
set(button, 'disabled', Boolean(chip.disabled));
|
||||
attribute(button, 'aria-pressed', String(Boolean(chip.active)));
|
||||
|
||||
@@ -31,3 +31,24 @@ test('keyed chips retain focus, reflect state, reorder and remove without redund
|
||||
syncChipGroup(f.container, []);
|
||||
assert.deepEqual(f.container.children, [legend]);
|
||||
});
|
||||
|
||||
test('a chip colour is set once, changed, and cleared through a CSS variable', () => {
|
||||
const f = railFixture(() => {});
|
||||
const calls = [];
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M' }]);
|
||||
const chip = f.container.children[0];
|
||||
chip.style.setProperty = (name, value) => calls.push(['set', name, value]);
|
||||
chip.style.removeProperty = (name) => calls.push(['remove', name]);
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M' }]);
|
||||
assert.deepEqual(calls, [], 'a chip without a colour never touches style');
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M', color: '#05cb63' }]);
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M', color: '#05cb63' }]);
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M', color: '#a66bff' }]);
|
||||
syncChipGroup(f.container, [{ id: 'm', label: 'M' }]);
|
||||
assert.deepEqual(calls, [
|
||||
['set', '--chip-color', '#05cb63'],
|
||||
['set', '--chip-color', '#a66bff'],
|
||||
['remove', '--chip-color'],
|
||||
]);
|
||||
assert.equal(chip.dataset.chipColor, undefined);
|
||||
});
|
||||
@@ -91,6 +91,7 @@ function presentProviders(state) {
|
||||
return {
|
||||
id: provider.id,
|
||||
label: provider.label,
|
||||
color: provider.color || null,
|
||||
title,
|
||||
active: on,
|
||||
disabled: false,
|
||||
|
||||
@@ -18,7 +18,7 @@ const provider = (overrides = {}) => ({
|
||||
count: 0,
|
||||
hint: '',
|
||||
error: null,
|
||||
legend: [],
|
||||
color: '#05cb63',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -30,9 +30,7 @@ function snapshot(overrides = {}) {
|
||||
providers: [provider()],
|
||||
coverage: { loading: false, count: 0, hint: '', error: null },
|
||||
legend: [
|
||||
{ key: 'mapillary:recent', label: 'Recent (≤2 yr)', color: '#05cb63' },
|
||||
{ key: 'mapillary:older', label: 'Older', color: '#2e7d5b' },
|
||||
{ key: 'mapillary:pano', label: '360°', color: '#ff4fd8' },
|
||||
{ key: 'mapillary', label: 'Mapillary', color: '#05cb63' },
|
||||
{ key: 'selected', label: 'Selected', color: '#00d4ff' },
|
||||
],
|
||||
sequence: { providerId: null, selectedId: null, images: 0, loading: false },
|
||||
@@ -239,7 +237,25 @@ test('legend passes through in the layer’s order', () => {
|
||||
const view = presentStreetLevelPanel(snapshot());
|
||||
assert.deepEqual(
|
||||
view.legend.map((entry) => entry.key),
|
||||
['mapillary:recent', 'mapillary:older', 'mapillary:pano', 'selected'],
|
||||
['mapillary', 'selected'],
|
||||
);
|
||||
});
|
||||
|
||||
test('each provider chip carries its source colour', () => {
|
||||
const view = presentStreetLevelPanel(
|
||||
snapshot({
|
||||
providers: [
|
||||
provider(),
|
||||
provider({ id: 'panoramax', label: 'PANORAMAX', color: '#a66bff' }),
|
||||
],
|
||||
}),
|
||||
);
|
||||
assert.deepEqual(
|
||||
view.providers.map((chip) => [chip.id, chip.color]),
|
||||
[
|
||||
['mapillary', '#05cb63'],
|
||||
['panoramax', '#a66bff'],
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -139,6 +139,38 @@ button.sl-status:focus-visible {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* One colour per source: a swatch dot, and the whole chip in that colour
|
||||
while the source is on. `--chip-color` comes from the provider. */
|
||||
.sl-chips .data-toggle-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.sl-chips .data-toggle-chip::before {
|
||||
content: '';
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--chip-color, currentColor);
|
||||
opacity: 0.45;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.sl-chips .data-toggle-chip.active {
|
||||
color: var(--chip-color, var(--accent));
|
||||
border-color: var(--chip-color, var(--accent));
|
||||
background: color-mix(
|
||||
in srgb,
|
||||
var(--chip-color, var(--accent)) 14%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
.sl-chips .data-toggle-chip.active::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sl-chips .data-toggle-chip.chip-error {
|
||||
color: #ffb300;
|
||||
border-color: rgba(255, 179, 0, 0.55);
|
||||
|
||||
Reference in new issue
Block a user