diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/SettingsTab.tsx b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/SettingsTab.tsx
new file mode 100644
index 00000000000..1b567dddd6e
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/SettingsTab.tsx
@@ -0,0 +1,57 @@
+import { Button } from "@superset/ui/button";
+import { cn } from "@superset/ui/utils";
+import { HiMiniXMark, HiOutlineCog6Tooth } from "react-icons/hi2";
+import {
+ useCloseSettingsTab,
+ useOpenSettings,
+} from "renderer/stores/app-state";
+
+interface SettingsTabProps {
+ width: number;
+ isActive: boolean;
+}
+
+export function SettingsTab({ width, isActive }: SettingsTabProps) {
+ const openSettings = useOpenSettings();
+ const closeSettingsTab = useCloseSettingsTab();
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx
index 42dbb11c340..518b422d02f 100644
--- a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx
@@ -55,7 +55,7 @@ export function WorkspaceDropdown({ className }: WorkspaceDropdownProps) {
variant="ghost"
size="icon"
aria-label="Add new workspace"
- className="ml-1 size-7 text-muted-foreground hover:text-foreground"
+ className="ml-1 mt-1 size-7 text-muted-foreground hover:text-foreground"
>
diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
index b95730bbe68..e621a229770 100644
--- a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
@@ -8,6 +8,7 @@ import {
useSetActiveWorkspace,
} from "renderer/react-query/workspaces";
import { useTabs } from "renderer/stores";
+import { useCloseSettings } from "renderer/stores/app-state";
import { DeleteWorkspaceDialog } from "./DeleteWorkspaceDialog";
import { useWorkspaceRename } from "./useWorkspaceRename";
import { WorkspaceItemContextMenu } from "./WorkspaceItemContextMenu";
@@ -39,6 +40,7 @@ export function WorkspaceItem({
}: WorkspaceItemProps) {
const setActive = useSetActiveWorkspace();
const reorderWorkspaces = useReorderWorkspaces();
+ const closeSettings = useCloseSettings();
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const tabs = useTabs();
const rename = useWorkspaceRename(id, title);
@@ -89,7 +91,12 @@ export function WorkspaceItem({
ref={(node) => {
drag(drop(node));
}}
- onMouseDown={() => !rename.isRenaming && setActive.mutate({ id })}
+ onMouseDown={() => {
+ if (!rename.isRenaming) {
+ closeSettings();
+ setActive.mutate({ id });
+ }
+ }}
onDoubleClick={rename.startRename}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
index 1bde37b413b..61f72a19538 100644
--- a/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
@@ -2,7 +2,12 @@ import { Fragment, useEffect, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { trpc } from "renderer/lib/trpc";
import { useSetActiveWorkspace } from "renderer/react-query/workspaces";
+import {
+ useCurrentView,
+ useIsSettingsTabOpen,
+} from "renderer/stores/app-state";
import { HOTKEYS } from "shared/hotkeys";
+import { SettingsTab } from "./SettingsTab";
import { WorkspaceDropdown } from "./WorkspaceDropdown";
import { WorkspaceGroup } from "./WorkspaceGroup";
@@ -15,6 +20,9 @@ export function WorkspacesTabs() {
const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
const activeWorkspaceId = activeWorkspace?.id || null;
const setActiveWorkspace = useSetActiveWorkspace();
+ const currentView = useCurrentView();
+ const isSettingsTabOpen = useIsSettingsTabOpen();
+ const isSettingsActive = currentView === "settings";
const containerRef = useRef(null);
const scrollRef = useRef(null);
const [showStartFade, setShowStartFade] = useState(false);
@@ -125,7 +133,9 @@ export function WorkspacesTabs() {
projectColor={group.project.color}
projectIndex={groupIndex}
workspaces={group.workspaces}
- activeWorkspaceId={activeWorkspaceId}
+ activeWorkspaceId={
+ isSettingsActive ? null : activeWorkspaceId
+ }
workspaceWidth={workspaceWidth}
hoveredWorkspaceId={hoveredWorkspaceId}
onWorkspaceHover={setHoveredWorkspaceId}
@@ -137,6 +147,19 @@ export function WorkspacesTabs() {
)}
))}
+ {isSettingsTabOpen && (
+ <>
+ {groups.length > 0 && (
+
+ )}
+
+ >
+ )}
{/* Fade effects for scroll indication */}
diff --git a/apps/desktop/src/renderer/stores/app-state.ts b/apps/desktop/src/renderer/stores/app-state.ts
index af5aa389512..9fe5264fbf9 100644
--- a/apps/desktop/src/renderer/stores/app-state.ts
+++ b/apps/desktop/src/renderer/stores/app-state.ts
@@ -6,10 +6,12 @@ export type SettingsSection = "appearance" | "keyboard";
interface AppState {
currentView: AppView;
+ isSettingsTabOpen: boolean;
settingsSection: SettingsSection;
setView: (view: AppView) => void;
openSettings: (section?: SettingsSection) => void;
closeSettings: () => void;
+ closeSettingsTab: () => void;
setSettingsSection: (section: SettingsSection) => void;
}
@@ -17,6 +19,7 @@ export const useAppStore = create()(
devtools(
(set) => ({
currentView: "workspace",
+ isSettingsTabOpen: false,
settingsSection: "appearance",
setView: (view) => {
@@ -26,6 +29,7 @@ export const useAppStore = create()(
openSettings: (section) => {
set({
currentView: "settings",
+ isSettingsTabOpen: true,
...(section && { settingsSection: section }),
});
},
@@ -34,6 +38,10 @@ export const useAppStore = create()(
set({ currentView: "workspace" });
},
+ closeSettingsTab: () => {
+ set({ currentView: "workspace", isSettingsTabOpen: false });
+ },
+
setSettingsSection: (section) => {
set({ settingsSection: section });
},
@@ -44,6 +52,8 @@ export const useAppStore = create()(
// Convenience hooks
export const useCurrentView = () => useAppStore((state) => state.currentView);
+export const useIsSettingsTabOpen = () =>
+ useAppStore((state) => state.isSettingsTabOpen);
export const useSettingsSection = () =>
useAppStore((state) => state.settingsSection);
export const useSetSettingsSection = () =>
@@ -51,3 +61,5 @@ export const useSetSettingsSection = () =>
export const useOpenSettings = () => useAppStore((state) => state.openSettings);
export const useCloseSettings = () =>
useAppStore((state) => state.closeSettings);
+export const useCloseSettingsTab = () =>
+ useAppStore((state) => state.closeSettingsTab);