feat(ui): panel resize handles have grab icon

This commit is contained in:
psychedelicious
2025-02-20 17:30:15 +10:00
parent e3069ad336
commit 871cb54988
5 changed files with 76 additions and 34 deletions

View File

@@ -4,7 +4,7 @@ import { useFocusRegion } from 'common/hooks/focus';
import { GalleryHeader } from 'features/gallery/components/GalleryHeader';
import { selectBoardSearchText } from 'features/gallery/store/gallerySelectors';
import { boardSearchTextChanged } from 'features/gallery/store/gallerySlice';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import { HorizontalResizeHandle } from 'features/ui/components/tabs/ResizeHandle';
import { usePanel, type UsePanelOptions } from 'features/ui/hooks/usePanel';
import type { CSSProperties } from 'react';
import { memo, useCallback, useMemo, useRef } from 'react';
@@ -94,7 +94,7 @@ const GalleryPanelContent = () => {
<BoardsListWrapper />
</Flex>
</Panel>
<ResizeHandle id="gallery-panel-handle" {...boardsListPanel.resizeHandleProps} />
<HorizontalResizeHandle id="gallery-panel-handle" {...boardsListPanel.resizeHandleProps} />
<Panel id="gallery-wrapper-panel" minSize={20}>
<Gallery />
</Panel>

View File

@@ -1,7 +1,7 @@
import { Flex, Image } from '@invoke-ai/ui-library';
import type { ComparisonProps } from 'features/gallery/components/ImageViewer/common';
import { ImageComparisonLabel } from 'features/gallery/components/ImageViewer/ImageComparisonLabel';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import { VerticalResizeHandle } from 'features/ui/components/tabs/ResizeHandle';
import { memo, useCallback, useRef } from 'react';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
@@ -42,7 +42,7 @@ export const ImageComparisonSideBySide = memo(({ firstImage, secondImage }: Comp
</Flex>
</Flex>
</Panel>
<ResizeHandle id="image-comparison-side-by-side-handle" onDoubleClick={onDoubleClickHandle} />
<VerticalResizeHandle id="image-comparison-side-by-side-handle" onDoubleClick={onDoubleClickHandle} />
<Panel minSize={20}>
<Flex position="relative" w="full" h="full" alignItems="center" justifyContent="center">

View File

@@ -1,7 +1,7 @@
import { Box } from '@invoke-ai/ui-library';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import { ViewContextProvider } from 'features/nodes/contexts/ViewContext';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import { HorizontalResizeHandle } from 'features/ui/components/tabs/ResizeHandle';
import type { CSSProperties } from 'react';
import { memo, useCallback, useRef } from 'react';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
@@ -36,7 +36,7 @@ export const EditModeLeftPanelContent = memo(() => {
<Panel id="workflow" collapsible minSize={25}>
<WorkflowFieldsLinearViewPanel />
</Panel>
<ResizeHandle onDoubleClick={handleDoubleClickHandle} />
<HorizontalResizeHandle onDoubleClick={handleDoubleClickHandle} />
<Panel id="inspector" collapsible minSize={25}>
<WorkflowNodeInspectorPanel />
</Panel>

View File

@@ -32,7 +32,7 @@ import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
import ParametersPanelUpscale from './ParametersPanels/ParametersPanelUpscale';
import ResizeHandle from './tabs/ResizeHandle';
import { VerticalResizeHandle } from './tabs/ResizeHandle';
const panelStyles: CSSProperties = { position: 'relative', height: '100%', width: '100%', minWidth: 0 };
@@ -136,7 +136,7 @@ export const AppContent = memo(() => {
</Box>
</Flex>
</Panel>
<ResizeHandle id="left-main-handle" {...leftPanel.resizeHandleProps} />
<VerticalResizeHandle id="left-main-handle" {...leftPanel.resizeHandleProps} />
</>
)}
<Panel id="main-panel" order={1} minSize={20} style={panelStyles}>
@@ -146,7 +146,7 @@ export const AppContent = memo(() => {
</Panel>
{withRightPanel && (
<>
<ResizeHandle id="main-right-handle" {...rightPanel.resizeHandleProps} />
<VerticalResizeHandle id="main-right-handle" {...rightPanel.resizeHandleProps} />
<Panel order={2} style={panelStyles} collapsible {...rightPanel.panelProps}>
<RightPanelContent />
</Panel>

View File

@@ -1,28 +1,75 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { chakra } from '@invoke-ai/ui-library';
import { chakra, Flex, Icon } from '@invoke-ai/ui-library';
import { memo } from 'react';
import { PiDotsSix, PiDotsSixVertical } from 'react-icons/pi';
import type { PanelResizeHandleProps } from 'react-resizable-panels';
import { PanelResizeHandle } from 'react-resizable-panels';
const ChakraPanelResizeHandle = chakra(PanelResizeHandle);
const ResizeHandle = (props: Omit<PanelResizeHandleProps, 'style'>) => {
return <ChakraPanelResizeHandle {...props} sx={sx} />;
};
export default memo(ResizeHandle);
const sx: SystemStyleObject = {
const commonSx: SystemStyleObject = {
'&[data-resize-handle-state="hover"]': {
_before: {
background: 'base.600 !important',
},
'.resize-handle-dots': {
color: 'base.400',
},
},
'&[data-resize-handle-state="drag"]': {
_before: {
background: 'base.500 !important',
},
'.resize-handle-dots': {
color: 'base.300',
},
},
'.resize-handle-dots': {
pointerEvents: 'none',
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%) scale(0.75)',
background: 'base.900',
color: 'base.500',
},
};
const horizontalSx: SystemStyleObject = {
...commonSx,
'&[data-panel-group-direction="vertical"]': {
h: 4,
w: 'full',
position: 'relative',
_before: {
transitionProperty: 'background',
transitionDuration: 'fast',
content: '""',
w: 'full',
h: '2px',
background: 'base.800',
position: 'absolute',
top: '50%',
left: 0,
transform: 'translateY(-50%)',
},
},
};
export const HorizontalResizeHandle = memo((props: Omit<PanelResizeHandleProps, 'style'>) => {
return (
<ChakraPanelResizeHandle {...props} sx={horizontalSx}>
<Flex className="resize-handle-dots" clipPath="inset(0px 2px 2px 0px)" px={1}>
<Icon as={PiDotsSix} me={-0.5} />
<Icon as={PiDotsSix} ms={-0.5} />
</Flex>
</ChakraPanelResizeHandle>
);
});
HorizontalResizeHandle.displayName = 'HorizontalResizeHandle';
const verticalSx: SystemStyleObject = {
...commonSx,
'&[data-panel-group-direction="horizontal"]': {
w: 4,
h: 'full',
@@ -40,21 +87,16 @@ const sx: SystemStyleObject = {
transform: 'translateX(-50%)',
},
},
'&[data-panel-group-direction="vertical"]': {
h: 4,
w: 'full',
position: 'relative',
_before: {
transitionProperty: 'background',
transitionDuration: 'normal',
content: '""',
w: 'full',
h: '2px',
background: 'base.800',
position: 'absolute',
top: '50%',
left: 0,
transform: 'translateY(-50%)',
},
},
};
export const VerticalResizeHandle = memo((props: Omit<PanelResizeHandleProps, 'style'>) => {
return (
<ChakraPanelResizeHandle {...props} sx={verticalSx}>
<Flex flexDir="column" className="resize-handle-dots" clipPath="inset(2px 0px 0px 2px)" py={1}>
<Icon as={PiDotsSixVertical} mb={-0.5} />
<Icon as={PiDotsSixVertical} mt={-0.5} />
</Flex>
</ChakraPanelResizeHandle>
);
});
VerticalResizeHandle.displayName = 'VerticalResizeHandle';