mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-27 03:41:26 +01:00
Floating sidebar refactor
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useFloatingSidebarHidden } from '../hooks/useFloatingSidebarHidden';
|
||||
import { useShouldFloatSidebar } from '../hooks/useShouldFloatSidebar';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { CreateDropdown } from './CreateDropdown';
|
||||
import { IconButton } from './core/IconButton';
|
||||
import { HStack } from './core/Stacks';
|
||||
|
||||
export function SidebarActions() {
|
||||
const floating = useShouldFloatSidebar();
|
||||
const [normalHidden, setNormalHidden] = useSidebarHidden();
|
||||
interface Props {
|
||||
floating?: boolean;
|
||||
}
|
||||
|
||||
export function SidebarActions({ floating = false }: Props) {
|
||||
const [sidebarHidden, setSidebarHidden] = useSidebarHidden();
|
||||
const [floatingHidden, setFloatingHidden] = useFloatingSidebarHidden();
|
||||
|
||||
const hidden = floating ? floatingHidden : normalHidden;
|
||||
const hidden = floating ? floatingHidden : sidebarHidden;
|
||||
const setHidden = useMemo(
|
||||
() => (floating ? setFloatingHidden : setNormalHidden),
|
||||
[floating, setFloatingHidden, setNormalHidden],
|
||||
() => (floating ? setFloatingHidden : setSidebarHidden),
|
||||
[floating, setFloatingHidden, setSidebarHidden],
|
||||
);
|
||||
|
||||
return (
|
||||
<HStack className="h-full">
|
||||
<IconButton
|
||||
onClick={async () => {
|
||||
// NOTE: We're not using the (h) => !h pattern here because the data
|
||||
// might be different if another window changed it (out of sync)
|
||||
await setHidden(!hidden);
|
||||
}}
|
||||
className="pointer-events-auto"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { type } from '@tauri-apps/plugin-os';
|
||||
import { settingsAtom, workspacesAtom } from '@yaakapp-internal/models';
|
||||
import { HeaderSize, Overlay, SidebarLayout } from '@yaakapp-internal/ui';
|
||||
import { HeaderSize, SidebarLayout } from '@yaakapp-internal/ui';
|
||||
import classNames from 'classnames';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import * as m from 'motion/react-m';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import {
|
||||
useEnsureActiveCookieJar,
|
||||
useSubscribeActiveCookieJarId,
|
||||
@@ -24,7 +24,6 @@ import { useSubscribeRecentCookieJars } from '../hooks/useRecentCookieJars';
|
||||
import { useSubscribeRecentEnvironments } from '../hooks/useRecentEnvironments';
|
||||
import { useSubscribeRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useSubscribeRecentWorkspaces } from '../hooks/useRecentWorkspaces';
|
||||
import { useShouldFloatSidebar } from '../hooks/useShouldFloatSidebar';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
||||
import { useSyncWorkspaceRequestTitle } from '../hooks/useSyncWorkspaceRequestTitle';
|
||||
@@ -55,11 +54,11 @@ export function Workspace() {
|
||||
const workspaces = useAtomValue(workspacesAtom);
|
||||
const settings = useAtomValue(settingsAtom);
|
||||
const osType = type();
|
||||
const [width, setWidth, resetWidth] = useSidebarWidth();
|
||||
const [width, setWidth] = useSidebarWidth();
|
||||
const [sidebarHidden, setSidebarHidden] = useSidebarHidden();
|
||||
const [floatingSidebarHidden, setFloatingSidebarHidden] = useFloatingSidebarHidden();
|
||||
const activeEnvironment = useAtomValue(activeEnvironmentAtom);
|
||||
const floating = useShouldFloatSidebar();
|
||||
const [floating, setFloating] = useState(false);
|
||||
|
||||
const environmentBgStyle = useMemo(() => {
|
||||
if (activeEnvironment?.color == null) return undefined;
|
||||
@@ -89,7 +88,7 @@ export function Workspace() {
|
||||
className="absolute left-0 right-0 -bottom-[1px] h-[1px] opacity-20"
|
||||
/>
|
||||
</div>
|
||||
<WorkspaceHeader className="pointer-events-none" />
|
||||
<WorkspaceHeader className="pointer-events-none" floatingSidebar={floating} />
|
||||
</HeaderSize>
|
||||
);
|
||||
|
||||
@@ -99,7 +98,30 @@ export function Workspace() {
|
||||
</ErrorBoundary>
|
||||
);
|
||||
|
||||
const sidebarContent = (
|
||||
const sidebarContent = floating ? (
|
||||
<div
|
||||
className={classNames(
|
||||
'x-theme-sidebar',
|
||||
'h-full bg-surface border-r border-border-subtle',
|
||||
'grid grid-rows-[auto_1fr]',
|
||||
)}
|
||||
>
|
||||
<HeaderSize
|
||||
hideControls
|
||||
size="lg"
|
||||
className="border-transparent flex items-center"
|
||||
osType={osType}
|
||||
hideWindowControls={settings.hideWindowControls}
|
||||
useNativeTitlebar={settings.useNativeTitlebar}
|
||||
interfaceScale={settings.interfaceScale}
|
||||
>
|
||||
<SidebarActions floating />
|
||||
</HeaderSize>
|
||||
<ErrorBoundary name="Sidebar (Floating)">
|
||||
<Sidebar />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
) : (
|
||||
<div className="x-theme-sidebar overflow-hidden bg-surface h-full">
|
||||
<ErrorBoundary name="Sidebar">
|
||||
<Sidebar className="border-r border-border-subtle" />
|
||||
@@ -110,52 +132,18 @@ export function Workspace() {
|
||||
return (
|
||||
<div className="grid w-full h-full grid-rows-[auto_1fr]">
|
||||
{header}
|
||||
{floating ? (
|
||||
<>
|
||||
<Overlay
|
||||
open={!floatingSidebarHidden}
|
||||
portalName="sidebar"
|
||||
onClose={() => setFloatingSidebarHidden(true)}
|
||||
zIndex={20}
|
||||
>
|
||||
<m.div
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
className={classNames(
|
||||
'x-theme-sidebar',
|
||||
'absolute top-0 left-0 bottom-0 bg-surface border-r border-border-subtle w-[20rem]',
|
||||
'grid grid-rows-[auto_1fr]',
|
||||
)}
|
||||
>
|
||||
<HeaderSize
|
||||
hideControls
|
||||
size="lg"
|
||||
className="border-transparent flex items-center"
|
||||
osType={osType}
|
||||
hideWindowControls={settings.hideWindowControls}
|
||||
useNativeTitlebar={settings.useNativeTitlebar}
|
||||
interfaceScale={settings.interfaceScale}
|
||||
>
|
||||
<SidebarActions />
|
||||
</HeaderSize>
|
||||
<ErrorBoundary name="Sidebar (Floating)">
|
||||
<Sidebar />
|
||||
</ErrorBoundary>
|
||||
</m.div>
|
||||
</Overlay>
|
||||
{workspaceBody}
|
||||
</>
|
||||
) : (
|
||||
<SidebarLayout
|
||||
width={width ?? 250}
|
||||
onWidthChange={setWidth}
|
||||
hidden={sidebarHidden ?? false}
|
||||
onHiddenChange={(hidden) => setSidebarHidden(hidden)}
|
||||
sidebar={sidebarContent}
|
||||
>
|
||||
{workspaceBody}
|
||||
</SidebarLayout>
|
||||
)}
|
||||
<SidebarLayout
|
||||
width={width ?? 250}
|
||||
onWidthChange={setWidth}
|
||||
hidden={sidebarHidden ?? false}
|
||||
onHiddenChange={(hidden) => setSidebarHidden(hidden)}
|
||||
floatingHidden={floatingSidebarHidden ?? true}
|
||||
onFloatingHiddenChange={(hidden) => setFloatingSidebarHidden(hidden)}
|
||||
onFloatingChange={setFloating}
|
||||
sidebar={sidebarContent}
|
||||
>
|
||||
{workspaceBody}
|
||||
</SidebarLayout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@ import { WorkspaceActionsDropdown } from './WorkspaceActionsDropdown';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
floatingSidebar?: boolean;
|
||||
}
|
||||
|
||||
export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) {
|
||||
export const WorkspaceHeader = memo(function WorkspaceHeader({ className, floatingSidebar }: Props) {
|
||||
const togglePalette = useToggleCommandPalette();
|
||||
const [workspaceLayout, setWorkspaceLayout] = useAtom(workspaceLayoutAtom);
|
||||
const workspace = useAtomValue(activeWorkspaceAtom);
|
||||
@@ -41,7 +42,7 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
|
||||
)}
|
||||
>
|
||||
<HStack space={0.5} className={classNames('flex-1 pointer-events-none')}>
|
||||
<SidebarActions />
|
||||
<SidebarActions floating={floatingSidebar} />
|
||||
<CookieDropdown />
|
||||
<HStack className="min-w-0">
|
||||
<WorkspaceActionsDropdown />
|
||||
|
||||
Reference in New Issue
Block a user