diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index c027feb3b69..48aa9f80507 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -2400,7 +2400,8 @@ "uploadImage": "Upload Image", "useForTemplate": "Use For Prompt Template", "viewList": "View Template List", - "viewModeTooltip": "This is how your prompt will look with your currently selected template. To edit your prompt, click anywhere in the text box." + "viewModeTooltip": "This is how your prompt will look with your currently selected template. To edit your prompt, click anywhere in the text box.", + "togglePromptPreviews": "Toggle Prompt Previews" }, "upsell": { "inviteTeammates": "Invite Teammates", diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetCreateButton.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetCreateButton.tsx index 547dd9fffeb..207b5a1d1ef 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetCreateButton.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetCreateButton.tsx @@ -17,14 +17,13 @@ export const StylePresetCreateButton = () => { return ( } tooltip={t('stylePresets.createPromptTemplate')} aria-label={t('stylePresets.createPromptTemplate')} onClick={handleClickAddNew} - size="md" - variant="ghost" - w={8} - h={8} /> ); }; diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetExportButton.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetExportButton.tsx index dc02b63c4f5..3e47e9aba61 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetExportButton.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetExportButton.tsx @@ -53,14 +53,13 @@ export const StylePresetExportButton = () => { return ( : } tooltip={t('stylePresets.exportPromptTemplates')} aria-label={t('stylePresets.exportPromptTemplates')} - size="md" - variant="link" - w={8} - h={8} sx={isLoading ? loadingStyles : undefined} isDisabled={isLoading || presetCount === 0} /> diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetImportButton.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetImportButton.tsx index 54498ba6c3b..401a2ab7ff0 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetImportButton.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetImportButton.tsx @@ -50,13 +50,12 @@ export const StylePresetImportButton = () => { return ( <> : } tooltip={} aria-label={t('stylePresets.importTemplates')} - size="md" - variant="link" - w={8} - h={8} sx={isLoading ? loadingStyles : undefined} isDisabled={isLoading} {...getRootProps()} diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetListItem.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetListItem.tsx index 45e5c81e6c6..2e223dd8cc7 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetListItem.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetListItem.tsx @@ -1,10 +1,11 @@ -import { Badge, Flex, IconButton, Text } from '@invoke-ai/ui-library'; +import { Badge, Button, Flex, IconButton, Spacer, Text } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useDeleteStylePreset } from 'features/stylePresets/components/DeleteStylePresetDialog'; import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal'; import { $isStylePresetsMenuOpen, activeStylePresetIdChanged, + selectShowPromptPreviews, selectStylePresetActivePresetId, } from 'features/stylePresets/store/stylePresetSlice'; import type { MouseEvent } from 'react'; @@ -18,6 +19,7 @@ import StylePresetImage from './StylePresetImage'; export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithImage }) => { const dispatch = useAppDispatch(); const activeStylePresetId = useAppSelector(selectStylePresetActivePresetId); + const showPromptPreviews = useAppSelector(selectShowPromptPreviews); const { t } = useTranslation(); const deleteStylePreset = useDeleteStylePreset(); @@ -77,82 +79,80 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI ); return ( - - - - - - {preset.name} - - {activeStylePresetId === preset.id && ( - - {t('stylePresets.active')} - - )} - - - - } - /> - {preset.type !== 'default' && ( - <> - } - /> - } - /> - - )} - - - - - - - {t('stylePresets.positivePrompt')}: - {' '} - {preset.preset_data.positive_prompt} - - - - {t('stylePresets.negativePrompt')}: - {' '} - {preset.preset_data.negative_prompt} + + + + {preset.name} + {activeStylePresetId === preset.id && ( + + {t('stylePresets.active')} + + )} + + } + /> + {preset.type !== 'default' && ( + <> + } + /> + } + /> + + )} + {showPromptPreviews && ( + <> + + + {t('stylePresets.positivePrompt')}:{' '} + + {preset.preset_data.positive_prompt} + + + + + + {t('stylePresets.negativePrompt')}:{' '} + + {preset.preset_data.negative_prompt} + + + + + )} - + ); }; diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetMenu.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetMenu.tsx index 73cc8b2a410..4b84f13864e 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetMenu.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetMenu.tsx @@ -3,6 +3,7 @@ import { EMPTY_ARRAY } from 'app/store/constants'; import { useAppSelector } from 'app/store/storeHooks'; import { StylePresetExportButton } from 'features/stylePresets/components/StylePresetExportButton'; import { StylePresetImportButton } from 'features/stylePresets/components/StylePresetImportButton'; +import { StylePresetPromptPreviewToggle } from 'features/stylePresets/components/StylePresetPromptPreviewToggle'; import { selectStylePresetSearchTerm } from 'features/stylePresets/store/stylePresetSlice'; import { selectAllowPrivateStylePresets } from 'features/system/store/configSlice'; import { useTranslation } from 'react-i18next'; @@ -54,9 +55,12 @@ export const StylePresetMenu = () => { - - - + + + + + + diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetPromptPreviewToggle.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetPromptPreviewToggle.tsx new file mode 100644 index 00000000000..15b3411d224 --- /dev/null +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetPromptPreviewToggle.tsx @@ -0,0 +1,29 @@ +import { IconButton } from '@invoke-ai/ui-library'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { selectShowPromptPreviews, showPromptPreviewsChanged } from 'features/stylePresets/store/stylePresetSlice'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiEyeBold, PiEyeSlashBold } from 'react-icons/pi'; + +export const StylePresetPromptPreviewToggle = () => { + const dispatch = useAppDispatch(); + const showPromptPreviews = useAppSelector(selectShowPromptPreviews); + const { t } = useTranslation(); + + const handleToggle = useCallback(() => { + dispatch(showPromptPreviewsChanged(!showPromptPreviews)); + }, [dispatch, showPromptPreviews]); + + return ( + : } + colorScheme={showPromptPreviews ? 'invokeBlue' : 'base'} + /> + ); +}; diff --git a/invokeai/frontend/web/src/features/stylePresets/store/stylePresetSlice.ts b/invokeai/frontend/web/src/features/stylePresets/store/stylePresetSlice.ts index ba996defc71..df93d82c63c 100644 --- a/invokeai/frontend/web/src/features/stylePresets/store/stylePresetSlice.ts +++ b/invokeai/frontend/web/src/features/stylePresets/store/stylePresetSlice.ts @@ -12,6 +12,7 @@ const initialState: StylePresetState = { activeStylePresetId: null, searchTerm: '', viewMode: false, + showPromptPreviews: false, }; export const stylePresetSlice = createSlice({ @@ -27,6 +28,9 @@ export const stylePresetSlice = createSlice({ viewModeChanged: (state, action: PayloadAction) => { state.viewMode = action.payload; }, + showPromptPreviewsChanged: (state, action: PayloadAction) => { + state.showPromptPreviews = action.payload; + }, }, extraReducers(builder) { builder.addCase(paramsReset, () => { @@ -53,7 +57,8 @@ export const stylePresetSlice = createSlice({ }, }); -export const { activeStylePresetIdChanged, searchTermChanged, viewModeChanged } = stylePresetSlice.actions; +export const { activeStylePresetIdChanged, searchTermChanged, viewModeChanged, showPromptPreviewsChanged } = + stylePresetSlice.actions; /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const migrateStylePresetState = (state: any): any => { @@ -79,6 +84,7 @@ export const selectStylePresetActivePresetId = createStylePresetSelector( ); export const selectStylePresetViewMode = createStylePresetSelector((stylePreset) => stylePreset.viewMode); export const selectStylePresetSearchTerm = createStylePresetSelector((stylePreset) => stylePreset.searchTerm); +export const selectShowPromptPreviews = createStylePresetSelector((stylePreset) => stylePreset.showPromptPreviews); /** * Tracks whether or not the style preset menu is open. diff --git a/invokeai/frontend/web/src/features/stylePresets/store/types.ts b/invokeai/frontend/web/src/features/stylePresets/store/types.ts index 98b53e307bc..d1568083843 100644 --- a/invokeai/frontend/web/src/features/stylePresets/store/types.ts +++ b/invokeai/frontend/web/src/features/stylePresets/store/types.ts @@ -2,4 +2,5 @@ export type StylePresetState = { activeStylePresetId: string | null; searchTerm: string; viewMode: boolean; + showPromptPreviews: boolean; };