Skip to content

Commit c6c3209

Browse files
vgeorgekylebarron
andauthored
feat: Reinstate tooltip (#736)
Contributes to #586. @kylebarron this just restore the original tooltip files, re-enabling the feature that was removed in #636. I think the tooltip need improvements on the layout to break lines in a similar way the sidepanel does. But we can address it in separate if we want to restore the feature right away. --------- Co-authored-by: Kyle Barron <[email protected]>
1 parent ae81363 commit c6c3209

File tree

5 files changed

+110
-2
lines changed

5 files changed

+110
-2
lines changed

lonboard/_map.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,18 @@ def on_click(self, callback: Callable, *, remove: bool = False) -> None:
190190
"""One or more `Layer` objects to display on this map.
191191
"""
192192

193-
show_tooltip = t.Bool(default_value=True).tag(sync=True)
193+
show_tooltip = t.Bool(default_value=False).tag(sync=True)
194194
"""
195195
Whether to render a tooltip on hover on the map.
196196
197+
- Type: `bool`
198+
- Default: `False`
199+
"""
200+
201+
show_side_panel = t.Bool(default_value=True).tag(sync=True)
202+
"""
203+
Whether to render a side panel upon clicking on elements.
204+
197205
- Type: `bool`
198206
- Default: `True`
199207
"""

lonboard/types/map.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ class MapKwargs(TypedDict, total=False):
2020
parameters: dict[str, Any]
2121
picking_radius: int
2222
show_tooltip: bool
23+
show_side_panel: bool
2324
use_device_pixels: int | float | bool
2425
view_state: dict[str, Any]

src/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { NextUIProvider } from "@nextui-org/react";
2323
import Toolbar from "./toolbar.js";
2424
import throttle from "lodash.throttle";
2525
import SidePanel from "./sidepanel/index";
26+
import { getTooltip } from "./tooltip/index.js";
2627

2728
await initParquetWasm();
2829

@@ -98,6 +99,7 @@ function App() {
9899
const [mapStyle] = useModelState<string>("basemap_style");
99100
const [mapHeight] = useModelState<number>("_height");
100101
const [showTooltip] = useModelState<boolean>("show_tooltip");
102+
const [showSidePanel] = useModelState<boolean>("show_side_panel");
101103
const [pickingRadius] = useModelState<number>("picking_radius");
102104
const [useDevicePixels] = useModelState<number | boolean>(
103105
"use_device_pixels",
@@ -221,7 +223,7 @@ function App() {
221223
>
222224
<Toolbar />
223225

224-
{showTooltip && highlightedFeature && (
226+
{showSidePanel && highlightedFeature && (
225227
<SidePanel
226228
info={highlightedFeature}
227229
onClose={() => actorRef.send({ type: "Close side panel" })}
@@ -243,6 +245,7 @@ function App() {
243245
? layers.concat(bboxSelectPolygonLayer)
244246
: layers
245247
}
248+
getTooltip={(showTooltip && getTooltip) || undefined}
246249
getCursor={() => (isDrawingBBoxSelection ? "crosshair" : "grab")}
247250
pickingRadius={pickingRadius}
248251
onClick={onMapClickHandler}

src/tooltip/index.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Set fonts based on jupyter defaults */
2+
.lonboard-tooltip {
3+
font-family: var(--jp-ui-font-family);
4+
font-size: var(--jp-ui-font-size1);
5+
}
6+
7+
/* Remove spaces between table cells */
8+
.lonboard-tooltip table {
9+
border-collapse: collapse;
10+
}
11+
12+
/* Alternate row colors */
13+
.lonboard-tooltip table tr:nth-child(odd) {
14+
background-color: white;
15+
}
16+
17+
.lonboard-tooltip table tr:nth-child(even) {
18+
background-color: rgb(241, 241, 241);
19+
}
20+
21+
/* Define table cell borders and padding */
22+
.lonboard-tooltip td {
23+
border: 1px solid rgb(204, 204, 204);
24+
padding: 5px;
25+
}
26+
27+
/* Make the first column bold */
28+
.lonboard-tooltip td:first-child {
29+
font-weight: 450;
30+
}

src/tooltip/index.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { TooltipContent } from "@deck.gl/core/dist/lib/tooltip";
2+
import type { GeoArrowPickingInfo } from "@geoarrow/deck.gl-layers";
3+
4+
import "./index.css";
5+
6+
const rowIndexSymbol = Symbol.for("rowIndex");
7+
8+
function toHtmlTable(featureProperties: Record<string, unknown>): string {
9+
return `<table>
10+
<tbody>
11+
${Object.keys(featureProperties)
12+
.map((key) => {
13+
const value = featureProperties[key];
14+
return `<tr>
15+
<td>${key}</td>
16+
<td>${value}</td>
17+
</tr>`;
18+
})
19+
.join("")}
20+
</tbody>
21+
</table>`;
22+
}
23+
24+
export function getTooltip({ object }: GeoArrowPickingInfo): TooltipContent {
25+
if (object) {
26+
// If the row index is -1 or undefined, return
27+
//
28+
// Note that this is a private API, but this appears to be the only way to
29+
// get this information
30+
//
31+
// Without this block, we end up showing a tooltip even when not hovering
32+
// over a point
33+
if (
34+
object[rowIndexSymbol] === null ||
35+
object[rowIndexSymbol] === undefined ||
36+
(object[rowIndexSymbol] && object[rowIndexSymbol] < 0)
37+
) {
38+
return null;
39+
}
40+
41+
const jsonObj = object.toJSON();
42+
43+
if (!jsonObj) {
44+
return null;
45+
}
46+
47+
delete jsonObj["geometry"];
48+
49+
if (Object.keys(jsonObj).length === 0) {
50+
return null;
51+
}
52+
53+
return {
54+
className: "lonboard-tooltip",
55+
html: toHtmlTable(jsonObj),
56+
style: {
57+
backgroundColor: "#fff",
58+
boxShadow: "0 0 15px rgba(0, 0, 0, 0.1)",
59+
color: "#000",
60+
padding: "6px",
61+
},
62+
};
63+
}
64+
65+
return null;
66+
}

0 commit comments

Comments
 (0)