From 193de6a8f2b5a349573d44b98cd53d666366377e Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 8 Jul 2025 07:15:47 +1000 Subject: [PATCH] feat(ui): add launchpad container component --- .../SimpleSession/CanvasLaunchpadPanel.tsx | 54 +++-- .../SimpleSession/GenerateLaunchpadPanel.tsx | 64 +++--- .../SimpleSession/LaunchpadContainer.tsx | 17 ++ .../SimpleSession/UpscalingLaunchpadPanel.tsx | 197 +++++++++--------- .../SimpleSession/WorkflowsLaunchpadPanel.tsx | 101 +++++---- 5 files changed, 218 insertions(+), 215 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/LaunchpadContainer.tsx diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/CanvasLaunchpadPanel.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/CanvasLaunchpadPanel.tsx index 367c71cc4a..0d2f826781 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/CanvasLaunchpadPanel.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/CanvasLaunchpadPanel.tsx @@ -1,4 +1,4 @@ -import { Button, Flex, Grid, Heading, Text } from '@invoke-ai/ui-library'; +import { Button, Flex, Grid, Text } from '@invoke-ai/ui-library'; import { navigationApi } from 'features/ui/layouts/navigation-api'; import { WORKSPACE_PANEL_ID } from 'features/ui/layouts/shared'; import { memo, useCallback } from 'react'; @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import { InitialStateMainModelPicker } from './InitialStateMainModelPicker'; import { LaunchpadAddStyleReference } from './LaunchpadAddStyleReference'; +import { LaunchpadContainer } from './LaunchpadContainer'; import { LaunchpadEditImageButton } from './LaunchpadEditImageButton'; import { LaunchpadGenerateFromTextButton } from './LaunchpadGenerateFromTextButton'; import { LaunchpadUseALayoutImageButton } from './LaunchpadUseALayoutImageButton'; @@ -16,35 +17,30 @@ export const CanvasLaunchpadPanel = memo(() => { navigationApi.focusPanel('canvas', WORKSPACE_PANEL_ID); }, []); return ( - - - {t('ui.launchpad.canvasTitle')} - - - - - - {t('ui.launchpad.modelGuideText')}{' '} - - - - - - - - + + + + + + {t('ui.launchpad.modelGuideText')}{' '} + + - - + + + + + + ); }); CanvasLaunchpadPanel.displayName = 'CanvasLaunchpadPanel'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel.tsx index bbd2f4b07b..dd7160cb43 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel.tsx @@ -1,9 +1,10 @@ -import { Alert, Button, Flex, Grid, Heading, Text } from '@invoke-ai/ui-library'; +import { Alert, Button, Flex, Grid, Text } from '@invoke-ai/ui-library'; import { InitialStateMainModelPicker } from 'features/controlLayers/components/SimpleSession/InitialStateMainModelPicker'; import { LaunchpadAddStyleReference } from 'features/controlLayers/components/SimpleSession/LaunchpadAddStyleReference'; import { navigationApi } from 'features/ui/layouts/navigation-api'; import { memo, useCallback } from 'react'; +import { LaunchpadContainer } from './LaunchpadContainer'; import { LaunchpadGenerateFromTextButton } from './LaunchpadGenerateFromTextButton'; export const GenerateLaunchpadPanel = memo(() => { @@ -12,41 +13,36 @@ export const GenerateLaunchpadPanel = memo(() => { }, []); return ( - - - Generate images from text prompts. - - - - - - Want to learn what prompts work best for each model?{' '} - - - - - - - - - Looking to get more control, edit, and iterate on your images? - - - + - - + + + + + + Looking to get more control, edit, and iterate on your images? + + + + ); }); GenerateLaunchpadPanel.displayName = 'GenerateLaunchpad'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/LaunchpadContainer.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/LaunchpadContainer.tsx new file mode 100644 index 0000000000..332e7d75fa --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/LaunchpadContainer.tsx @@ -0,0 +1,17 @@ +import { Flex, Heading } from '@invoke-ai/ui-library'; +import type { PropsWithChildren } from 'react'; +import { memo } from 'react'; + +export const LaunchpadContainer = memo((props: PropsWithChildren<{ heading: string }>) => { + return ( + + + {props.heading} + + {props.children} + + + + ); +}); +LaunchpadContainer.displayName = 'LaunchpadContainer'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/UpscalingLaunchpadPanel.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/UpscalingLaunchpadPanel.tsx index f78e8ac646..496663064b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/UpscalingLaunchpadPanel.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/UpscalingLaunchpadPanel.tsx @@ -24,6 +24,7 @@ import { import type { ImageDTO } from 'services/api/types'; import { LaunchpadButton } from './LaunchpadButton'; +import { LaunchpadContainer } from './LaunchpadContainer'; export const UpscalingLaunchpadPanel = memo(() => { const { t } = useTranslation(); @@ -65,108 +66,104 @@ export const UpscalingLaunchpadPanel = memo(() => { }, [dispatch]); return ( - - - {t('ui.launchpad.upscalingTitle')} - - {/* Upload Area */} - - {!upscaleInitialImage ? ( - <> - - - {t('ui.launchpad.upscaling.uploadImage.title')} - {t('ui.launchpad.upscaling.uploadImage.description')} - - - - - - - ) : ( - <> - - - {t('ui.launchpad.upscaling.replaceImage.title')} - {t('ui.launchpad.upscaling.replaceImage.description')} - - - - - - - )} - - - - {/* Guidance text */} - {upscaleInitialImage && ( - - - {t('ui.launchpad.upscaling.readyToUpscale.title')}{' '} - {t('ui.launchpad.upscaling.readyToUpscale.description')} - - + + {/* Upload Area */} + + {!upscaleInitialImage ? ( + <> + + + {t('ui.launchpad.upscaling.uploadImage.title')} + {t('ui.launchpad.upscaling.uploadImage.description')} + + + + + + + ) : ( + <> + + + {t('ui.launchpad.upscaling.replaceImage.title')} + {t('ui.launchpad.upscaling.replaceImage.description')} + + + + + + )} + + - {/* Controls */} - - {/* Left Column: Creativity and Structural Defaults */} - - - Creativity & Structure Defaults - - - - - - - - - {/* Right Column: Description/help text */} - - - {t('ui.launchpad.upscaling.helpText.promptAdvice')} - - - {t('ui.launchpad.upscaling.helpText.styleAdvice')} - - - - - + {/* Guidance text */} + {upscaleInitialImage && ( + + + {t('ui.launchpad.upscaling.readyToUpscale.title')}{' '} + {t('ui.launchpad.upscaling.readyToUpscale.description')} + + + )} + + {/* Controls */} + + {/* Left Column: Creativity and Structural Defaults */} + + + Creativity & Structure Defaults + + + + + + + + + {/* Right Column: Description/help text */} + + + {t('ui.launchpad.upscaling.helpText.promptAdvice')} + + + {t('ui.launchpad.upscaling.helpText.styleAdvice')} + + + + ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/WorkflowsLaunchpadPanel.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/WorkflowsLaunchpadPanel.tsx index 9ee01f2921..d432f3193e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/WorkflowsLaunchpadPanel.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/WorkflowsLaunchpadPanel.tsx @@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next'; import { PiFilePlusBold, PiFolderOpenBold, PiUploadBold } from 'react-icons/pi'; import { LaunchpadButton } from './LaunchpadButton'; +import { LaunchpadContainer } from './LaunchpadContainer'; export const WorkflowsLaunchpadPanel = memo(() => { const { t } = useTranslation(); @@ -45,63 +46,59 @@ export const WorkflowsLaunchpadPanel = memo(() => { }); return ( - - - {t('ui.launchpad.workflowsTitle')} + + {/* Description */} + + {t('ui.launchpad.workflows.description')} + - {/* Description */} - - {t('ui.launchpad.workflows.description')} - + + + - - - + {/* Action Buttons */} + + {/* Browse Workflow Templates */} + + + + {t('ui.launchpad.workflows.browseTemplates.title')} + {t('ui.launchpad.workflows.browseTemplates.description')} + + - {/* Action Buttons */} - - {/* Browse Workflow Templates */} - - - - {t('ui.launchpad.workflows.browseTemplates.title')} - {t('ui.launchpad.workflows.browseTemplates.description')} - - + {/* Create a new Workflow */} + + + + {t('ui.launchpad.workflows.createNew.title')} + {t('ui.launchpad.workflows.createNew.description')} + + - {/* Create a new Workflow */} - - - - {t('ui.launchpad.workflows.createNew.title')} - {t('ui.launchpad.workflows.createNew.description')} - - - - {/* Load workflow from existing image or file */} - - - - {t('ui.launchpad.workflows.loadFromFile.title')} - {t('ui.launchpad.workflows.loadFromFile.description')} - - - - - - - + {/* Load workflow from existing image or file */} + + + + {t('ui.launchpad.workflows.loadFromFile.title')} + {t('ui.launchpad.workflows.loadFromFile.description')} + + + + + + - + ); });