Skip to content

Commit 653885e

Browse files
committed
update pop card styling @cursor
1 parent d0d6762 commit 653885e

2 files changed

Lines changed: 114 additions & 19 deletions

File tree

frontend/src/index.html

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,57 @@
184184
background: white;
185185
}
186186

187+
/* Properties scroll container for limited display */
188+
.properties-scroll-container {
189+
max-height: 200px;
190+
overflow-y: auto;
191+
border: 1px solid #e8eaed;
192+
border-radius: 4px;
193+
margin: 8px 0;
194+
}
195+
196+
.properties-scroll-container::-webkit-scrollbar {
197+
width: 6px;
198+
}
199+
200+
.properties-scroll-container::-webkit-scrollbar-track {
201+
background: #f8f9fa;
202+
border-radius: 3px;
203+
}
204+
205+
.properties-scroll-container::-webkit-scrollbar-thumb {
206+
background: #dadce0;
207+
border-radius: 3px;
208+
}
209+
210+
.properties-scroll-container::-webkit-scrollbar-thumb:hover {
211+
background: #bdc1c6;
212+
}
213+
214+
/* Popup hint styling */
215+
.popup-hint {
216+
margin-top: 12px;
217+
padding: 8px 12px;
218+
background: rgba(26, 115, 232, 0.05);
219+
border: 1px solid rgba(26, 115, 232, 0.2);
220+
border-radius: 4px;
221+
font-size: 11px;
222+
color: #5f6368;
223+
text-align: center;
224+
}
225+
226+
.popup-hint kbd {
227+
background: #f8f9fa;
228+
border: 1px solid #dadce0;
229+
border-radius: 3px;
230+
padding: 2px 6px;
231+
font-family: 'Roboto Mono', monospace;
232+
font-size: 10px;
233+
font-weight: 600;
234+
color: #3c4043;
235+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
236+
}
237+
187238
/* Map Information Panel - Bottom Right Layout */
188239
.map-info-panel {
189240
position: fixed;

frontend/src/js/hazard-layer.js

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,45 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
9292
},
9393
});
9494

