diff --git a/invokeai/frontend/web/src/features/ui/layouts/TabWithLaunchpadIcon.tsx b/invokeai/frontend/web/src/features/ui/layouts/TabWithLaunchpadIcon.tsx new file mode 100644 index 0000000000..3dd0c1297e --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/layouts/TabWithLaunchpadIcon.tsx @@ -0,0 +1,55 @@ +import { Flex, Text } from '@invoke-ai/ui-library'; +import { useAppSelector } from 'app/store/storeHooks'; +import { useCallbackOnDragEnter } from 'common/hooks/useCallbackOnDragEnter'; +import type { IDockviewPanelHeaderProps } from 'dockview'; +import { selectActiveTab } from 'features/ui/store/uiSelectors'; +import type { TabName } from 'features/ui/store/uiTypes'; +import { memo, useCallback, useRef } from 'react'; +import { + PiBoundingBoxBold, + PiCubeBold, + PiFlowArrowBold, + PiFrameCornersBold, + PiQueueBold, + PiTextAaBold, +} from 'react-icons/pi'; + +const TAB_ICONS: Record = { + generate: , + canvas: , + upscaling: , + workflows: , + models: , + queue: , +}; + +export const TabWithLaunchpadIcon = memo((props: IDockviewPanelHeaderProps) => { + const ref = useRef(null); + const activeTab = useAppSelector(selectActiveTab); + + const setActive = useCallback(() => { + if (!props.api.isActive) { + props.api.setActive(); + } + }, [props.api]); + + useCallbackOnDragEnter(setActive, ref, 300); + + // Show icon only for Launchpad panel + const isLaunchpadPanel = props.api.id === 'launchpad'; + const currentTabIcon = TAB_ICONS[activeTab]; + + return ( + + {isLaunchpadPanel && currentTabIcon && ( + + {currentTabIcon} + + )} + + {props.api.title ?? props.api.id} + + + ); +}); +TabWithLaunchpadIcon.displayName = 'TabWithLaunchpadIcon'; diff --git a/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx index 8f294eba6c..62122fb00e 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx +++ b/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx @@ -33,16 +33,19 @@ import { RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX, SETTINGS_PANEL_ID, + TAB_WITH_LAUNCHPAD_ICON_ID, TAB_WITH_PROGRESS_INDICATOR_ID, VIEWER_PANEL_ID, WORKSPACE_PANEL_ID, } from './shared'; +import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon'; import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator'; import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible'; const tabComponents = { [DEFAULT_TAB_ID]: TabWithoutCloseButton, [TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator, + [TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon, }; const centerPanelComponents: IDockviewReactProps['components'] = { @@ -57,7 +60,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => { id: LAUNCHPAD_PANEL_ID, component: LAUNCHPAD_PANEL_ID, title: 'Launchpad', - tabComponent: DEFAULT_TAB_ID, + tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID, }); api.addPanel({ id: WORKSPACE_PANEL_ID, diff --git a/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx index c877a1fd88..f2209bdfbf 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx +++ b/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx @@ -29,15 +29,18 @@ import { RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX, SETTINGS_PANEL_ID, + TAB_WITH_LAUNCHPAD_ICON_ID, TAB_WITH_PROGRESS_INDICATOR_ID, VIEWER_PANEL_ID, } from './shared'; +import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon'; import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator'; import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible'; const tabComponents = { [DEFAULT_TAB_ID]: TabWithoutCloseButton, [TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator, + [TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon, }; const centerPanelComponents: IDockviewReactProps['components'] = { @@ -51,7 +54,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => { id: LAUNCHPAD_PANEL_ID, component: LAUNCHPAD_PANEL_ID, title: 'Launchpad', - tabComponent: DEFAULT_TAB_ID, + tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID, }); api.addPanel({ id: VIEWER_PANEL_ID, diff --git a/invokeai/frontend/web/src/features/ui/layouts/shared.ts b/invokeai/frontend/web/src/features/ui/layouts/shared.ts index 57363994d6..cc2b2dffd1 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/shared.ts +++ b/invokeai/frontend/web/src/features/ui/layouts/shared.ts @@ -15,6 +15,7 @@ export const SETTINGS_PANEL_ID = 'settings'; export const DEFAULT_TAB_ID = 'default-tab'; export const TAB_WITH_PROGRESS_INDICATOR_ID = 'tab-with-progress-indicator'; +export const TAB_WITH_LAUNCHPAD_ICON_ID = 'tab-with-launchpad-icon'; export const LEFT_PANEL_MIN_SIZE_PX = 420; export const RIGHT_PANEL_MIN_SIZE_PX = 420; diff --git a/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx index 969ddeb8b1..d29ce99711 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx +++ b/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx @@ -28,9 +28,11 @@ import { RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX, SETTINGS_PANEL_ID, + TAB_WITH_LAUNCHPAD_ICON_ID, TAB_WITH_PROGRESS_INDICATOR_ID, VIEWER_PANEL_ID, } from './shared'; +import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon'; import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator'; import { UpscalingTabLeftPanel } from './UpscalingTabLeftPanel'; import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible'; @@ -38,6 +40,7 @@ import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible'; const tabComponents = { [DEFAULT_TAB_ID]: TabWithoutCloseButton, [TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator, + [TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon, }; const centerComponents: IDockviewReactProps['components'] = { @@ -51,7 +54,7 @@ const initializeCenterLayout = (api: DockviewApi) => { id: LAUNCHPAD_PANEL_ID, component: LAUNCHPAD_PANEL_ID, title: 'Launchpad', - tabComponent: DEFAULT_TAB_ID, + tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID, }); api.addPanel({ id: VIEWER_PANEL_ID, diff --git a/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx index 323b803fe8..d23ff07a61 100644 --- a/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx +++ b/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx @@ -30,16 +30,19 @@ import { RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX, SETTINGS_PANEL_ID, + TAB_WITH_LAUNCHPAD_ICON_ID, TAB_WITH_PROGRESS_INDICATOR_ID, VIEWER_PANEL_ID, WORKSPACE_PANEL_ID, } from './shared'; +import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon'; import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator'; import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible'; const tabComponents = { [DEFAULT_TAB_ID]: TabWithoutCloseButton, [TAB_WITH_PROGRESS_INDICATOR_ID]: TabWithoutCloseButtonAndWithProgressIndicator, + [TAB_WITH_LAUNCHPAD_ICON_ID]: TabWithLaunchpadIcon, }; const centerPanelComponents: IDockviewReactProps['components'] = { @@ -54,7 +57,7 @@ const initializeCenterPanelLayout = (api: DockviewApi) => { id: LAUNCHPAD_PANEL_ID, component: LAUNCHPAD_PANEL_ID, title: 'Launchpad', - tabComponent: DEFAULT_TAB_ID, + tabComponent: TAB_WITH_LAUNCHPAD_ICON_ID, }); api.addPanel({ id: WORKSPACE_PANEL_ID,