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);