Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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 (
<div
className="group relative flex items-end shrink-0 h-full no-drag"
style={{ width: `${width}px` }}
>
<button
type="button"
onClick={() => openSettings()}
className={cn(
"flex items-center gap-1.5 rounded-t-md transition-all w-full shrink-0 pr-6 pl-3 h-[80%]",
isActive
? "text-foreground bg-tertiary-active"
: "text-muted-foreground hover:text-foreground hover:bg-tertiary/30",
)}
>
<HiOutlineCog6Tooth className="size-4 shrink-0" />
<span className="text-sm whitespace-nowrap truncate flex-1 text-left">
Settings
</span>
</button>

<Button
type="button"
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
closeSettingsTab();
}}
className={cn(
"mt-1 absolute right-1 top-1/2 -translate-y-1/2 cursor-pointer size-5 group-hover:opacity-100",
isActive ? "opacity-90" : "opacity-0",
)}
aria-label="Close settings"
>
<HiMiniXMark />
</Button>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
>
<HiMiniPlus className="size-4" />
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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<HTMLDivElement>(null);
const scrollRef = useRef<HTMLDivElement>(null);
const [showStartFade, setShowStartFade] = useState(false);
Expand Down Expand Up @@ -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}
Expand All @@ -137,6 +147,19 @@ export function WorkspacesTabs() {
)}
</Fragment>
))}
{isSettingsTabOpen && (
<>
{groups.length > 0 && (
<div className="flex items-center h-full py-2">
<div className="w-px h-full bg-border" />
</div>
)}
<SettingsTab
width={workspaceWidth}
isActive={isSettingsActive}
/>
</>
)}
</div>

{/* Fade effects for scroll indication */}
Expand Down
12 changes: 12 additions & 0 deletions apps/desktop/src/renderer/stores/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ 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;
}

export const useAppStore = create<AppState>()(
devtools(
(set) => ({
currentView: "workspace",
isSettingsTabOpen: false,
settingsSection: "appearance",

setView: (view) => {
Expand All @@ -26,6 +29,7 @@ export const useAppStore = create<AppState>()(
openSettings: (section) => {
set({
currentView: "settings",
isSettingsTabOpen: true,
...(section && { settingsSection: section }),
});
},
Expand All @@ -34,6 +38,10 @@ export const useAppStore = create<AppState>()(
set({ currentView: "workspace" });
},

closeSettingsTab: () => {
set({ currentView: "workspace", isSettingsTabOpen: false });
},

setSettingsSection: (section) => {
set({ settingsSection: section });
},
Expand All @@ -44,10 +52,14 @@ export const useAppStore = create<AppState>()(

// 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 = () =>
useAppStore((state) => state.setSettingsSection);
export const useOpenSettings = () => useAppStore((state) => state.openSettings);
export const useCloseSettings = () =>
useAppStore((state) => state.closeSettings);
export const useCloseSettingsTab = () =>
useAppStore((state) => state.closeSettingsTab);
Loading