From 064db68c56c8bf093fce262a4835506400b87b37 Mon Sep 17 00:00:00 2001 From: Kevin Fabre Date: Thu, 16 Nov 2023 16:41:09 +0100 Subject: [PATCH] fix(POI Map): Update popup style - When map width is below 500px, force the popup to behave as a sidebar popup taking up the full width - Add a close icon for modal style popup --- .../stories/Poi/PoiMap.stories.tsx | 8 +- .../stories/Poi/sources.ts | 14 ++-- .../src/components/MapPoi/Map.ts | 6 +- .../src/components/MapPoi/MapRender.svelte | 78 +++++++++++++++++-- .../src/components/MapPoi/constants.ts | 7 +- 5 files changed, 94 insertions(+), 19 deletions(-) diff --git a/packages/visualizations-react/stories/Poi/PoiMap.stories.tsx b/packages/visualizations-react/stories/Poi/PoiMap.stories.tsx index 6bf9a2fe..ba88e575 100644 --- a/packages/visualizations-react/stories/Poi/PoiMap.stories.tsx +++ b/packages/visualizations-react/stories/Poi/PoiMap.stories.tsx @@ -21,8 +21,8 @@ const layer1: Layer = { display: PopupDisplayTypes.Tooltip, getContent: async (_, properties) => { await timeout(500); - const { key } = properties as { key: string }; - return Promise.resolve(`

${key}

`); + const { key, description } = properties as Record; + return Promise.resolve(`

${key}

${description}
`); }, getLoadingContent: () => 'Loading...', }, @@ -107,7 +107,7 @@ const meta: ComponentMeta = { export default meta; -const Template: ComponentStory = args => ( +const Template: ComponentStory = (args) => (
= Template.bind({}); const PoiMapMinMaxZoomsArgs = { data: { value: { layers: [{ ...layer1, colorMatch: citiesColorMatch }, layer2], sources } }, - options: { + options: { ...options, legend, minZoom: 3, diff --git a/packages/visualizations-react/stories/Poi/sources.ts b/packages/visualizations-react/stories/Poi/sources.ts index 5b2b723b..265c0191 100644 --- a/packages/visualizations-react/stories/Poi/sources.ts +++ b/packages/visualizations-react/stories/Poi/sources.ts @@ -15,7 +15,8 @@ const sources : PoiMapData["sources"] = { coordinates: [2.357573,48.837904], }, properties: { - key: 'Paris' + key: 'Paris', + description: 'Officia deserunt commodo enim ea ad veniam enim consectetur aliquip adipisicing duis. Exercitation aute velit pariatur est et ea qui veniam ad duis quis ad aliquip. Ipsum exercitation dolor tempor deserunt sunt amet laborum tempor excepteur est sunt ea quis.' }, }, { @@ -26,7 +27,8 @@ const sources : PoiMapData["sources"] = { coordinates: [-0.563328,44.838245], }, properties: { - key: 'Bordeaux' + key: 'Bordeaux', + description: 'Pariatur duis mollit sit id ullamco ea non ad dolore voluptate nostrud deserunt fugiat proident. Sunt dolor qui consectetur exercitation mollit proident Lorem laborum cillum sit Lorem id eiusmod. Lorem culpa tempor aliqua aliquip reprehenderit. Aute officia reprehenderit aute pariatur incididunt nostrud exercitation voluptate id est ex. Qui eiusmod est enim est ipsum elit laboris.' }, }, { @@ -37,7 +39,8 @@ const sources : PoiMapData["sources"] = { coordinates: [-1.552924,47.214847], }, properties: { - key: 'Nantes' + key: 'Nantes', + description: "Irure incididunt deserunt officia eiusmod occaecat duis nostrud sint excepteur. Id non voluptate non proident sunt sit nisi eiusmod sit excepteur duis cillum adipisicing. Nostrud officia ad tempor quis commodo aute elit tempor reprehenderit esse est aute fugiat reprehenderit. Aliquip eu occaecat Lorem cupidatat labore consequat. Culpa commodo sunt proident exercitation. Enim voluptate minim veniam enim nulla aute dolor magna est elit aliqua. Ex occaecat fugiat laboris do do dolor nostrud cupidatat." }, }, { @@ -48,7 +51,8 @@ const sources : PoiMapData["sources"] = { coordinates: [5.360529,43.303114], }, properties: { - key: 'Marseille' + key: 'Marseille', + description: "Dolore nisi non id labore. Ea deserunt irure nisi nisi deserunt anim nisi et. Culpa sint mollit deserunt ea eiusmod laborum nostrud." }, }, ], @@ -65,7 +69,7 @@ const sources : PoiMapData["sources"] = { properties: { name: "Battle of Verdun", date: "1916", - description: "The Battle of Verdun was fought from 21 February to 18 December 1916 on the Western Front in France. The battle was the longest of the First World War and took place on the hills north of Verdun-sur-Meuse." + description: "The Battle of Verdun was fought from 21 February to 18 December 1916 on the Western Front in France. The battle was the longest of the First World War and took place on the hills north of Verdun-sur-Meuse. Nisi magna dolor ullamco Lorem culpa ea tempor exercitation dolor ex cupidatat esse voluptate ea. Incididunt consectetur ut officia eiusmod voluptate commodo adipisicing tempor eiusmod esse nulla veniam ut. Aute ipsum eiusmod culpa dolore ea aliquip nulla consectetur reprehenderit in mollit nostrud. Elit commodo non est voluptate pariatur. Exercitation reprehenderit pariatur dolore aute elit ea dolor commodo cillum. Est dolore ut elit in. Ullamco est laborum aute labore. Cillum incididunt laboris do eiusmod fugiat enim veniam aliquip duis incididunt laboris anim nostrud. Laborum mollit esse magna fugiat fugiat fugiat aliquip." }, geometry: { type: "Point", diff --git a/packages/visualizations/src/components/MapPoi/Map.ts b/packages/visualizations/src/components/MapPoi/Map.ts index f883a575..5475115d 100644 --- a/packages/visualizations/src/components/MapPoi/Map.ts +++ b/packages/visualizations/src/components/MapPoi/Map.ts @@ -10,7 +10,7 @@ import maplibregl, { StyleSpecification, } from 'maplibre-gl'; -import { POPUP_OPTIONS, POPUP_WIDTH } from './constants'; +import { POPUP_CLASSNAME, POPUP_OPTIONS, POPUP_WIDTH } from './constants'; import type { PopupsConfiguration, CenterZoomOptions } from './types'; const CURSOR = { @@ -194,13 +194,15 @@ export default class MapPOI { this.popup.setLngLat(geometry.coordinates as LngLatLike).addTo(map); } + this.popup.addClassName(`${POPUP_CLASSNAME}--loading`); this.popup.setHTML(getLoadingContent()); getContent(featureId, properties).then((content) => { this.popup.setHTML(content); + this.popup.removeClassName(`${POPUP_CLASSNAME}--loading`); }); const classnameModifier = display === 'sidebar' ? 'addClassName' : 'removeClassName'; - this.popup[classnameModifier](`${POPUP_OPTIONS.className}--as-sidebar`); + this.popup[classnameModifier](`${POPUP_CLASSNAME}--as-sidebar`); if (display === 'sidebar') { map.easeTo({ diff --git a/packages/visualizations/src/components/MapPoi/MapRender.svelte b/packages/visualizations/src/components/MapPoi/MapRender.svelte index a0a66fae..7177dad6 100644 --- a/packages/visualizations/src/components/MapPoi/MapRender.svelte +++ b/packages/visualizations/src/components/MapPoi/MapRender.svelte @@ -112,6 +112,8 @@ } } .map-card { + container-type: inline-size; + container-name: map-card; display: flex; flex-direction: column; margin: 0; @@ -124,27 +126,93 @@ figcaption h3 { margin: 0; } + /* To add classes programmatically in svelte we will use a global selector. We place it inside a local selector to obtain some encapsulation and avoid side effects */ + + /* --- POPUP --- */ .map-card :global(.poi-map__popup) { /* To be above map controls (z-index: 2)*/ z-index: 3; - /* 26px is for its padding */ - max-height: calc(100% - 26px); height: auto; - overflow-y: auto; + max-height: 100%; } .map-card :global(.poi-map__popup.poi-map__popup--as-sidebar) { /* TO DO: add common stylesheet */ - transform: translate(13px, 13px) !important; + transform: translate(0px, 0px) !important; + margin: 13px 13px 0px 13px; } + + /* --- POPUP TIP --- */ .map-card :global(.poi-map__popup.poi-map__popup--as-sidebar > .maplibregl-popup-tip) { display: none; } + + /* --- POPUP CONTENT --- */ .map-card :global(.poi-map__popup > .maplibregl-popup-content) { + display: flex; + flex-direction: column; + flex-wrap: nowrap; padding: 13px; border-radius: 6px; - box-shadow: 0 6px 13px 0 rgba(0, 0, 0, 0.26); + max-height: 100%; + overflow-y: auto; + box-sizing: border-box; + } + + /* --- POPUP CLOSE BUTTON --- */ + .map-card :global(.maplibregl-popup-close-button) { + font-size: 16px; + padding: 0; + width: 24px; + height: 24px; + margin-bottom: 13px; + position: relative; + order: -1; + flex-shrink: 0; + left: calc(100% - 26px); + } + .map-card :global(.maplibregl-popup-close-button:hover) { + background-color: transparent; } + /* Hide close button when content is loading */ + .map-card :global(.poi-map__popup--loading .maplibregl-popup-close-button) { + display: none; + } + + /* --- CONTROLS --- */ + .map-card :global(.maplibregl-ctrl.maplibregl-ctrl-group) { + margin-top: 13px; + margin-right: 13px; + } + + /* --- CONTAINER QUERIES --- */ + @container map-card (width < 600px) { + /* Force tooltip popup to behave like a sidebar popup */ + .map-card :global(.poi-map__popup) { + transform: translate(0px, 0px) !important; + margin: 13px 13px 0px 13px; + width: 100%; + max-width: calc(100% - 26px) !important; + } + .map-card :global(.maplibregl-popup-tip) { + display: none; + } + .map-card :global(.poi-map__popup > .maplibregl-popup-content) { + width: 100%; + } + } + @container map-card (width >= 600px) { + .map-card :global(.poi-map__popup) { + max-width: 300px !important; + } + /* Close button is not visible for tooltip popup */ + .map-card + :global(.poi-map__popup:not(.poi-map__popup--as-sidebar) + .maplibregl-popup-close-button) { + display: none; + } + } + .main { aspect-ratio: var(--aspect-ratio); flex-grow: 1; diff --git a/packages/visualizations/src/components/MapPoi/constants.ts b/packages/visualizations/src/components/MapPoi/constants.ts index 5cb80bda..984ceb69 100644 --- a/packages/visualizations/src/components/MapPoi/constants.ts +++ b/packages/visualizations/src/components/MapPoi/constants.ts @@ -14,8 +14,9 @@ export const DEFAULT_DARK_GREY: Color = '#515457'; export const POPUP_WIDTH = 300; +export const POPUP_CLASSNAME = 'poi-map__popup'; + export const POPUP_OPTIONS: PopupOptions = { - className: 'poi-map__popup', - closeButton: false, - maxWidth: `${POPUP_WIDTH}px`, + className: `${POPUP_CLASSNAME} ${POPUP_CLASSNAME}--loading`, + closeButton: true, };