Skip to content

Commit 1a3da73

Browse files
committed
fix: size & color marker props
1 parent 45aada4 commit 1a3da73

File tree

3 files changed

+100
-35
lines changed

3 files changed

+100
-35
lines changed

src/components/Markers/Markers.tsx

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, useTheme } from "@tracktor/design-system";
1+
import { Box, Theme, useTheme } from "@tracktor/design-system";
22
import { isString } from "@tracktor/react-utils";
33

44
const BLACK = "#000000";
@@ -14,32 +14,58 @@ export const variantMarkerColor = {
1414

1515
export type VariantMarker = keyof typeof variantMarkerColor;
1616

17+
type ThemeColorPath = `${keyof Theme["palette"]}.${string}`;
18+
type ThemeColor = string | ((theme: Theme) => string) | ThemeColorPath;
19+
1720
interface MarkerProps {
1821
variant?: string | keyof typeof variantMarkerColor;
19-
color?: string;
22+
color?: ThemeColor;
23+
size?: number;
2024
}
2125

2226
const isPredefinedVariant = (v: string): v is VariantMarker => v in variantMarkerColor;
2327

24-
const Markers = ({ color, variant }: MarkerProps) => {
25-
const { palette } = useTheme();
26-
const centerColor = palette.mode === "dark" ? BLACK : WHITE;
28+
const Markers = ({ color, variant, size = 28 }: MarkerProps) => {
29+
const theme = useTheme();
30+
const centerColor = theme.palette.mode === "dark" ? BLACK : WHITE;
31+
32+
const borderSize = Math.max(3, Math.round(size * 0.25));
33+
34+
const resolvedColor = (() => {
35+
if (variant && isPredefinedVariant(variant)) {
36+
return variantMarkerColor[variant];
37+
}
38+
39+
if (!color) {
40+
return variantMarkerColor.default;
41+
}
42+
43+
if (typeof color === "function") {
44+
return color(theme);
45+
}
46+
47+
if (isString(color) && color.includes(".")) {
48+
const [paletteKey, shade] = color.split(".") as [keyof Theme["palette"], string];
49+
const paletteSection = theme.palette[paletteKey];
50+
51+
if (paletteSection && typeof paletteSection === "object" && shade in paletteSection) {
52+
return (paletteSection as Record<string, string>)[shade];
53+
}
54+
}
2755

28-
const markerColor =
29-
(variant && isPredefinedVariant(variant) && variantMarkerColor[variant]) ||
30-
color ||
31-
(isString(variant) ? variant : variantMarkerColor.default);
56+
return color;
57+
})();
3258

3359
return (
3460
<Box
3561
component="div"
3662
style={{
3763
backgroundColor: centerColor,
38-
border: `7px solid ${markerColor}`,
64+
border: `${borderSize}px solid ${resolvedColor}`,
3965
borderRadius: "50%",
4066
boxShadow: "0 0 4px rgba(0,0,0,0.3)",
41-
height: 28,
42-
width: 28,
67+
height: size,
68+
width: size,
4369
}}
4470
/>
4571
);

src/features/MapView/MapView.tsx

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Box, GlobalStyles, Skeleton, useTheme } from "@tracktor/design-system";
2-
import { memo, ReactElement, useEffect, useMemo, useRef, useState } from "react";
2+
import { CSSProperties, memo, ReactElement, useEffect, useMemo, useRef, useState } from "react";
33
import MapboxMap, { MapRef, Marker, Popup } from "react-map-gl";
44
import "mapbox-gl/dist/mapbox-gl.css";
55
import { isArray, isNumber } from "@tracktor/react-utils";
@@ -185,28 +185,57 @@ const MapView = ({
185185
>
186186
{/* Markers - only rendered after map fully initialized */}
187187
{mapLoaded &&
188-
markers.filter(isValidMarker).map((m) => (
189-
<Marker
190-
key={m.id}
191-
longitude={m.lng}
192-
latitude={m.lat}
193-
anchor="bottom"
194-
onClick={(e) => {
195-
e.originalEvent.stopPropagation();
196-
m.id && handleMarkerClick(m.id, Boolean(m.Tooltip));
197-
onMapClick?.(m.lng, m.lat, m);
198-
}}
199-
>
200-
<Box
201-
component="div"
202-
onMouseEnter={() => m.id && handleMarkerHover(m.id, Boolean(m.Tooltip))}
203-
onMouseLeave={() => handleMarkerHover(null)}
204-
style={{ cursor: m.Tooltip ? "pointer" : "default" }}
188+
markers.filter(isValidMarker).map((m) => {
189+
const size = typeof m.size === "number" ? m.size : undefined;
190+
191+
const iconComponent = (() => {
192+
if (!m.IconComponent) {
193+
return null;
194+
}
195+
196+
const iconProps = { ...m.iconProps };
197+
198+
if (size) {
199+
iconProps.width = size;
200+
iconProps.height = size;
201+
}
202+
203+
return <m.IconComponent {...iconProps} />;
204+
})();
205+
206+
const defaultMarker = m.IconComponent ? null : <Markers color={m.color} variant={m.variant} size={size} />;
207+
208+
const wrapperStyle: CSSProperties = {
209+
alignItems: "center",
210+
cursor: m.Tooltip ? "pointer" : "default",
211+
display: "inline-flex",
212+
justifyContent: "center",
213+
...(m.IconComponent && !size ? {} : size ? { height: size, width: size } : {}),
214+
};
215+
216+
return (
217+
<Marker
218+
key={m.id}
219+
longitude={m.lng}
220+
latitude={m.lat}
221+
anchor="bottom"
222+
onClick={(e) => {
223+
e.originalEvent.stopPropagation();
224+
m.id && handleMarkerClick(m.id, Boolean(m.Tooltip));
225+
onMapClick?.(m.lng, m.lat, m);
226+
}}
205227
>
206-
{m.IconComponent ? <m.IconComponent {...m.iconProps} /> : <Markers color={m.color} variant={m.variant} />}
207-
</Box>
208-
</Marker>
209-
))}
228+
<Box
229+
component="div"
230+
onMouseEnter={() => m.id && handleMarkerHover(m.id, Boolean(m.Tooltip))}
231+
onMouseLeave={() => handleMarkerHover(null)}
232+
style={wrapperStyle}
233+
>
234+
{iconComponent || defaultMarker}
235+
</Box>
236+
</Marker>
237+
);
238+
})}
210239

211240
{/* Popup */}
212241
{mapLoaded && selectedMarker?.Tooltip && (

src/types/MarkerProps.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { Theme } from "@tracktor/design-system";
12
import { ComponentType, ReactNode } from "react";
23
import { VariantMarker } from "@/components/Markers/Markers.tsx";
34

5+
export type ThemeColor = string | ((theme: Theme) => string) | `${keyof Theme["palette"]}.${string}`;
6+
47
interface CustomMarkerMapProps {
58
geometry: {
69
coordinates: number[];
@@ -92,6 +95,13 @@ export interface MarkerProps<T = Record<string, unknown>> {
9295
// biome-ignore lint/suspicious/noExplicitAny: <Icons can receive any props depending on context>
9396
IconComponent?: ComponentType<any>;
9497

95-
color?: string;
98+
/**
99+
* Color theme for the marker.
100+
*/
101+
color?: ThemeColor;
102+
103+
/**
104+
* Predefined variant for the marker styling.
105+
*/
96106
variant?: string | VariantMarker;
97107
}

0 commit comments

Comments
 (0)