diff --git a/apps/client/src/components/layouts/global/app-header.module.css b/apps/client/src/components/layouts/global/app-header.module.css
index 7cdec643..6abbdad4 100644
--- a/apps/client/src/components/layouts/global/app-header.module.css
+++ b/apps/client/src/components/layouts/global/app-header.module.css
@@ -13,6 +13,7 @@
text-decoration: none;
color: inherit;
cursor: pointer;
+ user-select: none;
}
.brandIcon {
@@ -33,21 +34,3 @@
that is ~9.3px, minus the font descent (~2px) ≈ 7px. */
margin-bottom: rem(7px);
}
-
-.link {
- display: block;
- line-height: 1;
- padding: rem(8px) rem(12px);
- border-radius: var(--mantine-radius-sm);
- text-decoration: none;
- color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0));
- font-size: var(--mantine-font-size-sm);
- font-weight: 500;
- user-select: none;
- white-space: nowrap;
- flex-shrink: 0;
-
- @mixin hover {
- background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6));
- }
-}
diff --git a/apps/client/src/components/layouts/global/app-header.tsx b/apps/client/src/components/layouts/global/app-header.tsx
index fc8e769a..8eb7c303 100644
--- a/apps/client/src/components/layouts/global/app-header.tsx
+++ b/apps/client/src/components/layouts/global/app-header.tsx
@@ -10,7 +10,6 @@ import classes from "./app-header.module.css";
import { BrandLogo } from "@/components/ui/brand-logo";
import TopMenu from "@/components/layouts/global/top-menu.tsx";
import { Link } from "react-router-dom";
-import APP_ROUTE from "@/lib/app-route.ts";
import { useAtom, useSetAtom } from "jotai";
import {
desktopSidebarAtom,
@@ -30,10 +29,6 @@ import {
} from "@/features/search/constants.ts";
import { NotificationPopover } from "@/features/notification/components/notification-popover.tsx";
-const links = [
- { link: APP_ROUTE.HOME, label: "Home" },
-];
-
export function AppHeader() {
const { t } = useTranslation();
const [mobileOpened] = useAtom(mobileSidebarAtom);
@@ -47,12 +42,6 @@ export function AppHeader() {
// AI chat entry point: only shown when the workspace enables it (A7 gate).
const aiChatEnabled = workspace?.settings?.ai?.chat === true;
- const items = links.map((link) => (
-
- {t(link.label)}
-
- ));
-
return (
<>
@@ -97,10 +86,6 @@ export function AppHeader() {
-
-
- {items}
-
diff --git a/apps/client/src/components/layouts/global/top-menu.tsx b/apps/client/src/components/layouts/global/top-menu.tsx
index 84925080..f2872ea0 100644
--- a/apps/client/src/components/layouts/global/top-menu.tsx
+++ b/apps/client/src/components/layouts/global/top-menu.tsx
@@ -20,18 +20,29 @@ import {
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
-import { Link } from "react-router-dom";
+import { Link, useMatch } from "react-router-dom";
import APP_ROUTE from "@/lib/app-route.ts";
import useAuth from "@/features/auth/hooks/use-auth.ts";
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { useTranslation } from "react-i18next";
import { AvatarIconType } from "@/features/attachments/types/attachment.types.ts";
+import { useDisclosure } from "@mantine/hooks";
+import SpaceSettingsModal from "@/features/space/components/settings-modal.tsx";
export default function TopMenu() {
const { t } = useTranslation();
const [currentUser] = useAtom(currentUserAtom);
const { logout } = useAuth();
const { colorScheme, setColorScheme } = useMantineColorScheme();
+ // Detect the currently viewed space so the "Space settings" item is only
+ // offered while the user is inside a space. The "/*" splat also matches the
+ // bare "/s/:spaceSlug" route (the splat matches an empty segment).
+ const spaceMatch = useMatch("/s/:spaceSlug/*");
+ const spaceSlug = spaceMatch?.params?.spaceSlug;
+ const [
+ spaceSettingsOpened,
+ { open: openSpaceSettings, close: closeSpaceSettings },
+ ] = useDisclosure(false);
const user = currentUser?.user;
const workspace = currentUser?.workspace;
@@ -41,124 +52,143 @@ export default function TopMenu() {
}
return (
-
+
+
+
{t("Account")}
+
+
+
+
+
+
+ {user.name}
+
+
+ {user.email}
+
+
+
+
+
}
+ >
+ {t("My profile")}
+
+
+
}
+ >
+ {t("My preferences")}
+
+
+
+
+ }>
+ {t("Theme")}
+
+
+
+
+ setColorScheme("light")}
+ leftSection={}
+ rightSection={
+ colorScheme === "light" ? : null
+ }
+ >
+ {t("Light")}
+
+ setColorScheme("dark")}
+ leftSection={}
+ rightSection={
+ colorScheme === "dark" ? : null
+ }
+ >
+ {t("Dark")}
+
+ setColorScheme("auto")}
+ leftSection={}
+ rightSection={
+ colorScheme === "auto" ? : null
+ }
+ >
+ {t("System settings")}
+
+
+
+
+
+
+
}>
+ {t("Logout")}
+
+
+
+
+ {spaceSlug && (
+
+ )}
+ >
);
}
diff --git a/apps/client/src/components/settings/settings-sidebar.tsx b/apps/client/src/components/settings/settings-sidebar.tsx
index 47ecece6..a3f6c0ed 100644
--- a/apps/client/src/components/settings/settings-sidebar.tsx
+++ b/apps/client/src/components/settings/settings-sidebar.tsx
@@ -20,7 +20,6 @@ import {
prefetchSpaces,
prefetchWorkspaceMembers,
} from "@/components/settings/settings-queries.tsx";
-import AppVersion from "@/components/settings/app-version.tsx";
import { mobileSidebarAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts";
import { useToggleSidebar } from "@/components/layouts/global/hooks/hooks/use-toggle-sidebar.ts";
import { useSettingsNavigation } from "@/hooks/use-settings-navigation";
@@ -141,8 +140,6 @@ export default function SettingsSidebar() {
{menuItems}
-
-
);
}
diff --git a/apps/client/src/components/ui/brand-logo.tsx b/apps/client/src/components/ui/brand-logo.tsx
index cc41ce5e..3ec5706f 100644
--- a/apps/client/src/components/ui/brand-logo.tsx
+++ b/apps/client/src/components/ui/brand-logo.tsx
@@ -27,6 +27,7 @@ export function BrandLogo({
src={src}
alt="Gitmost"
className={className}
+ draggable={false}
style={{ height, width: "auto", display: "block", userSelect: "none" }}
/>
);
diff --git a/apps/client/src/features/space/components/sidebar/space-sidebar.tsx b/apps/client/src/features/space/components/sidebar/space-sidebar.tsx
index b5b9a9c8..b6ccfefc 100644
--- a/apps/client/src/features/space/components/sidebar/space-sidebar.tsx
+++ b/apps/client/src/features/space/components/sidebar/space-sidebar.tsx
@@ -87,7 +87,6 @@ export function SpaceSidebar() {
spaceName={space?.name}
spaceSlug={space?.slug}
spaceIcon={space?.logo}
- onSettings={openSettings}
/>
diff --git a/apps/client/src/features/space/components/sidebar/switch-space.module.css b/apps/client/src/features/space/components/sidebar/switch-space.module.css
index 480c40bb..39493607 100644
--- a/apps/client/src/features/space/components/sidebar/switch-space.module.css
+++ b/apps/client/src/features/space/components/sidebar/switch-space.module.css
@@ -2,16 +2,6 @@
width: 100%;
}
-.header {
- padding: rem(4px) var(--mantine-spacing-sm);
-}
-
-.spaceName {
- flex: 1;
- min-width: 0;
- color: light-dark(var(--mantine-color-dark-4), var(--mantine-color-dark-0));
-}
-
.grid {
display: flex;
flex-wrap: wrap;
diff --git a/apps/client/src/features/space/components/sidebar/switch-space.tsx b/apps/client/src/features/space/components/sidebar/switch-space.tsx
index 23b19679..5fc94daf 100644
--- a/apps/client/src/features/space/components/sidebar/switch-space.tsx
+++ b/apps/client/src/features/space/components/sidebar/switch-space.tsx
@@ -1,8 +1,7 @@
import classes from "./switch-space.module.css";
import { useNavigate } from "react-router-dom";
import { getSpaceUrl } from "@/lib/config";
-import { ActionIcon, Group, Text, Tooltip, UnstyledButton } from "@mantine/core";
-import { IconSettings } from "@tabler/icons-react";
+import { Text, UnstyledButton } from "@mantine/core";
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { AvatarIconType } from "@/features/attachments/types/attachment.types.ts";
import {
@@ -10,7 +9,6 @@ import {
useGetSpacesQuery,
} from "@/features/space/queries/space-query.ts";
import { ISpace } from "../../types/space.types";
-import { useTranslation } from "react-i18next";
import clsx from "clsx";
import React, { useMemo } from "react";
@@ -19,7 +17,6 @@ interface SwitchSpaceProps {
spaceName: string;
spaceSlug: string;
spaceIcon?: string;
- onSettings: () => void;
}
export function SwitchSpace({
@@ -27,9 +24,7 @@ export function SwitchSpace({
spaceName,
spaceSlug,
spaceIcon,
- onSettings,
}: SwitchSpaceProps) {
- const { t } = useTranslation();
const navigate = useNavigate();
// Load every space the user belongs to (API caps limit at 100) and render
// them as an always-visible grid instead of the previous searchable popover.
@@ -59,31 +54,6 @@ export function SwitchSpace({
return (
-
-
-
- {spaceName}
-
-
-
-
-
-
-
-
{spaces.map((space: ISpace) => (