diff --git a/libs/shared/lib/components/colorComponents/colorDropdown/index.tsx b/libs/shared/lib/components/colorComponents/colorDropdown/index.tsx
index f16a9a350127f4b81f6cbdd63d827ffecf8a31d5..1ffe9ed536a9b9885833f95dd4de7d99673233ba 100644
--- a/libs/shared/lib/components/colorComponents/colorDropdown/index.tsx
+++ b/libs/shared/lib/components/colorComponents/colorDropdown/index.tsx
@@ -51,7 +51,7 @@ export const DropdownColorLegend = ({ value, onChange }: DropdownColorLegendProp
 
   return (
     <div className="w-200 h-200 relative">
-      <DropdownContainer>
+      <DropdownContainer open={menuOpen}>
         <DropdownTrigger
           title={
             <div className="flex items-center h-4">
@@ -69,23 +69,21 @@ export const DropdownColorLegend = ({ value, onChange }: DropdownColorLegendProp
           }
           onClick={() => setMenuOpen(!menuOpen)}
         />
-        {menuOpen && (
-          <DropdownItemContainer className="absolute w-60 bg-white shadow-lg z-10">
-            <ul>
-              {Object.keys(colorStructure).map((option: string, index) => (
-                <li key={index} onClick={() => handleOptionClick(option)} className="cursor-pointer flex items-center ml-2 h-4 m-2">
-                  <ColorLegend
-                    key={index.toString() + '_colorLegend'}
-                    colors={colorStructure[option].colors}
-                    data={colorStructure[option].data}
-                    name={colorStructure[option].name}
-                    showAxis={colorStructure[option].showAxis}
-                  />
-                </li>
-              ))}
-            </ul>
-          </DropdownItemContainer>
-        )}
+        <DropdownItemContainer className="absolute w-60 bg-white shadow-lg z-10">
+          <ul>
+            {Object.keys(colorStructure).map((option: string, index) => (
+              <li key={index} onClick={() => handleOptionClick(option)} className="cursor-pointer flex items-center ml-2 h-4 m-2">
+                <ColorLegend
+                  key={index.toString() + '_colorLegend'}
+                  colors={colorStructure[option].colors}
+                  data={colorStructure[option].data}
+                  name={colorStructure[option].name}
+                  showAxis={colorStructure[option].showAxis}
+                />
+              </li>
+            ))}
+          </ul>
+        </DropdownItemContainer>
       </DropdownContainer>
     </div>
   );
diff --git a/libs/shared/lib/vis/visualizations/mapvis/components/Tooltip.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/Tooltip.tsx
index 772e9ea72309441a0448b1ff1fd58a70b9fe5f97..ea5bc92fc41140633a1698955284d7d6a8bc96a1 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/components/Tooltip.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/components/Tooltip.tsx
@@ -2,11 +2,11 @@ import React from 'react';
 import { NodeType } from '../../nodelinkvis/types';
 import { GeoJsonType } from '../mapvis.types';
 import { SearchResultType } from '../mapvis.types';
+import { TooltipProvider } from '@graphpolaris/shared/lib/components';
 
 export type NodelinkPopupProps = {
   type: 'node' | 'area' | 'location';
   data: NodeType | GeoJsonType | SearchResultType;
-  onClose: () => void;
 };
 
 const isGeoJsonType = (data: NodeType | GeoJsonType | SearchResultType): data is GeoJsonType => {
@@ -18,15 +18,30 @@ export const MapTooltip = (props: NodelinkPopupProps) => {
 
   const renderNodeDetails = (node: NodeType) => (
     <div>
-      {node.attributes &&
+      {Object.keys(node.attributes).length === 0 ? (
+        <div className="flex justify-center items-center h-full">
+          <span>No attributes</span>
+        </div>
+      ) : (
         Object.entries(node.attributes).map(([k, v]) => (
-          <div key={k} className="flex flex-row gap-3">
-            <span>{k}: </span>
-            <span className="ml-auto max-w-[10rem] text-right truncate">
-              <span title={JSON.stringify(v)}>{JSON.stringify(v)}</span>
+          <div key={k} className="flex flex-row gap-1 items-center min-h-5">
+            <span className="font-semibold truncate min-w-[40%]">{k}</span>
+            <span className="ml-auto text-right truncate grow-1 flex items-center">
+              {v !== undefined && (typeof v !== 'object' || Array.isArray(v)) && v != '' ? (
+                <span className="ml-auto text-right truncate">{typeof v === 'number' ? v.toLocaleString('de-DE') : v.toString()}</span>
+              ) : (
+                <div
+                  className={`ml-auto mt-auto h-4 w-12 border-[1px] solid border-gray`}
+                  style={{
+                    background:
+                      'repeating-linear-gradient(-45deg, transparent, transparent 6px, #eaeaea 6px, #eaeaea 8px), linear-gradient(to bottom, transparent, transparent)',
+                  }}
+                ></div>
+              )}
             </span>
           </div>
-        ))}
+        ))
+      )}
     </div>
   );
 
@@ -79,32 +94,22 @@ export const MapTooltip = (props: NodelinkPopupProps) => {
   );
 
   return (
-    <div className="text-[0.9rem] min-w-[10rem]">
-      <div className="card-body p-0">
-        <span className="px-2.5 pt-2">
-          <span>{type === 'node' ? 'Node' : 'Area'}</span>
-          <span className="float-right">
+    <TooltipProvider delayDuration={100}>
+      <div className="text-[0.9rem] min-w-[10rem]">
+        <div className="card-body p-0">
+          <div className="h-[1px] w-full bg-secondary-200"></div>
+          <div className="px-2.5 text-[0.8rem]">
             {type === 'node'
-              ? (data as NodeType)?._id
-              : isGeoJsonType(data)
-                ? data.properties?.name
-                : type === 'location'
-                  ? (data as SearchResultType)?.name
-                  : 'N/A'}
-          </span>
-        </span>
-        <div className="h-[1px] w-full bg-secondary-200"></div>
-        <div className="px-2.5 text-[0.8rem]">
-          {type === 'node'
-            ? data && 'attributes' in data
-              ? renderNodeDetails(data as NodeType)
-              : null
-            : data && isGeoJsonType(data)
-              ? renderAreaDetails(data as GeoJsonType)
-              : renderLocationDetails(data as SearchResultType)}
+              ? data && 'attributes' in data
+                ? renderNodeDetails(data as NodeType)
+                : null
+              : data && isGeoJsonType(data)
+                ? renderAreaDetails(data as GeoJsonType)
+                : renderLocationDetails(data as SearchResultType)}
+          </div>
+          <div className="h-[1px] w-full"></div>
         </div>
-        <div className="h-[1px] w-full"></div>
       </div>
-    </div>
+    </TooltipProvider>
   );
 };
