diff --git a/src/components/DesktopNavManager.tsx b/src/components/DesktopNavManager.tsx
new file mode 100644
index 0000000..73c0416
--- /dev/null
+++ b/src/components/DesktopNavManager.tsx
@@ -0,0 +1,157 @@
+import { useDesktopNavPreferences, type NavTab } from '@/hooks/useNavPreferences';
+import { useTranslation } from '@/contexts/LanguageContext';
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+import { ArrowUp, ArrowDown, Eye, EyeOff, Lock, RotateCcw, Monitor } from 'lucide-react';
+
+/**
+ * Desktop top-nav customizer (Settings).
+ *
+ * A lightweight list: reorder the primary top-nav tabs with up/down controls
+ * and toggle items shown/hidden. Map is the fixed first tab (locked). Hidden
+ * items still live in the header's "More" dropdown, so nothing is ever lost.
+ * Persists via useDesktopNavPreferences (localStorage).
+ */
+export function DesktopNavManager() {
+ const { primaryIds, hiddenIds, setPrimaryIds, reset, catalog, fixedMapTab } =
+ useDesktopNavPreferences();
+ const { t } = useTranslation();
+
+ const label = (tab: NavTab) => (tab.labelKey ? t(tab.labelKey) : tab.label);
+ const byId = (id: string) => catalog.find((c) => c.id === id);
+
+ const move = (id: string, dir: -1 | 1) => {
+ const idx = primaryIds.indexOf(id);
+ const next = idx + dir;
+ if (idx < 0 || next < 0 || next >= primaryIds.length) return;
+ const copy = [...primaryIds];
+ [copy[idx], copy[next]] = [copy[next], copy[idx]];
+ setPrimaryIds(copy);
+ };
+
+ const hide = (id: string) => setPrimaryIds(primaryIds.filter((x) => x !== id));
+ const show = (id: string) => setPrimaryIds([...primaryIds, id]);
+
+ return (
+
+
+
+
+
+
+
Desktop navigation
+
+ Choose which tabs appear in the top bar and their order. Hidden tabs
+ still live in the “More” menu.
+
+
+
+
+ {/* Fixed Map tab */}
+
+
+ {label(fixedMapTab)}
+
+ Fixed
+
+
+
+ {/* Shown (primary) tabs — reorderable */}
+
+
+ Shown in top bar ({primaryIds.length})
+
+ {primaryIds.length === 0 && (
+
+ No extra tabs shown — everything is in the “More” menu. Add some below.
+
+ )}
+ {primaryIds.map((id, i) => {
+ const tab = byId(id);
+ if (!tab) return null;
+ return (
+
+
+
{label(tab)}
+
+
+
+
+ );
+ })}
+
+
+ {/* Hidden tabs — available to add */}
+ {hiddenIds.length > 0 && (
+
+
+ In “More” menu ({hiddenIds.length})
+
+ {hiddenIds.map((id) => {
+ const tab = byId(id);
+ if (!tab) return null;
+ return (
+
+
+
+ {label(tab)}
+
+
+
+ );
+ })}
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 4cb1955..a5af17c 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -2,7 +2,7 @@ import { useState, useRef } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { cn } from '@/lib/utils';
import { CustomizeNavSheet } from '@/components/CustomizeNavSheet';
-import { useNavPreferences, type NavTab } from '@/hooks/useNavPreferences';
+import { useNavPreferences, useDesktopNavPreferences, type NavTab } from '@/hooks/useNavPreferences';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from '@/components/ui/sheet';
@@ -394,6 +394,12 @@ export function Layout({ children, noPadding }: LayoutProps) {
const displayName = author.data?.metadata?.name ?? genUserName(user?.pubkey);
const userAvatar = author.data?.metadata?.picture;
const { fixedMapTab, middleTabs } = useNavPreferences();
+ const {
+ primaryTabs: desktopPrimaryTabs,
+ hiddenIds: desktopHiddenIds,
+ fixedMapTab: desktopMapTab,
+ catalog: desktopCatalog,
+ } = useDesktopNavPreferences();
const isActive = (path: string) => {
// Both / and /map are the "spots" page
@@ -418,9 +424,10 @@ export function Layout({ children, noPadding }: LayoutProps) {