Skip to content

Commit acfa7d2

Browse files
danditomasoCopilot
andauthored
Add badge indicator on layers icon. (#894)
* feat: indicate number of layers enabled. * Update packages/web/src/components/PageComponents/Map/Tools/MapLayerTool.tsx Co-authored-by: Copilot <[email protected]> * fix: reduced code duplication in layers component * fixed unread message bubble --------- Co-authored-by: Copilot <[email protected]>
1 parent 8f62fb7 commit acfa7d2

File tree

2 files changed

+49
-47
lines changed

2 files changed

+49
-47
lines changed

packages/web/src/components/PageComponents/Map/Tools/MapLayerTool.tsx

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from "@components/UI/Popover.tsx";
77
import { cn } from "@core/utils/cn.ts";
88
import { LayersIcon } from "lucide-react";
9-
import type { ReactNode } from "react";
9+
import { type ReactNode, useMemo } from "react";
1010
import { useTranslation } from "react-i18next";
1111

1212
export interface VisibilityState {
@@ -62,13 +62,36 @@ export function MapLayerTool({
6262
}: MapLayerToolProps): ReactNode {
6363
const { t } = useTranslation("map");
6464

65+
const enabledCount = useMemo(() => {
66+
return Object.values(visibilityState).filter(Boolean).length;
67+
}, [visibilityState]);
68+
69+
const handleCheckboxChange = (key: keyof VisibilityState) => {
70+
setVisibilityState({
71+
...visibilityState,
72+
[key]: !visibilityState[key],
73+
});
74+
};
75+
76+
const layers = useMemo(
77+
() => [
78+
{ key: "nodeMarkers", label: t("layerTool.nodeMarkers") },
79+
{ key: "waypoints", label: t("layerTool.waypoints") },
80+
{ key: "directNeighbors", label: t("layerTool.directNeighbors") },
81+
{ key: "remoteNeighbors", label: t("layerTool.remoteNeighbors") },
82+
{ key: "positionPrecision", label: t("layerTool.positionPrecision") },
83+
// { key: "traceroutes", label: t("layerTool.traceroutes") },
84+
],
85+
[t],
86+
);
87+
6588
return (
6689
<Popover>
6790
<PopoverTrigger asChild>
6891
<button
6992
type="button"
7093
className={cn(
71-
"rounded align-center",
94+
"relative rounded align-center",
7295
"w-[29px] px-1 py-1 shadow-l outline-[2px] outline-stone-600/20",
7396
"bg-stone-50 hover:bg-stone-200 dark:bg-stone-200 dark:hover:bg-stone-300 ",
7497
"text-slate-600 hover:text-slate-700 active:bg-slate-300",
@@ -77,6 +100,21 @@ export function MapLayerTool({
77100
aria-label={t("mapMenu.layersAria")}
78101
>
79102
<LayersIcon className="w-[21px]" />
103+
{enabledCount > 0 && (
104+
<span
105+
className={cn(
106+
"absolute -bottom-2 -right-2",
107+
"min-w-4 h-4 px-[3px]",
108+
"rounded-full text-[10px] leading-4",
109+
"bg-blue-500 text-white",
110+
"flex items-center justify-center",
111+
"ring-2 ring-white dark:ring-stone-200",
112+
)}
113+
aria-hidden="true"
114+
>
115+
{enabledCount}
116+
</span>
117+
)}
80118
</button>
81119
</PopoverTrigger>
82120
<PopoverContent
@@ -85,50 +123,14 @@ export function MapLayerTool({
85123
align="end"
86124
sideOffset={7}
87125
>
88-
<CheckboxItem
89-
label={t("layerTool.nodeMarkers")}
90-
checked={visibilityState.nodeMarkers}
91-
onChange={(checked) => {
92-
setVisibilityState({ ...visibilityState, nodeMarkers: checked });
93-
}}
94-
/>
95-
<CheckboxItem
96-
label={t("layerTool.waypoints")}
97-
checked={visibilityState.waypoints}
98-
onChange={(checked) => {
99-
setVisibilityState({ ...visibilityState, waypoints: checked });
100-
}}
101-
/>
102-
<CheckboxItem
103-
label={t("layerTool.directNeighbors")}
104-
checked={visibilityState.directNeighbors}
105-
onChange={(checked) => {
106-
setVisibilityState({
107-
...visibilityState,
108-
directNeighbors: checked,
109-
});
110-
}}
111-
/>
112-
<CheckboxItem
113-
label={t("layerTool.remoteNeighbors")}
114-
checked={visibilityState.remoteNeighbors}
115-
onChange={(checked) => {
116-
setVisibilityState({
117-
...visibilityState,
118-
remoteNeighbors: checked,
119-
});
120-
}}
121-
/>
122-
<CheckboxItem
123-
label={t("layerTool.positionPrecision")}
124-
checked={visibilityState.positionPrecision}
125-
onChange={(checked) => {
126-
setVisibilityState({
127-
...visibilityState,
128-
positionPrecision: checked,
129-
});
130-
}}
131-
/>
126+
{layers.map(({ key, label }) => (
127+
<CheckboxItem
128+
key={key}
129+
label={label}
130+
checked={visibilityState[key as keyof VisibilityState]}
131+
onChange={() => handleCheckboxChange(key as keyof VisibilityState)}
132+
/>
133+
))}
132134
{/*<CheckboxItem
133135
key="traceroutes"
134136
label={t("layerTool.traceroutes")}

packages/web/src/components/UI/Sidebar/SidebarButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export const SidebarButton = ({
7070
"flex-shrink-0",
7171
"transition-opacity duration-300 ease-in-out",
7272
isButtonCollapsed ? "opacity-0 invisible" : "opacity-100 visible",
73-
isDirty ? "bg-sky-500" : "bg-red-600",
73+
isDirty ? "bg-sky-500" : "bg-blue-500",
7474
)}
7575
>
7676
{count}

0 commit comments

Comments
 (0)