Skip to content

Commit 19b6dc1

Browse files
cursoragenthipsterusername
authored andcommitted
Add custom Launchpad tab with dynamic icon based on active tab
Co-authored-by: kent <kent@invoke.ai>
1 parent 7566d0d commit 19b6dc1

File tree

6 files changed

+72
-4
lines changed

6 files changed

+72
-4
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Flex, Text } from '@invoke-ai/ui-library';
2+
import { useAppSelector } from 'app/store/storeHooks';
3+
import { useCallbackOnDragEnter } from 'common/hooks/useCallbackOnDragEnter';
4+
import type { IDockviewPanelHeaderProps } from 'dockview';
5+
import { selectActiveTab } from 'features/ui/store/uiSelectors';
6+
import type { TabName } from 'features/ui/store/uiTypes';
7+
import { memo, useCallback, useRef } from 'react';
8+
import {
9+
PiBoundingBoxBold,
10+
PiCubeBold,
11+
PiFlowArrowBold,
12+
PiFrameCornersBold,
13+
PiQueueBold,
14+
PiTextAaBold,
15+
} from 'react-icons/pi';
16+
17+
const TAB_ICONS: Record<TabName, React.ReactElement> = {
18+
generate: <PiTextAaBold />,
19+
canvas: <PiBoundingBoxBold />,
20+
upscaling: <PiFrameCornersBold />,
21+
workflows: <PiFlowArrowBold />,
22+
models: <PiCubeBold />,
23+
queue: <PiQueueBold />,
24+
};
25+
26+
export const TabWithLaunchpadIcon = memo((props: IDockviewPanelHeaderProps) => {
27+
const ref = useRef<HTMLDivElement>(null);
28+
const activeTab = useAppSelector(selectActiveTab);
29+
30+
const setActive = useCallback(() => {
31+
if (!props.api.isActive) {
32+
props.api.setActive();
33+
}
34+
}, [props.api]);
35+
36+
useCallbackOnDragEnter(setActive, ref, 300);
37+
38+
// Show icon only for Launchpad panel
39+
const isLaunchpadPanel = props.api.id === 'launchpad';
40+
const currentTabIcon = TAB_ICONS[activeTab];
41+
42+
return (
43+
<Flex ref={ref} alignItems="center" h="full">
44+
{isLaunchpadPanel && currentTabIcon && (
45+
<Flex alignItems="center" px={2}>
46+
{currentTabIcon}
47+
</Flex>
48+
)}
49+
<Text userSelect="none" px={isLaunchpadPanel ? 2 : 4}>
50+
{props.api.title ?? props.api.id}
51+
</Text>
52+
</Flex>
53+
);
54+
});
55+
TabWithLaunchpadIcon.displayName = 'TabWithLaunchpadIcon';

invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,19 @@ import {
3333
RIGHT_PANEL_ID,
3434
RIGHT_PANEL_MIN_SIZE_PX,
3535
SETTINGS_PANEL_ID,
36+
TAB_WITH_LAUNCHPAD_ICON_ID,
3637
TAB_WITH_PROGRESS_INDICATOR_ID,
3738
VIEWER_PANEL_ID,
3839
WORKSPACE_PANEL_ID,
3940
} from './shared';
41+
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
4042
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
4143
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
4244

4345
const tabComponents = {
4446
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
4547
[TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator,
48+
[TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon,
4649
};
4750

4851
const centerPanelComponents: IDockviewReactProps['components'] = {
@@ -57,7 +60,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => {
5760
id: LAUNCHPAD_PANEL_ID,
5861
component: LAUNCHPAD_PANEL_ID,
5962
title: 'Launchpad',
60-
tabComponent: DEFAULT_TAB_ID,
63+
tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID,
6164
});
6265
api.addPanel({
6366
id: WORKSPACE_PANEL_ID,

invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@ import {
2929
RIGHT_PANEL_ID,
3030
RIGHT_PANEL_MIN_SIZE_PX,
3131
SETTINGS_PANEL_ID,
32+
TAB_WITH_LAUNCHPAD_ICON_ID,
3233
TAB_WITH_PROGRESS_INDICATOR_ID,
3334
VIEWER_PANEL_ID,
3435
} from './shared';
36+
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
3537
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
3638
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
3739

3840
const tabComponents = {
3941
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
4042
[TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator,
43+
[TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon,
4144
};
4245

4346
const centerPanelComponents: IDockviewReactProps['components'] = {
@@ -51,7 +54,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => {
5154
id: LAUNCHPAD_PANEL_ID,
5255
component: LAUNCHPAD_PANEL_ID,
5356
title: 'Launchpad',
54-
tabComponent: DEFAULT_TAB_ID,
57+
tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID,
5558
});
5659
api.addPanel({
5760
id: VIEWER_PANEL_ID,

invokeai/frontend/web/src/features/ui/layouts/shared.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const SETTINGS_PANEL_ID = 'settings';
1515

1616
export const DEFAULT_TAB_ID = 'default-tab';
1717
export const TAB_WITH_PROGRESS_INDICATOR_ID = 'tab-with-progress-indicator';
18+
export const TAB_WITH_LAUNCHPAD_ICON_ID = 'tab-with-launchpad-icon';
1819

1920
export const LEFT_PANEL_MIN_SIZE_PX = 420;
2021
export const RIGHT_PANEL_MIN_SIZE_PX = 420;

invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,19 @@ import {
2828
RIGHT_PANEL_ID,
2929
RIGHT_PANEL_MIN_SIZE_PX,
3030
SETTINGS_PANEL_ID,
31+
TAB_WITH_LAUNCHPAD_ICON_ID,
3132
TAB_WITH_PROGRESS_INDICATOR_ID,
3233
VIEWER_PANEL_ID,
3334
} from './shared';
35+
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
3436
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
3537
import { UpscalingTabLeftPanel } from './UpscalingTabLeftPanel';
3638
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
3739

3840
const tabComponents = {
3941
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
4042
[TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator,
43+
[TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon,
4144
};
4245

4346
const centerComponents: IDockviewReactProps['components'] = {
@@ -51,7 +54,7 @@ const initializeCenterLayout = (api: DockviewApi) => {
5154
id: LAUNCHPAD_PANEL_ID,
5255
component: LAUNCHPAD_PANEL_ID,
5356
title: 'Launchpad',
54-
tabComponent: DEFAULT_TAB_ID,
57+
tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID,
5558
});
5659
api.addPanel({
5760
id: VIEWER_PANEL_ID,

invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,19 @@ import {
3030
RIGHT_PANEL_ID,
3131
RIGHT_PANEL_MIN_SIZE_PX,
3232
SETTINGS_PANEL_ID,
33+
TAB_WITH_LAUNCHPAD_ICON_ID,
3334
TAB_WITH_PROGRESS_INDICATOR_ID,
3435
VIEWER_PANEL_ID,
3536
WORKSPACE_PANEL_ID,
3637
} from './shared';
38+
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
3739
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
3840
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
3941

4042
const tabComponents = {
4143
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
4244
[TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator,
45+
[TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon,
4346
};
4447

4548
const centerPanelComponents: IDockviewReactProps['components'] = {
@@ -54,7 +57,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => {
5457
id: LAUNCHPAD_PANEL_ID,
5558
component: LAUNCHPAD_PANEL_ID,
5659
title: 'Launchpad',
57-
tabComponent: DEFAULT_TAB_ID,
60+
tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID,
5861
});
5962
api.addPanel({
6063
id: WORKSPACE_PANEL_ID,

0 commit comments

Comments
 (0)