web: hide legend by default (#582)

* web: hide legend my default

* web: run rufo
This commit is contained in:
l5y
2025-12-31 12:42:53 +01:00
committed by GitHub
parent e61e701240
commit 6c711f80b4
6 changed files with 85 additions and 5 deletions

View File

@@ -0,0 +1,41 @@
/*
* Copyright © 2025-26 l5yth & contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import test from 'node:test';
import assert from 'node:assert/strict';
import { resolveLegendVisibility } from '../map-legend-visibility.js';
test('resolveLegendVisibility hides when a default collapse is requested', () => {
assert.equal(resolveLegendVisibility({ defaultCollapsed: true, mediaQueryMatches: false }), false);
assert.equal(resolveLegendVisibility({ defaultCollapsed: true, mediaQueryMatches: true }), false);
});
test('resolveLegendVisibility hides for dashboard and map views', () => {
assert.equal(
resolveLegendVisibility({ defaultCollapsed: false, mediaQueryMatches: false, viewMode: 'dashboard' }),
false
);
assert.equal(
resolveLegendVisibility({ defaultCollapsed: false, mediaQueryMatches: false, viewMode: 'map' }),
false
);
});
test('resolveLegendVisibility follows the media query when not forced', () => {
assert.equal(resolveLegendVisibility({ defaultCollapsed: false, mediaQueryMatches: false }), true);
assert.equal(resolveLegendVisibility({ defaultCollapsed: false, mediaQueryMatches: true }), false);
});

View File

@@ -18,6 +18,7 @@ import { computeBoundingBox, computeBoundsForPoints, haversineDistanceKm } from
import { createMapAutoFitController } from './map-auto-fit-controller.js'; import { createMapAutoFitController } from './map-auto-fit-controller.js';
import { resolveAutoFitBoundsConfig } from './map-auto-fit-settings.js'; import { resolveAutoFitBoundsConfig } from './map-auto-fit-settings.js';
import { attachNodeInfoRefreshToMarker, overlayToPopupNode } from './map-marker-node-info.js'; import { attachNodeInfoRefreshToMarker, overlayToPopupNode } from './map-marker-node-info.js';
import { resolveLegendVisibility } from './map-legend-visibility.js';
import { createMapFocusHandler, DEFAULT_NODE_FOCUS_ZOOM } from './nodes-map-focus.js'; import { createMapFocusHandler, DEFAULT_NODE_FOCUS_ZOOM } from './nodes-map-focus.js';
import { enhanceCoordinateCell } from './nodes-coordinate-links.js'; import { enhanceCoordinateCell } from './nodes-coordinate-links.js';
import { createShortInfoOverlayStack } from './short-info-overlay-manager.js'; import { createShortInfoOverlayStack } from './short-info-overlay-manager.js';
@@ -116,6 +117,7 @@ export function initializeApp(config) {
: false; : false;
const isDashboardView = bodyClassList ? bodyClassList.contains('view-dashboard') : false; const isDashboardView = bodyClassList ? bodyClassList.contains('view-dashboard') : false;
const isChatView = bodyClassList ? bodyClassList.contains('view-chat') : false; const isChatView = bodyClassList ? bodyClassList.contains('view-chat') : false;
const isMapView = bodyClassList ? bodyClassList.contains('view-map') : false;
const mapZoomOverride = Number.isFinite(config.mapZoom) ? Number(config.mapZoom) : null; const mapZoomOverride = Number.isFinite(config.mapZoom) ? Number(config.mapZoom) : null;
/** /**
* Column sorter configuration for the node table. * Column sorter configuration for the node table.
@@ -435,6 +437,7 @@ export function initializeApp(config) {
const mapFullscreenToggle = document.getElementById('mapFullscreenToggle'); const mapFullscreenToggle = document.getElementById('mapFullscreenToggle');
const fullscreenContainer = mapPanel || mapContainer; const fullscreenContainer = mapPanel || mapContainer;
const isFederationView = bodyClassList ? bodyClassList.contains('view-federation') : false; const isFederationView = bodyClassList ? bodyClassList.contains('view-federation') : false;
const legendDefaultCollapsed = mapPanel ? mapPanel.dataset.legendCollapsed === 'true' : false;
let mapStatusEl = null; let mapStatusEl = null;
let map = null; let map = null;
let mapCenterLatLng = null; let mapCenterLatLng = null;
@@ -1526,8 +1529,14 @@ export function initializeApp(config) {
legendToggleControl.addTo(map); legendToggleControl.addTo(map);
const legendMediaQuery = window.matchMedia('(max-width: 1024px)'); const legendMediaQuery = window.matchMedia('(max-width: 1024px)');
setLegendVisibility(!legendMediaQuery.matches); const initialLegendVisible = resolveLegendVisibility({
defaultCollapsed: legendDefaultCollapsed,
mediaQueryMatches: legendMediaQuery.matches,
viewMode: isDashboardView ? 'dashboard' : (isMapView ? 'map' : undefined)
});
setLegendVisibility(initialLegendVisible);
legendMediaQuery.addEventListener('change', event => { legendMediaQuery.addEventListener('change', event => {
if (legendDefaultCollapsed || isDashboardView || isMapView) return;
setLegendVisibility(!event.matches); setLegendVisibility(!event.matches);
}); });
} else if (mapContainer && !hasLeaflet) { } else if (mapContainer && !hasLeaflet) {

View File

@@ -0,0 +1,26 @@
/*
* Copyright © 2025-26 l5yth & contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Resolve the initial visibility of the map legend.
*
* @param {{ defaultCollapsed: boolean, mediaQueryMatches: boolean, viewMode?: string }} options
* @returns {boolean} True when the legend should be visible.
*/
export function resolveLegendVisibility({ defaultCollapsed, mediaQueryMatches, viewMode }) {
if (defaultCollapsed || viewMode === 'dashboard' || viewMode === 'map') return false;
return !mediaQueryMatches;
}

View File

@@ -17,7 +17,7 @@
<% unless private_mode %> <% unless private_mode %>
<%= erb :"shared/_chat_panel", locals: { full_screen: false } %> <%= erb :"shared/_chat_panel", locals: { full_screen: false } %>
<% end %> <% end %>
<%= erb :"shared/_map_panel", locals: { full_screen: false } %> <%= erb :"shared/_map_panel", locals: { full_screen: false, legend_collapsed: true } %>
</div> </div>
<%= erb :"shared/_nodes_table", locals: { full_screen: false } %> <%= erb :"shared/_nodes_table", locals: { full_screen: false } %>

View File

@@ -14,5 +14,5 @@
limitations under the License. limitations under the License.
--> -->
<section class="full-screen-section full-screen-section--map"> <section class="full-screen-section full-screen-section--map">
<%= erb :"shared/_map_panel", locals: { full_screen: true } %> <%= erb :"shared/_map_panel", locals: { full_screen: true, legend_collapsed: true } %>
</section> </section>

View File

@@ -14,8 +14,12 @@
limitations under the License. limitations under the License.
--> -->
<% map_classes = ["map-panel"] <% map_classes = ["map-panel"]
map_classes << "map-panel--full" if defined?(full_screen) && full_screen %> map_classes << "map-panel--full" if defined?(full_screen) && full_screen
<div class="<%= map_classes.join(" ") %>" id="mapPanel"> data_attrs = []
if defined?(legend_collapsed)
data_attrs << "data-legend-collapsed=\\" #{legend_collapsed ? 'true' : 'false'}\\""
end %>
<div class="<%= map_classes.join(" ") %>" id="mapPanel" <%= data_attrs.join(" ") %>>
<div id="map" role="region" aria-label="Nodes map"></div> <div id="map" role="region" aria-label="Nodes map"></div>
<div class="map-toolbar" role="group" aria-label="Map view controls"> <div class="map-toolbar" role="group" aria-label="Map view controls">
<button id="mapFullscreenToggle" type="button" aria-pressed="false" aria-label="Enter full screen map view"> <button id="mapFullscreenToggle" type="button" aria-pressed="false" aria-label="Enter full screen map view">