Skip to content

Commit 23fada3

Browse files
feat(ui): simpler dnd indicator for right panel tabs
We can use the drop overlay component directly for this, without needing to add it as a `noop` dnd target. Other changes: - The `label` prop is now used to conditionally render the label - every drop target provides its own label, so this doesn't break anything. - Add `withBackdrop` prop to control whether we apply the dimmed drop target effect.
1 parent 2917e59 commit 23fada3

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { Flex, Text } from '@invoke-ai/ui-library';
22
import { memo } from 'react';
3-
import { useTranslation } from 'react-i18next';
43

54
type Props = {
65
isOver: boolean;
76
label?: string;
7+
withBackdrop?: boolean;
88
};
99

1010
const IAIDropOverlay = (props: Props) => {
11-
const { t } = useTranslation();
12-
const { isOver, label = t('gallery.drop') } = props;
11+
const { isOver, label, withBackdrop = true } = props;
1312
return (
1413
<Flex position="absolute" top={0} right={0} bottom={0} left={0}>
1514
<Flex
@@ -20,7 +19,7 @@ const IAIDropOverlay = (props: Props) => {
2019
left={0}
2120
w="full"
2221
h="full"
23-
bg="base.900"
22+
bg={withBackdrop ? 'base.900' : 'transparent'}
2423
opacity={0.7}
2524
borderRadius="base"
2625
alignItems="center"
@@ -45,16 +44,18 @@ const IAIDropOverlay = (props: Props) => {
4544
alignItems="center"
4645
justifyContent="center"
4746
>
48-
<Text
49-
fontSize="lg"
50-
fontWeight="semibold"
51-
color={isOver ? 'invokeYellow.300' : 'base.500'}
52-
transitionProperty="common"
53-
transitionDuration="0.1s"
54-
textAlign="center"
55-
>
56-
{label}
57-
</Text>
47+
{label && (
48+
<Text
49+
fontSize="lg"
50+
fontWeight="semibold"
51+
color={isOver ? 'invokeYellow.300' : 'base.500'}
52+
transitionProperty="common"
53+
transitionDuration="0.1s"
54+
textAlign="center"
55+
>
56+
{label}
57+
</Text>
58+
)}
5859
</Flex>
5960
</Flex>
6061
);

invokeai/frontend/web/src/features/controlLayers/components/CanvasRightPanel.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useDndContext } from '@dnd-kit/core';
22
import { Box, Button, Spacer, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
33
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
4+
import IAIDropOverlay from 'common/components/IAIDropOverlay';
45
import { CanvasLayersPanelContent } from 'features/controlLayers/components/CanvasLayersPanelContent';
56
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
67
import { selectEntityCountActive } from 'features/controlLayers/store/selectors';
@@ -9,7 +10,7 @@ import { useImageViewer } from 'features/gallery/components/ImageViewer/useImage
910
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
1011
import { selectActiveTabCanvasRightPanel } from 'features/ui/store/uiSelectors';
1112
import { activeTabCanvasRightPanelChanged } from 'features/ui/store/uiSlice';
12-
import { memo, useCallback, useMemo, useRef } from 'react';
13+
import { memo, useCallback, useMemo, useRef, useState } from 'react';
1314
import { useTranslation } from 'react-i18next';
1415

1516
export const CanvasRightPanel = memo(() => {
@@ -78,12 +79,15 @@ CanvasRightPanel.displayName = 'CanvasRightPanel';
7879

7980
const PanelTabs = memo(() => {
8081
const { t } = useTranslation();
82+
const activeTab = useAppSelector(selectActiveTabCanvasRightPanel);
8183
const activeEntityCount = useAppSelector(selectEntityCountActive);
8284
const tabTimeout = useRef<number | null>(null);
8385
const dndCtx = useDndContext();
8486
const dispatch = useAppDispatch();
87+
const [mouseOverTab, setMouseOverTab] = useState<'layers' | 'gallery' | null>(null);
8588

8689
const onOnMouseOverLayersTab = useCallback(() => {
90+
setMouseOverTab('layers');
8791
tabTimeout.current = window.setTimeout(() => {
8892
if (dndCtx.active) {
8993
dispatch(activeTabCanvasRightPanelChanged('layers'));
@@ -92,6 +96,7 @@ const PanelTabs = memo(() => {
9296
}, [dndCtx.active, dispatch]);
9397

9498
const onOnMouseOverGalleryTab = useCallback(() => {
99+
setMouseOverTab('gallery');
95100
tabTimeout.current = window.setTimeout(() => {
96101
if (dndCtx.active) {
97102
dispatch(activeTabCanvasRightPanelChanged('gallery'));
@@ -100,6 +105,7 @@ const PanelTabs = memo(() => {
100105
}, [dndCtx.active, dispatch]);
101106

102107
const onMouseOut = useCallback(() => {
108+
setMouseOverTab(null);
103109
if (tabTimeout.current) {
104110
clearTimeout(tabTimeout.current);
105111
}
@@ -118,9 +124,17 @@ const PanelTabs = memo(() => {
118124
<Box as="span" w="full">
119125
{layersTabLabel}
120126
</Box>
127+
{dndCtx.active && activeTab !== 'layers' && (
128+
<IAIDropOverlay isOver={mouseOverTab === 'layers'} withBackdrop={false} />
129+
)}
121130
</Tab>
122-
<Tab position="relative" onMouseOver={onOnMouseOverGalleryTab} onMouseOut={onMouseOut}>
123-
{t('gallery.gallery')}
131+
<Tab position="relative" onMouseOver={onOnMouseOverGalleryTab} onMouseOut={onMouseOut} w={32}>
132+
<Box as="span" w="full">
133+
{t('gallery.gallery')}
134+
</Box>
135+
{dndCtx.active && activeTab !== 'gallery' && (
136+
<IAIDropOverlay isOver={mouseOverTab === 'gallery'} withBackdrop={false} />
137+
)}
124138
</Tab>
125139
</>
126140
);

0 commit comments

Comments
 (0)