95+
// Global variable to track current popup for ESC key functionality
96+
let currentPopup = null;
97+
98+
// Add ESC key event listener for closing popups
99+
document.addEventListener("keydown", function (event) {
100+
if (event.key === "Escape" && currentPopup) {
101+
currentPopup.remove();
102+
currentPopup = null;
103+
}
104+
});
105+
95106
// Add click interaction for Global Hazard Points features
96107
map.on("click", "hazard-pt", (e) => {
108+
// Close existing popup if any
109+
if (currentPopup) {
110+
currentPopup.remove();
111+
currentPopup = null;
112+
}
113+
97114
const properties = e.features[0].properties;
98115
const featureId = properties.id || Date.now();
99116

100-
// Build table rows for feature properties
101-
let rows = "";
102-
for (const [key, value] of Object.entries(properties)) {
103-
if (key !== "id" && key !== "fid") {
104-
rows += `<tr><td>${key}</td><td>${value}</td></tr>`;
105-
}
106-
}
117+
// Build limited properties table (first 7 items)
118+
const propertyEntries = Object.entries(properties).filter(
119+
([key]) => key !== "id" && key !== "fid"
120+
);
121+
const visibleProperties = propertyEntries.slice(0, 7);
122+
const hiddenProperties = propertyEntries.slice(7);
123+
124+
let visibleRows = "";
125+
let hiddenRows = "";
126+
127+
visibleProperties.forEach(([key, value]) => {
128+
visibleRows += `<tr><td>${key}</td><td>${value}</td></tr>`;
129+
});
130+
131+
hiddenProperties.forEach(([key, value]) => {
132+
hiddenRows += `<tr><td>${key}</td><td>${value}</td></tr>`;
133+
});
107134

108135
const canvasId = `rate-chart-${featureId}`;
109136
const downloadId = `download-${featureId}`;
@@ -114,15 +141,21 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
114141
<canvas id="${canvasId}" width="400" height="160"></canvas>
115142
<button class="download-btn" id="${downloadId}">Download CSV</button>
116143
<details class="properties-details">
117-
<summary>Properties</summary>
144+
<summary>Properties (${propertyEntries.length} total)</summary>
118145
<div class="properties-content">
119-
<table class="popup-table">${rows}</table>
146+
<div class="properties-scroll-container">
147+
<table class="popup-table">
148+
${visibleRows}
149+
${hiddenRows}
150+
</table>
151+
</div>
120152
</div>
121153
</details>
154+
<div class="popup-hint">💡 Press <kbd>ESC</kbd> to close this popup</div>
122155
</div>`;
123156

124157
// Create popup with improved configuration to prevent jumping
125-
const popup = new maplibregl.Popup({
158+
currentPopup = new maplibregl.Popup({
126159
maxWidth: "480px",
127160
className: "chart-popup",
128161
closeOnClick: false,
@@ -134,22 +167,27 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
134167
.setHTML(html)
135168
.addTo(map);
136169

170+
// Handle popup close event to reset currentPopup
171+
currentPopup.on("close", () => {
172+
currentPopup = null;
173+
});
174+
137175
// Adjust popup position if it goes off screen
138176
setTimeout(() => {
139-
const popupElement = popup.getElement();
177+
const popupElement = currentPopup.getElement();
140178
if (popupElement) {
141179
const rect = popupElement.getBoundingClientRect();
142180
const mapContainer = map.getContainer().getBoundingClientRect();
143181

144182
// Check if popup extends beyond screen boundaries
145183
if (rect.right > mapContainer.right) {
146-
popup.setOffset([-rect.width / 2, -10]);
184+
currentPopup.setOffset([-rect.width / 2, -10]);
147185
}
148186
if (rect.left < mapContainer.left) {
149-
popup.setOffset([rect.width / 2, -10]);
187+
currentPopup.setOffset([rect.width / 2, -10]);
150188
}
151189
if (rect.top < mapContainer.top) {
152-
popup.setOffset([0, 10]);
190+
currentPopup.setOffset([0, 10]);
153191
}
154192
}
155193
}, 50);
@@ -292,30 +330,36 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
292330

293331
// Handle properties details expansion to prevent popup jumping
294332
setTimeout(() => {
295-
const detailsElement = popup
333+
const detailsElement = currentPopup
296334
.getElement()
297335
.querySelector(".properties-details");
298336
if (detailsElement) {
299337
detailsElement.addEventListener("toggle", (e) => {
300338
// Small delay to allow content to render
301339
setTimeout(() => {
302-
const popupElement = popup.getElement();
340+
const popupElement = currentPopup.getElement();
303341
const rect = popupElement.getBoundingClientRect();
304342
const mapContainer = map.getContainer().getBoundingClientRect();
305343

306344
// Adjust popup position if it goes beyond screen after expansion
307345
if (rect.bottom > mapContainer.bottom) {
308346
// Move popup up if it goes below screen
309347
const newOffset = [0, -(rect.height + 20)];
310-
popup.setOffset(newOffset);
348+
currentPopup.setOffset(newOffset);
311349
}
312350

313351
// Ensure popup doesn't go off the sides
314352
if (rect.right > mapContainer.right) {
315-
popup.setOffset([-rect.width / 2, popup.getOffset()[1]]);
353+
currentPopup.setOffset([
354+
-rect.width / 2,
355+
currentPopup.getOffset()[1],
356+
]);
316357
}
317358
if (rect.left < mapContainer.left) {
318-
popup.setOffset([rect.width / 2, popup.getOffset()[1]]);
359+
currentPopup.setOffset([
360+
rect.width / 2,
361+
currentPopup.getOffset()[1],
362+
]);
319363
}
320364
}, 50);
321365
});

0 commit comments

Comments
 (0)