fix: Finalize new sidebar, improve and loading animations

This commit is contained in:
LukeGus
2025-11-10 01:11:14 -06:00
parent 16e35d7976
commit b0523f995c
13 changed files with 139 additions and 1812 deletions

View File

@@ -101,7 +101,7 @@ export function Dashboard({
const topMarginPx = isTopbarOpen ? 74 : 26;
const leftMarginPx = sidebarState === "collapsed" ? 26 : 8;
const rightMarginPx = rightSidebarOpen ? rightSidebarWidth + 17 : 17;
const rightMarginPx = 17; // Base margin when closed
const bottomMarginPx = 8;
useEffect(() => {
@@ -341,10 +341,14 @@ export function Dashboard({
className="bg-dark-bg text-white rounded-lg border-2 border-dark-border overflow-hidden flex"
style={{
marginLeft: leftMarginPx,
marginRight: rightMarginPx,
marginRight: rightSidebarOpen
? `calc(var(--right-sidebar-width, ${rightSidebarWidth}px) + 8px)`
: rightMarginPx,
marginTop: topMarginPx,
marginBottom: bottomMarginPx,
height: `calc(100vh - ${topMarginPx + bottomMarginPx}px)`,
transition:
"margin-left 200ms linear, margin-right 200ms linear, margin-top 200ms linear",
}}
>
<div className="flex flex-col relative z-10 w-full h-full">

View File

@@ -24,7 +24,7 @@ import {
} from "lucide-react";
import { useTranslation } from "react-i18next";
import type { FileItem } from "../../../types/index.js";
import { LoadingOverlay } from "@/ui/components/LoadingOverlay";
import { SimpleLoader } from "@/ui/desktop/navigation/animations/SimpleLoader.tsx";
interface CreateIntent {
id: string;
@@ -1004,7 +1004,7 @@ export function FileManagerGrid({
tabIndex={0}
>
{dragState.type === "external" && (
<div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm z-10 pointer-events-none animate-in fade-in-0">
<div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm z-10 pointer-events-none">
<div className="text-center p-8 bg-background/95 border-2 border-dashed border-primary rounded-lg shadow-lg">
<Upload className="w-16 h-16 mx-auto mb-4 text-primary" />
<p className="text-xl font-semibold text-foreground mb-2">
@@ -1057,7 +1057,6 @@ export function FileManagerGrid({
draggable={true}
className={cn(
"group p-3 rounded-lg cursor-pointer",
"transition-all duration-150 ease-out",
"hover:bg-accent hover:text-accent-foreground hover:scale-[1.02] border-2 border-transparent",
isSelected &&
"bg-primary/20 border-primary ring-2 ring-primary/20",
@@ -1148,7 +1147,6 @@ export function FileManagerGrid({
draggable={true}
className={cn(
"flex items-center gap-3 p-2 rounded cursor-pointer",
"transition-all duration-150 ease-out",
"hover:bg-accent hover:text-accent-foreground",
isSelected && "bg-primary/20 ring-2 ring-primary/20",
dragState.target?.path === file.path &&
@@ -1322,12 +1320,7 @@ export function FileManagerGrid({
document.body,
)}
<LoadingOverlay
visible={isLoading}
minDuration={600}
message={t("common.loading")}
showLogo={true}
/>
<SimpleLoader visible={isLoading} message={t("common.loading")} />
</div>
);
}

View File

@@ -92,10 +92,14 @@ export function HostManager({
className="bg-dark-bg text-white p-4 pt-0 rounded-lg border-2 border-dark-border flex flex-col min-h-0 overflow-hidden"
style={{
marginLeft: leftMarginPx,
marginRight: rightSidebarOpen ? rightSidebarWidth + 17 : 17,
marginRight: rightSidebarOpen
? `calc(var(--right-sidebar-width, ${rightSidebarWidth}px) + 8px)`
: 17,
marginTop: topMarginPx,
marginBottom: bottomMarginPx,
height: `calc(100vh - ${topMarginPx + bottomMarginPx}px)`,
transition:
"margin-left 200ms linear, margin-right 200ms linear, margin-top 200ms linear",
}}
>
<Tabs

View File

@@ -17,7 +17,6 @@ import {
type StatsConfig,
DEFAULT_STATS_CONFIG,
} from "@/types/stats-widgets";
import { LoadingOverlay } from "@/ui/components/LoadingOverlay";
import {
CpuWidget,
MemoryWidget,
@@ -28,6 +27,7 @@ import {
SystemWidget,
LoginStatsWidget,
} from "./widgets";
import { SimpleLoader } from "@/ui/desktop/navigation/animations/SimpleLoader.tsx";
interface HostConfig {
id: number;
@@ -469,11 +469,9 @@ export function Server({
</div>
)}
<LoadingOverlay
<SimpleLoader
visible={isLoadingMetrics && !metrics}
minDuration={700}
message={t("serverStats.loadingMetrics")}
showLogo={true}
/>
</div>
)}

View File

@@ -31,7 +31,7 @@ import { useCommandTracker } from "@/ui/hooks/useCommandTracker";
import { useCommandHistory } from "@/ui/hooks/useCommandHistory";
import { CommandHistoryDialog } from "./CommandHistoryDialog";
import { CommandAutocomplete } from "./CommandAutocomplete";
import { LoadingOverlay } from "@/ui/components/LoadingOverlay";
import { SimpleLoader } from "@/ui/desktop/navigation/animations/SimpleLoader.tsx";
interface HostConfig {
id?: number;
@@ -1446,7 +1446,6 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
style={{
visibility:
isReady && !isConnecting && isFitted ? "visible" : "hidden",
opacity: isReady && !isConnecting && isFitted ? 1 : 0,
}}
onClick={() => {
if (terminal && !splitScreen) {
@@ -1494,12 +1493,10 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
onSelect={handleAutocompleteSelect}
/>
<LoadingOverlay
<SimpleLoader
visible={isConnecting}
minDuration={800}
message={t("terminal.connecting")}
backgroundColor={backgroundColor}
showLogo={true}
/>
</div>
);

View File

@@ -23,16 +23,7 @@ import {
SidebarProvider,
SidebarGroupLabel,
} from "@/components/ui/sidebar.tsx";
import {
Plus,
Play,
Edit,
Trash2,
Copy,
X,
RotateCcw,
ChevronRight,
} from "lucide-react";
import { Plus, Play, Edit, Trash2, Copy, X, RotateCcw } from "lucide-react";
import { toast } from "sonner";
import { useTranslation } from "react-i18next";
import { useConfirmation } from "@/hooks/use-confirmation.ts";
@@ -108,6 +99,14 @@ export function SSHUtilitySidebar({
const terminalTabs = tabs.filter((tab: TabData) => tab.type === "terminal");
// Initialize CSS variable on mount and when sidebar width changes
useEffect(() => {
document.documentElement.style.setProperty(
"--right-sidebar-width",
`${sidebarWidth}px`,
);
}, [sidebarWidth]);
useEffect(() => {
if (isOpen && activeTab === "snippets") {
fetchSnippets();
@@ -131,13 +130,22 @@ export function SSHUtilitySidebar({
const newWidth = Math.round(startWidthRef.current + dx);
const minWidth = 300;
const maxWidth = Math.round(window.innerWidth * 0.5);
if (newWidth >= minWidth && newWidth <= maxWidth) {
setSidebarWidth(newWidth);
} else if (newWidth < minWidth) {
setSidebarWidth(minWidth);
let finalWidth = newWidth;
if (newWidth < minWidth) {
finalWidth = minWidth;
} else if (newWidth > maxWidth) {
setSidebarWidth(maxWidth);
finalWidth = maxWidth;
}
// Update CSS variable immediately for smooth animation
document.documentElement.style.setProperty(
"--right-sidebar-width",
`${finalWidth}px`,
);
// Update React state (this will be batched/debounced naturally)
setSidebarWidth(finalWidth);
};
const handleMouseUp = () => {
@@ -156,7 +164,7 @@ export function SSHUtilitySidebar({
document.body.style.cursor = "";
document.body.style.userSelect = "";
};
}, [isResizing, sidebarWidth, setSidebarWidth]);
}, [isResizing]);
// SSH Tools handlers
const handleTabToggle = (tabId: number) => {
@@ -433,19 +441,22 @@ export function SSHUtilitySidebar({
toast.success(t("snippets.copySuccess", { name: snippet.name }));
};
if (!isOpen) return null;
return (
<>
<div className="min-h-svh">
<SidebarProvider
open={isOpen}
style={
{ "--sidebar-width": `${sidebarWidth}px` } as React.CSSProperties
}
>
<div className="flex h-screen w-full justify-end">
<Sidebar variant="floating" side="right">
{isOpen && (
<div className="fixed top-0 right-0 h-0 w-0 pointer-events-none">
<SidebarProvider
open={isOpen}
style={
{ "--sidebar-width": `${sidebarWidth}px` } as React.CSSProperties
}
className="!min-h-0 !h-0 !w-0"
>
<Sidebar
variant="floating"
side="right"
className="pointer-events-auto"
>
<SidebarHeader>
<SidebarGroupLabel className="text-lg font-bold text-white">
{t("nav.tools")}
@@ -780,24 +791,9 @@ export function SSHUtilitySidebar({
/>
)}
</Sidebar>
</div>
</SidebarProvider>
{!isOpen && (
<div
onClick={onClose}
className="fixed top-0 right-0 w-[10px] h-full cursor-pointer flex items-center justify-center rounded-tl-md rounded-bl-md"
style={{
zIndex: 9999,
backgroundColor: "#18181b",
border: "2px solid #27272a",
borderRight: "none",
}}
>
<ChevronRight size={10} />
</div>
)}
</div>
</SidebarProvider>
</div>
)}
{showDialog && (
<div