diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 76f1ac0069..c309e4de50 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -1154,6 +1154,136 @@
"variations": "Try a variation with a value between 0.1 and 1.0 to change the result for a given seed. Interesting variations of the seed are between 0.1 and 0.3."
}
},
+ "popovers": {
+ "clipSkip": {
+ "heading": "CLIP Skip",
+ "paragraph": "Choose how many layers of the CLIP model to skip. Certain models are better suited to be used with CLIP Skip."
+ },
+ "compositingBlur": {
+ "heading": "Blur",
+ "paragraph": "The blur radius of the mask."
+ },
+ "compositingBlurMethod": {
+ "heading": "Blur Method",
+ "paragraph": "The method of blur applied to the masked area."
+ },
+ "compositingCoherencePass": {
+ "heading": "Coherence Pass",
+ "paragraph": "Composite the Inpainted/Outpainted images."
+ },
+ "compositingCoherenceMode": {
+ "heading": "Mode",
+ "paragraph": "The mode of the Coherence Pass."
+ },
+ "compositingCoherenceSteps": {
+ "heading": "Steps",
+ "paragraph": "Number of steps in the Coherence Pass. Similar to Denoising Steps."
+ },
+ "compositingStrength": {
+ "heading": "Strength",
+ "paragraph": "Amount of noise added for the Coherence Pass. Similar to Denoising Strength."
+ },
+ "compositingMaskAdjustments": {
+ "heading": "Mask Adjustments",
+ "paragraph": "Adjust the mask."
+ },
+ "controlNetBeginEnd": {
+ "heading": "Begin / End Step Percentage",
+ "paragraph": "Which parts of the denoising process will have the ControlNet applied. ControlNets applied at the start of the process guide composition, and ControlNets applied at the end guide details."
+ },
+ "controlNetControlMode": {
+ "heading": "Control Mode",
+ "paragraph": "Lends more weight to either the prompt or ControlNet."
+ },
+ "controlNetResizeMode": {
+ "heading": "Resize Mode",
+ "paragraph": "How the ControlNet image will be fit to the image generation Ratio"
+ },
+ "controlNetToggle": {
+ "heading": "Enable ControlNet",
+ "paragraph": "ControlNets provide guidance to the generation process, helping create images with controlled composition, structure, or style, depending on the model selected."
+ },
+ "controlNetWeight": {
+ "heading": "Weight",
+ "paragraph": "How strongly the ControlNet will impact the generated image."
+ },
+ "dynamicPromptsToggle": {
+ "heading": "Enable Dynamic Prompts",
+ "paragraph": "Dynamic prompts allow multiple options within a prompt. Dynamic prompts can be used by: {option1|option2|option3}. Combinations of prompts will be randomly generated until the “Images” number has been reached."
+ },
+ "dynamicPromptsCombinatorial": {
+ "heading": "Combinatorial Generation",
+ "paragraph": "Generate an image for every possible combination of Dynamic Prompt until the Max Prompts is reached."
+ },
+ "infillMethod": {
+ "heading": "Infill Method",
+ "paragraph": "Method to infill the selected area."
+ },
+ "lora": {
+ "heading": "LoRA",
+ "paragraph": "Weight of the LoRA. Higher weight will lead to larger impacts on the final image."
+ },
+ "noiseEnable": {
+ "heading": "Enable Noise Settings",
+ "paragraph": "Advanced control over noise generation."
+ },
+ "noiseUseCPU": {
+ "heading": "Use CPU Noise",
+ "paragraph": "Uses the CPU to generate random noise."
+ },
+ "paramCFGScale": {
+ "heading": "CFG Scale",
+ "paragraph": "Controls how much your prompt influences the generation process."
+ },
+ "paramDenoisingStrength": {
+ "heading": "Denoising Strength",
+ "paragraph": "How much noise is added to the input image. 0 will result in an identical image, while 1 will result in a completely new image."
+ },
+ "paramImages": {
+ "heading": "Images",
+ "paragraph": "Number of images that will be generated."
+ },
+ "paramModel": {
+ "heading": "Model",
+ "paragraph": "Model used for the denoising steps. Different models are trained to specialize in producing different aesthetic results and content."
+ },
+ "paramNegativeConditioning": {
+ "heading": "Negative Prompts",
+ "paragraph": "This is where you enter your negative prompts."
+ },
+ "paramPositiveConditioning": {
+ "heading": "Positive Prompts",
+ "paragraph": "This is where you enter your positive prompts."
+ },
+ "paramRatio": {
+ "heading": "Ratio",
+ "paragraph": "The ratio of the dimensions of the image generated. An image size (in number of pixels) equivalent to 512x512 is recommended for SD1.5 models and a size equivalent to 1024x1024 is recommended for SDXL models."
+ },
+ "paramScheduler": {
+ "heading": "Scheduler",
+ "paragraph": "Scheduler defines how to iteratively add noise to an image or how to update a sample based on a model's output."
+ },
+ "paramSeed": {
+ "heading": "Seed",
+ "paragraph": "Controls the starting noise used for generation. Disable “Random Seed” to produce identical results with the same generation settings."
+ },
+ "paramSteps": {
+ "heading": "Steps",
+ "paragraph": "Number of steps that will be performed in each generation. Higher step counts will typically create better images but will require more generation time."
+ },
+ "paramVAE": {
+ "heading": "VAE",
+ "paragraph": "Model used for translating AI output into the final image."
+ },
+ "paramVAEPrecision": {
+ "heading": "VAE Precision",
+ "paragraph": "The precision used during VAE encoding and decoding. Fp16/Half precision is more efficient, at the expense of minor image variations."
+ },
+ "scaleBeforeProcessing": {
+ "heading": "Scale Before Processing",
+ "paragraph": "Scales the selected area to the size best suited for the model before the image generation process."
+ }
+ },
"ui": {
"hideProgressImages": "Hide Progress Images",
"lockRatio": "Lock Ratio",
diff --git a/invokeai/frontend/web/src/common/components/IAIInformationalPopover.tsx b/invokeai/frontend/web/src/common/components/IAIInformationalPopover.tsx
new file mode 100644
index 0000000000..bbfccf7c0d
--- /dev/null
+++ b/invokeai/frontend/web/src/common/components/IAIInformationalPopover.tsx
@@ -0,0 +1,112 @@
+import {
+ Button,
+ Popover,
+ PopoverTrigger,
+ PopoverContent,
+ PopoverArrow,
+ PopoverCloseButton,
+ PopoverHeader,
+ PopoverBody,
+ PopoverProps,
+ Flex,
+ Text,
+ Image,
+} from '@chakra-ui/react';
+import { useAppSelector } from '../../app/store/storeHooks';
+import { useTranslation } from 'react-i18next';
+
+interface Props extends PopoverProps {
+ details: string;
+ children: JSX.Element;
+ image?: string;
+ buttonLabel?: string;
+ buttonHref?: string;
+ placement?: PopoverProps['placement'];
+}
+
+function IAIInformationalPopover({
+ details,
+ image,
+ buttonLabel,
+ buttonHref,
+ children,
+ placement,
+}: Props): JSX.Element {
+ const shouldDisableInformationalPopovers = useAppSelector(
+ (state) => state.system.shouldDisableInformationalPopovers
+ );
+ const { t } = useTranslation();
+
+ const heading = t(`popovers.${details}.heading`);
+ const paragraph = t(`popovers.${details}.paragraph`);
+
+ if (shouldDisableInformationalPopovers) {
+ return children;
+ } else {
+ return (
+
+
+ {children}
+
+
+
+
+
+
+
+ {image && (
+
+ )}
+
+ {heading && {heading} }
+ {paragraph}
+ {buttonLabel && (
+
+ window.open(buttonHref)}
+ size="sm"
+ variant="invokeAIOutline"
+ >
+ {buttonLabel}
+
+
+ )}
+
+
+
+
+
+ );
+ }
+}
+
+export default IAIInformationalPopover;
diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx
index f34c863cff..fb43c3553d 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx
@@ -10,6 +10,7 @@ import {
Tooltip,
} from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import {
ControlNetConfig,
controlNetBeginStepPctChanged,
@@ -49,58 +50,60 @@ const ParamControlNetBeginEnd = (props: Props) => {
);
return (
-
- {t('controlnet.beginEndStepPercent')}
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {t('controlnet.beginEndStepPercent')}
+
+
- 0%
-
-
- 50%
-
-
- 100%
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ 0%
+
+
+ 50%
+
+
+ 100%
+
+
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx
index e8f26a6dd1..9b17c2bfb2 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx
@@ -1,4 +1,5 @@
import { useAppDispatch } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
ControlModes,
@@ -34,12 +35,14 @@ export default function ParamControlNetControlMode(
);
return (
-
+
+
+
);
}
diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetFeatureToggle.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetFeatureToggle.tsx
index 97a54dc7d1..1902d622ff 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetFeatureToggle.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetFeatureToggle.tsx
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISwitch from 'common/components/IAISwitch';
import { isControlNetEnabledToggled } from 'features/controlNet/store/controlNetSlice';
import { memo, useCallback } from 'react';
@@ -25,14 +26,16 @@ const ParamControlNetFeatureToggle = () => {
}, [dispatch]);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx
index f2b2b59785..0ad2f342b2 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx
@@ -1,4 +1,5 @@
import { useAppDispatch } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
ControlNetConfig,
@@ -33,12 +34,14 @@ export default function ParamControlNetResizeMode(
);
return (
-
+
+
+
);
}
diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetWeight.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetWeight.tsx
index 8314f26cfc..4e9928d828 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetWeight.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetWeight.tsx
@@ -1,4 +1,5 @@
import { useAppDispatch } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISlider from 'common/components/IAISlider';
import {
ControlNetConfig,
@@ -23,17 +24,19 @@ const ParamControlNetWeight = (props: ParamControlNetWeightProps) => {
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx
index 29c06ffdc7..391d588733 100644
--- a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx
+++ b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx
@@ -6,6 +6,7 @@ import IAISwitch from 'common/components/IAISwitch';
import { memo, useCallback } from 'react';
import { combinatorialToggled } from '../store/dynamicPromptsSlice';
import { useTranslation } from 'react-i18next';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const selector = createSelector(
stateSelector,
@@ -27,11 +28,13 @@ const ParamDynamicPromptsCombinatorial = () => {
}, [dispatch]);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/lora/components/ParamLora.tsx b/invokeai/frontend/web/src/features/lora/components/ParamLora.tsx
index 3432838ec0..951de86217 100644
--- a/invokeai/frontend/web/src/features/lora/components/ParamLora.tsx
+++ b/invokeai/frontend/web/src/features/lora/components/ParamLora.tsx
@@ -10,6 +10,7 @@ import {
loraWeightChanged,
loraWeightReset,
} from '../store/loraSlice';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
type Props = {
lora: LoRA;
@@ -35,30 +36,32 @@ const ParamLora = (props: Props) => {
}, [dispatch, lora.id]);
return (
-
-
- }
- colorScheme="error"
- />
-
+
+
+
+ }
+ colorScheme="error"
+ />
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx
index f51e42b6a1..a7d3d3c655 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx
@@ -1,5 +1,6 @@
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISlider from 'common/components/IAISlider';
import { setClipSkip } from 'features/parameters/store/generationSlice';
import { clipSkipMap } from 'features/parameters/types/constants';
@@ -42,19 +43,21 @@ export default function ParamClipSkip() {
}, [model]);
return (
-
+
+
+
);
}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxSize.tsx
index 1c1f60bc09..a3eb428526 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxSize.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxSize.tsx
@@ -18,6 +18,7 @@ import ParamAspectRatio, {
} from '../../Core/ParamAspectRatio';
import ParamBoundingBoxHeight from './ParamBoundingBoxHeight';
import ParamBoundingBoxWidth from './ParamBoundingBoxWidth';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const sizeOptsSelector = createSelector(
[generationSelector, canvasSelector],
@@ -93,18 +94,20 @@ export default function ParamBoundingBoxSize() {
}}
>
-
- {t('parameters.aspectRatio')}
-
+
+
+ {t('parameters.aspectRatio')}
+
+
{
};
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceSteps.tsx
index 5482a7e1d9..f7de446737 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceSteps.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceSteps.tsx
@@ -1,5 +1,6 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISlider from 'common/components/IAISlider';
import { setCanvasCoherenceSteps } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
@@ -13,23 +14,25 @@ const ParamCanvasCoherenceSteps = () => {
const { t } = useTranslation();
return (
- {
- dispatch(setCanvasCoherenceSteps(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => {
- dispatch(setCanvasCoherenceSteps(20));
- }}
- />
+
+ {
+ dispatch(setCanvasCoherenceSteps(v));
+ }}
+ withInput
+ withSliderMarks
+ withReset
+ handleReset={() => {
+ dispatch(setCanvasCoherenceSteps(20));
+ }}
+ />
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceStrength.tsx
index f478bd70fe..31b86cfd49 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceStrength.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceStrength.tsx
@@ -1,5 +1,6 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISlider from 'common/components/IAISlider';
import { setCanvasCoherenceStrength } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
@@ -13,23 +14,25 @@ const ParamCanvasCoherenceStrength = () => {
const { t } = useTranslation();
return (
- {
- dispatch(setCanvasCoherenceStrength(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => {
- dispatch(setCanvasCoherenceStrength(0.3));
- }}
- />
+
+ {
+ dispatch(setCanvasCoherenceStrength(v));
+ }}
+ withInput
+ withSliderMarks
+ withReset
+ handleReset={() => {
+ dispatch(setCanvasCoherenceStrength(0.3));
+ }}
+ />
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlur.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlur.tsx
index 82b82228e2..da68f5ed3c 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlur.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlur.tsx
@@ -1,5 +1,6 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISlider from 'common/components/IAISlider';
import { setMaskBlur } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
@@ -12,21 +13,23 @@ export default function ParamMaskBlur() {
const { t } = useTranslation();
return (
- {
- dispatch(setMaskBlur(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => {
- dispatch(setMaskBlur(16));
- }}
- />
+
+ {
+ dispatch(setMaskBlur(v));
+ }}
+ withInput
+ withSliderMarks
+ withReset
+ handleReset={() => {
+ dispatch(setMaskBlur(16));
+ }}
+ />
+
);
}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlurMethod.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlurMethod.tsx
index 62d0605640..12da7fd2fd 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlurMethod.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/MaskAdjustment/ParamMaskBlurMethod.tsx
@@ -2,6 +2,7 @@ import { SelectItem } from '@mantine/core';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { setMaskBlurMethod } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
@@ -28,11 +29,13 @@ export default function ParamMaskBlurMethod() {
};
return (
-
+
+
+
);
}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
index d0a0ff8f01..606d6d2dfc 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
@@ -15,13 +15,19 @@ const ParamCompositingSettingsCollapse = () => {
return (
-
+
-
+
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillMethod.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillMethod.tsx
index 9ac0e3588f..7a4ac1601d 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillMethod.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillMethod.tsx
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { setInfillMethod } from 'features/parameters/store/generationSlice';
@@ -39,14 +40,16 @@ const ParamInfillMethod = () => {
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaleBeforeProcessing.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaleBeforeProcessing.tsx
index e00d56b639..a1c63d6ddb 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaleBeforeProcessing.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaleBeforeProcessing.tsx
@@ -1,6 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxScaleMethod } from 'features/canvas/store/canvasSlice';
@@ -35,12 +36,14 @@ const ParamScaleBeforeProcessing = () => {
};
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx
index 54a7ccbe65..51d6edc2dc 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAINumberInput from 'common/components/IAINumberInput';
import IAISlider from 'common/components/IAISlider';
import { setCfgScale } from 'features/parameters/store/generationSlice';
@@ -53,31 +54,35 @@ const ParamCFGScale = () => {
);
return shouldUseSliders ? (
-
+
+
+
) : (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamIterations.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamIterations.tsx
index 46d90b3954..f9df43d7ca 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamIterations.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamIterations.tsx
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAINumberInput from 'common/components/IAINumberInput';
import IAISlider from 'common/components/IAISlider';
import { setIterations } from 'features/parameters/store/generationSlice';
@@ -60,29 +61,33 @@ const ParamIterations = ({ asSlider }: Props) => {
}, [dispatch, initial]);
return asSlider || shouldUseSliders ? (
-
+
+
+
) : (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamNegativeConditioning.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamNegativeConditioning.tsx
index 2aab013f4f..1154187eaf 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamNegativeConditioning.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamNegativeConditioning.tsx
@@ -9,6 +9,7 @@ import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
import { flushSync } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const ParamNegativeConditioning = () => {
const negativePrompt = useAppSelector(
@@ -81,18 +82,20 @@ const ParamNegativeConditioning = () => {
onClose={onClose}
onSelect={handleSelectEmbedding}
>
-
+
+
+
{!isOpen && isEmbeddingEnabled && (
{
onClose={onClose}
onSelect={handleSelectEmbedding}
>
-
+
+
+
{!isOpen && isEmbeddingEnabled && (
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx
index da1b359b37..3aadac0457 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx
@@ -1,6 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { setScheduler } from 'features/parameters/store/generationSlice';
@@ -51,12 +52,14 @@ const ParamScheduler = () => {
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx
index 99d0617de3..c7ddd59559 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx
@@ -16,6 +16,7 @@ import { activeTabNameSelector } from '../../../../ui/store/uiSelectors';
import ParamAspectRatio, { mappedAspectRatios } from './ParamAspectRatio';
import ParamHeight from './ParamHeight';
import ParamWidth from './ParamWidth';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
const sizeOptsSelector = createSelector(
@@ -83,18 +84,20 @@ export default function ParamSize() {
}}
>
-
- {t('parameters.aspectRatio')}
-
+
+
+ {t('parameters.aspectRatio')}
+
+
{
}, [dispatch]);
return shouldUseSliders ? (
-
+
+
+
) : (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx
index 2a14ee634c..b22dff22e5 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx
@@ -7,6 +7,7 @@ import { setImg2imgStrength } from 'features/parameters/store/generationSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import SubParametersWrapper from '../SubParametersWrapper';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const selector = createSelector(
[stateSelector],
@@ -46,20 +47,22 @@ const ImageToImageStrength = () => {
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/MainModel/ParamMainModelSelect.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/MainModel/ParamMainModelSelect.tsx
index 05b5b6468a..9c957523bc 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/MainModel/ParamMainModelSelect.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/MainModel/ParamMainModelSelect.tsx
@@ -21,6 +21,7 @@ import {
useGetOnnxModelsQuery,
} from 'services/api/endpoints/models';
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const selector = createSelector(
stateSelector,
@@ -118,24 +119,28 @@ const ParamMainModelSelect = () => {
data={[]}
/>
) : (
-
- 0 ? 'Select a model' : 'No models available'}
- data={data}
- error={data.length === 0}
- disabled={data.length === 0}
- onChange={handleChangeModel}
- w="100%"
- />
- {isSyncModelEnabled && (
-
-
-
- )}
-
+
+
+ 0 ? 'Select a model' : 'No models available'
+ }
+ data={data}
+ error={data.length === 0}
+ disabled={data.length === 0}
+ onChange={handleChangeModel}
+ w="100%"
+ />
+ {isSyncModelEnabled && (
+
+
+
+ )}
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx
index 23f8f23fb6..b3c8aea415 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx
@@ -1,4 +1,5 @@
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAISwitch from 'common/components/IAISwitch';
import { shouldUseCpuNoiseChanged } from 'features/parameters/store/generationSlice';
import { ChangeEvent, useCallback } from 'react';
@@ -19,10 +20,12 @@ export const ParamCpuNoiseToggle = () => {
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedFull.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedFull.tsx
index a1887ec896..8ddba1cbb2 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedFull.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedFull.tsx
@@ -3,14 +3,17 @@ import { memo } from 'react';
import ParamSeed from './ParamSeed';
import ParamSeedShuffle from './ParamSeedShuffle';
import ParamSeedRandomize from './ParamSeedRandomize';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const ParamSeedFull = () => {
return (
-
-
-
-
-
+
+
+
+
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/SubParametersWrapper.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/SubParametersWrapper.tsx
index 96c78b1336..65b565e926 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/SubParametersWrapper.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/SubParametersWrapper.tsx
@@ -1,9 +1,11 @@
import { Flex, Text } from '@chakra-ui/react';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import { ReactNode, memo } from 'react';
type SubParameterWrapperProps = {
children: ReactNode | ReactNode[];
label?: string;
+ headerInfoPopover?: string;
};
const SubParametersWrapper = (props: SubParameterWrapperProps) => (
@@ -21,7 +23,18 @@ const SubParametersWrapper = (props: SubParameterWrapperProps) => (
},
}}
>
- {props.label && (
+ {props.headerInfoPopover && props.label && (
+
+
+ {props.label}
+
+
+ )}
+ {!props.headerInfoPopover && props.label && (
{
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx
index c57cdc1132..5fa15c5fe3 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { vaePrecisionChanged } from 'features/parameters/store/generationSlice';
import { PrecisionParam } from 'features/parameters/types/parameterSchemas';
@@ -34,12 +35,14 @@ const ParamVAEModelSelect = () => {
);
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/sdxl/components/ParamSDXLImg2ImgDenoisingStrength.tsx b/invokeai/frontend/web/src/features/sdxl/components/ParamSDXLImg2ImgDenoisingStrength.tsx
index 5433c77b4e..dc8ae775f9 100644
--- a/invokeai/frontend/web/src/features/sdxl/components/ParamSDXLImg2ImgDenoisingStrength.tsx
+++ b/invokeai/frontend/web/src/features/sdxl/components/ParamSDXLImg2ImgDenoisingStrength.tsx
@@ -7,6 +7,7 @@ import SubParametersWrapper from 'features/parameters/components/Parameters/SubP
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { setSDXLImg2ImgDenoisingStrength } from '../store/sdxlSlice';
+import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
const selector = createSelector(
[stateSelector],
@@ -36,19 +37,21 @@ const ParamSDXLImg2ImgDenoisingStrength = () => {
return (
-
+
+
+
);
};
diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx
index f1bc3f0a40..0a50f9ad7f 100644
--- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx
+++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx
@@ -23,6 +23,7 @@ import {
consoleLogLevelChanged,
setEnableImageDebugging,
setShouldConfirmOnDelete,
+ setShouldDisableInformationalPopovers,
shouldAntialiasProgressImageChanged,
shouldLogToConsoleChanged,
shouldUseNSFWCheckerChanged,
@@ -66,6 +67,7 @@ const selector = createSelector(
shouldAntialiasProgressImage,
shouldUseNSFWChecker,
shouldUseWatermarker,
+ shouldDisableInformationalPopovers,
} = system;
const {
@@ -85,6 +87,7 @@ const selector = createSelector(
shouldUseNSFWChecker,
shouldUseWatermarker,
shouldAutoChangeDimensions,
+ shouldDisableInformationalPopovers,
};
},
{
@@ -158,6 +161,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
shouldUseNSFWChecker,
shouldUseWatermarker,
shouldAutoChangeDimensions,
+ shouldDisableInformationalPopovers,
} = useAppSelector(selector);
const handleClickResetWebUI = useCallback(() => {
@@ -307,6 +311,15 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
onChange={handleLanguageChanged}
/>
)}
+ ) =>
+ dispatch(
+ setShouldDisableInformationalPopovers(e.target.checked)
+ )
+ }
+ />
{shouldShowDeveloperSettings && (
diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts
index 40e8c42145..c74ab87dcf 100644
--- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts
+++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts
@@ -35,6 +35,7 @@ export const initialSystemState: SystemState = {
language: 'en',
shouldUseNSFWChecker: false,
shouldUseWatermarker: false,
+ shouldDisableInformationalPopovers: false,
status: 'DISCONNECTED',
};
@@ -75,6 +76,12 @@ export const systemSlice = createSlice({
shouldUseWatermarkerChanged(state, action: PayloadAction) {
state.shouldUseWatermarker = action.payload;
},
+ setShouldDisableInformationalPopovers(
+ state,
+ action: PayloadAction
+ ) {
+ state.shouldDisableInformationalPopovers = action.payload;
+ },
},
extraReducers(builder) {
/**
@@ -234,6 +241,7 @@ export const {
languageChanged,
shouldUseNSFWCheckerChanged,
shouldUseWatermarkerChanged,
+ setShouldDisableInformationalPopovers,
} = systemSlice.actions;
export default systemSlice.reducer;
diff --git a/invokeai/frontend/web/src/features/system/store/types.ts b/invokeai/frontend/web/src/features/system/store/types.ts
index b81e292e36..29bc836dae 100644
--- a/invokeai/frontend/web/src/features/system/store/types.ts
+++ b/invokeai/frontend/web/src/features/system/store/types.ts
@@ -33,6 +33,7 @@ export interface SystemState {
shouldUseNSFWChecker: boolean;
shouldUseWatermarker: boolean;
status: SystemStatus;
+ shouldDisableInformationalPopovers: boolean;
}
export const LANGUAGES = {
diff --git a/invokeai/frontend/web/src/theme/components/button.ts b/invokeai/frontend/web/src/theme/components/button.ts
index dd802a878b..fc6cde9cd0 100644
--- a/invokeai/frontend/web/src/theme/components/button.ts
+++ b/invokeai/frontend/web/src/theme/components/button.ts
@@ -80,6 +80,13 @@ const invokeAIOutline = defineStyle((props) => {
return {
border: '1px solid',
borderColor: c === 'gray' ? borderColor : 'currentColor',
+ _hover: {
+ bg: mode(`${c}.500`, `${c}.500`)(props),
+ color: mode('white', `base.50`)(props),
+ svg: {
+ fill: mode('white', `base.50`)(props),
+ },
+ },
'.chakra-button__group[data-attached][data-orientation=horizontal] > &:not(:last-of-type)':
{
marginEnd: '-1px',
diff --git a/invokeai/frontend/web/src/theme/components/popover.ts b/invokeai/frontend/web/src/theme/components/popover.ts
index a28e2bfbc4..55f69e9036 100644
--- a/invokeai/frontend/web/src/theme/components/popover.ts
+++ b/invokeai/frontend/web/src/theme/components/popover.ts
@@ -29,13 +29,34 @@ const invokeAIContent = defineStyle((props) => {
};
});
+const informationalContent = defineStyle((props) => {
+ return {
+ [$arrowBg.variable]: mode('colors.base.100', 'colors.base.600')(props),
+ [$popperBg.variable]: mode('colors.base.100', 'colors.base.600')(props),
+ [$arrowShadowColor.variable]: mode(
+ 'colors.base.400',
+ 'colors.base.400'
+ )(props),
+ p: 0,
+ bg: mode('base.100', 'base.600')(props),
+ border: 'none',
+ shadow: 'dark-lg',
+ };
+});
+
const invokeAI = definePartsStyle((props) => ({
content: invokeAIContent(props),
}));
+const informational = definePartsStyle((props) => ({
+ content: informationalContent(props),
+ body: { padding: 0 },
+}));
+
export const popoverTheme = defineMultiStyleConfig({
variants: {
invokeAI,
+ informational,
},
defaultProps: {
variant: 'invokeAI',