diff --git a/libs/shared/lib/vis/visualizations/mapvis/config.ts b/libs/shared/lib/vis/visualizations/mapvis/config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..db5f810c65a11bebd484c70566b5229530fdbd8d
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/mapvis/config.ts
@@ -0,0 +1,5 @@
+export const MAP_PROVIDER = [
+  'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
+  'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png',
+  'https://c.tile.openstreetmap.org/{z}/{x}/{y}.png',
+];
diff --git a/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx
index 52395513b83a59ebd11cd2ef183643fcf580345b..5641f01820187f0b3a85308fbf483e57b57c02a8 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx
@@ -1,8 +1,6 @@
 import React from 'react';
 import { CompositeLayer, HeatmapLayer, Layer } from 'deck.gl';
-import * as d3 from 'd3';
-import { getDistance } from '../../utlis';
-import { CompositeLayerType, Edge, LayerProps } from '../../mapvis.types';
+import { CompositeLayerType, LayerProps } from '../../mapvis.types';
 import { Node } from '@graphpolaris/shared/lib/data-access';
 
 export class HeatLayer extends CompositeLayer<CompositeLayerType> {
@@ -17,37 +15,6 @@ export class HeatLayer extends CompositeLayer<CompositeLayerType> {
     return changeFlags.propsOrDataChanged || changeFlags.somethingChanged;
   }
 
-  createSegments(edges: Edge[]) {
-    // Generates a path between source and target nodes
-    return edges.map((edge: Edge, index) => {
-      const length = getDistance(edge.path[0], edge.path[1]);
-      const nSegments = length * this.props.settings.nSegments;
-
-      let xscale = d3
-        .scaleLinear()
-        .domain([0, nSegments + 1])
-        .range([edge.path[0][0], edge.path[1][0]]);
-
-      let yscale = d3
-        .scaleLinear()
-        .domain([0, nSegments + 1])
-        .range([edge.path[0][1], edge.path[1][1]]);
-
-      let source = edge.path[0];
-      let target = null;
-      let local = [source];
-
-      for (let j = 1; j <= nSegments; j++) {
-        target = [xscale(j), yscale(j)];
-        local.push(target);
-        source = target;
-      }
-
-      local.push(edge.path.slice(-1)[0]);
-      return { ...edge, path: local };
-    });
-  }
-
   renderLayers() {
     const { data, settings, getNodeLocation, setLayerIds, graphMetadata } = this.props;
     const layerSettings = settings[HeatLayer.type];
diff --git a/libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx
index 9e5f7c31e76c2f3752733dd3c4c0f33ed2462500..92360935c9703cc6d49606b4a90cfe2af9930af2 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx
@@ -7,6 +7,7 @@ import { ChoroplethOptions } from './choropleth-layer/ChoroplethOptions';
 import { TileLayer, BitmapLayer } from 'deck.gl';
 import { MapProps } from '../mapvis';
 import { LayerSettingsComponentType } from '../mapvis.types';
+import { MAP_PROVIDER } from '../config';
 
 export type LayerTypes = 'nodelink' | 'heatmap' | 'choropleth';
 
@@ -26,12 +27,6 @@ export const layerSettings: Record<string, React.FC<MapLayerSettingsPropTypes>>
   choropleth: ChoroplethOptions,
 };
 
-const MAP_PROVIDER = [
-  'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
-  'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png',
-  'https://c.tile.openstreetmap.org/{z}/{x}/{y}.png',
-];
-
 export const createBaseMap = () => {
   return new TileLayer({
     data: MAP_PROVIDER,
diff --git a/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx
index dd407682b8d58002031a3c9d778445accf5ef3f2..a853da41aeda3c90a57fcf4e8737b4eb2efb28c3 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx
@@ -1,21 +1,67 @@
 import React from 'react';
 import { CompositeLayer, Layer } from 'deck.gl';
 import { LineLayer, ScatterplotLayer, TextLayer } from '@deck.gl/layers';
-import { CompositeLayerType, LayerProps } from '../../mapvis.types';
+import { CompositeLayerType, Coordinate, LayerProps } from '../../mapvis.types';
 import { BrushingExtension, CollisionFilterExtension } from '@deck.gl/extensions';
+import { scaleLinear, ScaleLinear, color, interpolateRgb } from 'd3';
+import { Node } from '@graphpolaris/shared/lib/data-access';
+
+interface ColorScales {
+  [label: string]: ScaleLinear<string, string>;
+}
+
+interface NodeLinkLayerState {
+  colorScales: ColorScales;
+  [key: string]: any;
+}
 
 export class NodeLinkLayer extends CompositeLayer<CompositeLayerType> {
   static type = 'nodelink';
   private _layers: Record<string, Layer> = {};
 
+  state: NodeLinkLayerState = {
+    colorScales: {},
+  };
+
   constructor(props: LayerProps) {
     super(props);
   }
 
-  updateState({ changeFlags }: { changeFlags: any }) {
+  updateState({ props, changeFlags }: { props: any; changeFlags: any }) {
+    // TODO: Remove any here
+    if (changeFlags.propsOrDataChanged) {
+      const colorScales: ColorScales = {};
+      Object.keys(props.settings[NodeLinkLayer.type].nodes).map((label) => {
+        const nodeSettings = props.settings[NodeLinkLayer.type].nodes[label];
+        const nodeDistribution = props.graphMetadata.nodes.types[label].attributes;
+        if (nodeSettings.colorByAttribute) {
+          if (nodeSettings.colorAttributeType === 'numerical') {
+            colorScales[label] = this.setNumericalColor(
+              nodeDistribution[nodeSettings?.colorAttribute]?.min,
+              nodeDistribution[nodeSettings?.colorAttribute]?.max,
+              nodeSettings.colorScale,
+            );
+          }
+        }
+      });
+      this.setState({ colorScales });
+    }
     return changeFlags.propsOrDataChanged || changeFlags.somethingChanged;
   }
 
+  setNumericalColor(min: number, max: number, colorScale: string) {
+    return scaleLinear<string>().domain([min, max]).range(['white', colorScale]).interpolate(interpolateRgb);
+  }
+
+  rgbStringToArray(rgbString: string): [number, number, number] {
+    const rgb = color(rgbString);
+    if (!rgb || !rgb.formatRgb()) return [0, 0, 0];
+    const match = rgb.formatRgb().match(/\d+/g);
+    if (!match || match.length !== 3) return [0, 0, 0];
+    const [r, g, b] = match.map(Number) as [number, number, number];
+    return [r, g, b];
+  }
+
   renderLayers() {
     const { data, settings, getNodeLocation, ml, graphMetadata, selected } = this.props;
     const layerSettings = settings[NodeLinkLayer.type];
@@ -23,7 +69,7 @@ export class NodeLinkLayer extends CompositeLayer<CompositeLayerType> {
     const brushingExtension = new BrushingExtension();
     const collisionFilter = new CollisionFilterExtension();
 
-    const nodeLocations = data.nodes.reduce((acc: Record<string, [number, number]>, node: any) => {
+    const nodeLocations = data.nodes.reduce((acc: Record<string, Coordinate>, node: Node) => {
       const pos = getNodeLocation(node._id);
       if (pos && (pos[0] !== 0 || pos[1] !== 0)) {
         acc[node._id] = pos;
@@ -31,13 +77,15 @@ export class NodeLinkLayer extends CompositeLayer<CompositeLayerType> {
       return acc;
     }, {});
 
+    const hiddenNodes = new Set(data.nodes.filter((node) => layerSettings.nodes[node.label]?.hidden).map((node) => node._id));
+
     graphMetadata.edges.labels.forEach((label: string) => {
       const layerId = `${label}-edges-line`;
 
-      const edgeData = data.edges.filter((edge: any) => {
+      const edgeData = data.edges.filter((edge) => {
         const from = nodeLocations[edge.from];
         const to = nodeLocations[edge.to];
-        return from && to;
+        return from && to && !hiddenNodes.has(edge.from) && !hiddenNodes.has(edge.to);
       });
 
       this._layers[layerId] = new LineLayer({
@@ -70,31 +118,50 @@ export class NodeLinkLayer extends CompositeLayer<CompositeLayerType> {
       const layerId = `${label}-nodes-scatterplot`;
       const textLayerId = `${label}-label-target`;
 
-      const nodes = data.nodes.filter((node: any) => nodeLocations[node._id] && node.label === label);
+      const nodes = data.nodes.filter((node: Node) => nodeLocations[node._id] && node.label === label);
 
       this._layers[layerId] = new ScatterplotLayer({
         id: layerId,
         visible: !layerSettings?.nodes[label]?.hidden,
         data: nodes,
         pickable: true,
-        getFillColor: (d) => layerSettings?.nodes[label]?.color,
-        getPosition: (d) => getNodeLocation(d._id),
-        getRadius: (d) => layerSettings?.nodes[label]?.size,
+        getFillColor: (d) => {
+          if (layerSettings?.nodes[label].colorByAttribute) {
+            let attributeValue = d.attributes[layerSettings?.nodes[label].colorAttribute];
+            if (layerSettings?.nodes[label].colorAttributeType === 'categorical') {
+              return layerSettings?.nodes[label]?.colorMapping[attributeValue];
+            } else if (layerSettings?.nodes[label].colorAttributeType === 'numerical') {
+              if (typeof attributeValue === 'string') {
+                const numericValue = parseFloat(attributeValue.replace(/[^0-9.]/g, ''));
+                if (!isNaN(numericValue)) {
+                  attributeValue = numericValue;
+                }
+              }
+              const colorScale = this.state.colorScales[label];
+              return this.rgbStringToArray(colorScale(attributeValue));
+            }
+          }
+          return layerSettings?.nodes[label].color;
+        },
+        getPosition: (d: Node) => getNodeLocation(d._id),
+        getRadius: () => layerSettings?.nodes[label]?.size,
         radiusMinPixels: 5,
-        getLineWidth: (d: any) => (selected && selected.some((sel) => sel._id === d._id) ? 2 : 1),
+        getLineWidth: (d: Node) => (selected && selected.some((sel) => sel._id === d._id) ? 2 : 1),
         lineWidthUnits: 'pixels',
         stroked: true,
         updateTriggers: {
           getIcon: [selected],
+          getRadius: [layerSettings?.nodes[label].size],
+          getFillColor: [this.state.colorScales],
         },
       });
 
       this._layers[textLayerId] = new TextLayer({
         id: textLayerId,
         data: nodes,
-        getPosition: (d: any) => getNodeLocation(d._id),
-        getText: (d: any) => d.label,
-        getSize: (d: any) => (layerSettings?.nodes[label]?.size * 2) / d.label.length,
+        getPosition: (d: Node) => getNodeLocation(d._id),
+        getText: (d: Node) => d.label,
+        getSize: (d: Node) => (layerSettings?.nodes[label]?.size * 2) / d.label.length,
         getAlignmentBaseline: 'center',
         getRadius: 10,
         radiusScale: 20,
diff --git a/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx
index 5668172943e5401a198876afbbd212c28052b17e..70b08dd096885b67ea95f2299ac23f46bebe83a1 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx
@@ -3,15 +3,18 @@ import ColorPicker from '@graphpolaris/shared/lib/components/colorComponents/col
 import { Button, DropdownColorLegend, EntityPill, Icon, Input, RelationPill } from '@graphpolaris/shared/lib/components';
 import { MapProps } from '../../mapvis';
 import { LayerSettingsComponentType } from '../../mapvis.types';
-import { nodeColorHex } from '../../utils';
+import { nodeColorRGB } from '../../utils';
+import { isEqual } from 'lodash-es';
 
 const defaultNodeSettings = (index: number) => ({
+  color: nodeColorRGB(index),
+  colorMapping: {},
+  colorScale: undefined,
   colorByAttribute: false,
   colorAttribute: undefined,
   colorAttributeType: undefined,
   hidden: false,
   shape: 'circle',
-  color: nodeColorHex(index),
   size: 40,
 });
 
@@ -53,7 +56,7 @@ export function NodeLinkOptions({
       {} as typeof edges,
     );
 
-    if (JSON.stringify(newNodes) !== JSON.stringify(nodes) || JSON.stringify(newEdges) !== JSON.stringify(edges)) {
+    if (!isEqual(newNodes, nodes) || !isEqual(newEdges, edges)) {
       updateLayerSettings({
         ...layerSettings,
         nodes: newNodes,
@@ -161,7 +164,6 @@ export function NodeLinkOptions({
                               type="dropdown"
                               value={nodeSettings.colorAttribute}
                               options={Object.keys(graphMetadata.nodes.types[nodeType]?.attributes)}
-                              disabled={!settings.nodes}
                               onChange={(val) =>
                                 updateLayerSettings({
                                   nodes: {
@@ -177,6 +179,7 @@ export function NodeLinkOptions({
                             />
                             {nodeSettings.colorAttributeType === 'numerical' ? (
                               <div>
+                                <p>Select color scale:</p>
                                 <DropdownColorLegend
                                   value={settings?.colorScale}
                                   onChange={(val) =>
@@ -187,7 +190,32 @@ export function NodeLinkOptions({
                                 />
                               </div>
                             ) : (
-                              <div>Categorical</div>
+                              nodeSettings.colorAttributeType === 'categorical' &&
+                              nodeSettings.colorAttribute && (
+                                <div>
+                                  {(
+                                    graphMetadata.nodes.types[nodeType] as { attributes: { [key: string]: { values: string[] } } }
+                                  )?.attributes?.[nodeSettings.colorAttribute]?.values.map((attr: string) => (
+                                    <div key={attr} className="flex items-center justify-between">
+                                      <p className="truncate w-18">{attr.length > 0 ? attr : 'Empty val'}</p>
+                                      <ColorPicker
+                                        value={(nodeSettings?.colorMapping ?? {})[attr] ?? [0, 0, 0]}
+                                        updateValue={(val) => {
+                                          updateLayerSettings({
+                                            nodes: {
+                                              ...layerSettings.nodes,
+                                              [nodeType]: {
+                                                ...nodeSettings,
+                                                colorMapping: { ...nodeSettings.colorMapping, [attr]: val },
+                                              },
+                                            },
+                                          });
+                                        }}
+                                      />
+                                    </div>
+                                  ))}
+                                </div>
+                              )
                             )}
                           </div>
                         )}
diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
index e48b49d6f9c274564aadccee426e4373115bb0c5..c7e6c50baff8a21a553f572b58eaf860d084cc8b 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
@@ -1,14 +1,17 @@
 import React, { useEffect, useCallback, useState, useRef, forwardRef, useImperativeHandle } from 'react';
 import DeckGL, { DeckGLProps, DeckGLRef } from '@deck.gl/react';
-import { CompositeLayer, FlyToInterpolator, MapViewState, MapViewState, WebMercatorViewport } from '@deck.gl/core';
+import { CompositeLayer, FlyToInterpolator, MapViewState, WebMercatorViewport } from '@deck.gl/core';
 import { CompositeLayerType, Coordinate, LayerSettingsType, LocationInfo, SearchResultType } from './mapvis.types';
 import { VISComponentType, VisualizationPropTypes } from '../../common';
 import { layerTypes, createBaseMap, LayerTypes } from './layers';
 import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
 import { geoCentroid } from 'd3';
 import { Attribution, ActionBar, MapTooltip, MapSettings } from './components';
-import { Tooltip, TooltipContent, TooltipTrigger } from '@graphpolaris/shared/lib/components';
 import { useSelectionLayer, useCoordinateLookup } from './hooks';
+import { VisualizationTooltip } from '@graphpolaris/shared/lib/components/VisualizationTooltip';
+import { Tooltip, TooltipContent, TooltipTrigger } from '@graphpolaris/shared/lib/components/tooltip';
+import { isGeoJsonType } from './utils';
+import { NodeType } from '../nodelinkvis/types';
 
 export type MapProps = {
   layer: LayerTypes;
@@ -257,7 +260,20 @@ export const MapVis = forwardRef((props: VisualizationPropTypes<MapProps>, refEx
           <Tooltip key={index} open={true} interactive={false} boundaryElement={ref} showArrow={true}>
             <TooltipTrigger x={node.x} y={node.y} />
             <TooltipContent>
-              <MapTooltip type={node.selectedType} onClose={() => {}} data={{ ...node }} key={node._id} />
+              <VisualizationTooltip
+                name={
+                  node.selectedType === 'node'
+                    ? (node as NodeType)?._id
+                    : isGeoJsonType(node)
+                      ? node.properties?.name
+                      : node.selectedType === 'location'
+                        ? (node as SearchResultType)?.name
+                        : 'N/A'
+                }
+                colorHeader="#FB9637"
+              >
+                <MapTooltip type={node.selectedType} data={{ ...node }} key={node._id} />
+              </VisualizationTooltip>
             </TooltipContent>
           </Tooltip>
         ))}
@@ -265,7 +281,7 @@ export const MapVis = forwardRef((props: VisualizationPropTypes<MapProps>, refEx
         <Tooltip open={true} interactive={false} boundaryElement={ref} showArrow={true}>
           <TooltipTrigger x={searchResult.x} y={searchResult.y} />
           <TooltipContent>
-            <MapTooltip type="location" onClose={() => {}} data={{ ...searchResult }} key={searchResult.name} />
+            <MapTooltip type="location" data={{ ...searchResult }} key={searchResult.name} />
           </TooltipContent>
         </Tooltip>
       )}
diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.types.ts b/libs/shared/lib/vis/visualizations/mapvis/mapvis.types.ts
index 08ef8bd7a452d4f43447981954e29f729d1a4095..fe4068e203a4dd78d5aaf1e5d14056be85975aef 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/mapvis.types.ts
+++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.types.ts
@@ -25,6 +25,7 @@ export type MapNodeData = {
   colorAttribute?: string | undefined;
   colorAttributeType?: string | undefined;
   colorScale: string;
+  colorMapping?: { [label: string]: [number, number, number] };
 };
 
 export type MapEdgeData = {
diff --git a/libs/shared/lib/vis/visualizations/mapvis/utils.ts b/libs/shared/lib/vis/visualizations/mapvis/utils.ts
index d45003bd9917c328ef2bbb4493add45c3e0f8c09..9cd704f2abfebb238587147992a41bf14851076e 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/utils.ts
+++ b/libs/shared/lib/vis/visualizations/mapvis/utils.ts
@@ -1,6 +1,9 @@
 import { visualizationColors } from 'config';
+import { NodeType } from '../nodelinkvis/types';
+import { GeoJsonType } from './mapvis.types';
+import { SearchResultType } from './mapvis.types';
 
-export function nodeColorHex(num: number) {
+export function nodeColorRGB(num: number) {
   const colorVal = visualizationColors.GPCat.colors[14][num % visualizationColors.GPCat.colors[14].length];
   const hex = colorVal.replace(/^#/, '');
   const r = parseInt(hex.substring(0, 2), 16);
@@ -8,3 +11,7 @@ export function nodeColorHex(num: number) {
   const b = parseInt(hex.substring(4, 6), 16);
   return [r, g, b];
 }
+
+export const isGeoJsonType = (data: NodeType | GeoJsonType | SearchResultType): data is GeoJsonType => {
+  return (data as GeoJsonType).properties !== undefined;
+};
diff --git a/libs/shared/lib/vis/visualizations/mapvis/utlis.tsx b/libs/shared/lib/vis/visualizations/mapvis/utlis.tsx
deleted file mode 100644
index 06db43a108157678c730e20e08a56c992ed6fa7f..0000000000000000000000000000000000000000
--- a/libs/shared/lib/vis/visualizations/mapvis/utlis.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Coordinate } from './mapvis.types';
-
-export const getDistance = (loc1: Coordinate, loc2: Coordinate): number => {
-  const [minLon, minLat]: Coordinate = loc1;
-  const [maxLon, maxLat]: Coordinate = loc2;
-  const lonDistance: number = (maxLon ?? 0) - (minLon ?? 0);
-  const latDistance: number = (maxLat ?? 0) - (minLat ?? 0);
-  const featureHypot: number = Math.hypot(lonDistance, latDistance);
-  return featureHypot;
-};