Skip to content

Commit 5aefa49

Browse files
psychedelicioushipsterusername
authored andcommitted
fix(ui): popover ref & wrapping of children (wip)
1 parent b6e9cd4 commit 5aefa49

File tree

13 files changed

+137
-103
lines changed

13 files changed

+137
-103
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,14 +1213,14 @@
12131213
},
12141214
"dynamicPromptsCombinatorial": {
12151215
"heading": "Combinatorial Generation",
1216-
"paragraph": "Generate an image for every possible combination of Dynamic Prompt until the Max Prompts is reached."
1216+
"paragraph": "Generate an image for every possible combination of Dynamic Prompts until the Max Prompts is reached."
12171217
},
12181218
"infillMethod": {
12191219
"heading": "Infill Method",
12201220
"paragraph": "Method to infill the selected area."
12211221
},
12221222
"lora": {
1223-
"heading": "LoRA",
1223+
"heading": "LoRA Weight",
12241224
"paragraph": "Weight of the LoRA. Higher weight will lead to larger impacts on the final image."
12251225
},
12261226
"noiseEnable": {
@@ -1239,21 +1239,21 @@
12391239
"heading": "Denoising Strength",
12401240
"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."
12411241
},
1242-
"paramImages": {
1243-
"heading": "Images",
1244-
"paragraph": "Number of images that will be generated."
1242+
"paramIterations": {
1243+
"heading": "Iterations",
1244+
"paragraph": "The number of images to generate. If Dynamic Prompts is enabled, each of the prompts will be generated this many times."
12451245
},
12461246
"paramModel": {
12471247
"heading": "Model",
12481248
"paragraph": "Model used for the denoising steps. Different models are trained to specialize in producing different aesthetic results and content."
12491249
},
12501250
"paramNegativeConditioning": {
1251-
"heading": "Negative Prompts",
1252-
"paragraph": "This is where you enter your negative prompts."
1251+
"heading": "Negative Prompt",
1252+
"paragraph": "The generation process avoids the concepts in the negative prompt. Use this to exclude qualities or objects from the output. Supports Compel syntax and embeddings."
12531253
},
12541254
"paramPositiveConditioning": {
1255-
"heading": "Positive Prompts",
1256-
"paragraph": "This is where you enter your positive prompts."
1255+
"heading": "Positive Prompt",
1256+
"paragraph": "Guides the generation process. You may use any words or phrases. Supports Compel and Dynamic Prompts syntaxes and embeddings."
12571257
},
12581258
"paramRatio": {
12591259
"heading": "Ratio",
Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
11
import {
2+
Box,
23
Button,
4+
Divider,
5+
Flex,
6+
Heading,
7+
Image,
38
Popover,
4-
PopoverTrigger,
5-
PopoverContent,
69
PopoverArrow,
7-
PopoverCloseButton,
8-
PopoverHeader,
910
PopoverBody,
11+
PopoverCloseButton,
12+
PopoverContent,
1013
PopoverProps,
11-
Flex,
14+
PopoverTrigger,
15+
Portal,
1216
Text,
13-
Image,
1417
} from '@chakra-ui/react';
15-
import { useAppSelector } from '../../app/store/storeHooks';
18+
import { ReactNode, memo } from 'react';
1619
import { useTranslation } from 'react-i18next';
20+
import { useAppSelector } from '../../app/store/storeHooks';
1721

18-
interface Props extends PopoverProps {
22+
const OPEN_DELAY = 1500;
23+
24+
type Props = Omit<PopoverProps, 'children'> & {
1925
details: string;
20-
children: JSX.Element;
26+
children: ReactNode;
2127
image?: string;
2228
buttonLabel?: string;
2329
buttonHref?: string;
2430
placement?: PopoverProps['placement'];
25-
}
31+
};
2632

27-
function IAIInformationalPopover({
33+
const IAIInformationalPopover = ({
2834
details,
2935
image,
3036
buttonLabel,
3137
buttonHref,
3238
children,
3339
placement,
34-
}: Props): JSX.Element {
40+
}: Props) => {
3541
const shouldEnableInformationalPopovers = useAppSelector(
3642
(state) => state.system.shouldEnableInformationalPopovers
3743
);
@@ -41,18 +47,21 @@ function IAIInformationalPopover({
4147
const paragraph = t(`popovers.${details}.paragraph`);
4248

4349
if (!shouldEnableInformationalPopovers) {
44-
return children;
45-
} else {
46-
return (
47-
<Popover
48-
placement={placement || 'top'}
49-
closeOnBlur={false}
50-
trigger="hover"
51-
variant="informational"
52-
>
53-
<PopoverTrigger>
54-
<div>{children}</div>
55-
</PopoverTrigger>
50+
return <>{children}</>;
51+
}
52+
53+
return (
54+
<Popover
55+
placement={placement || 'top'}
56+
closeOnBlur={false}
57+
trigger="hover"
58+
variant="informational"
59+
openDelay={OPEN_DELAY}
60+
>
61+
<PopoverTrigger>
62+
<Box w="full">{children}</Box>
63+
</PopoverTrigger>
64+
<Portal>
5665
<PopoverContent>
5766
<PopoverArrow />
5867
<PopoverCloseButton />
@@ -83,14 +92,17 @@ function IAIInformationalPopover({
8392
gap: 3,
8493
flexDirection: 'column',
8594
width: '100%',
86-
p: 3,
87-
pt: heading ? 0 : 3,
8895
}}
8996
>
90-
{heading && <PopoverHeader>{heading}</PopoverHeader>}
91-
<Text sx={{ px: 3 }}>{paragraph}</Text>
97+
{heading && (
98+
<>
99+
<Heading size="sm">{heading}</Heading>
100+
<Divider />
101+
</>
102+
)}
103+
<Text>{paragraph}</Text>
92104
{buttonLabel && (
93-
<Flex sx={{ px: 3 }} justifyContent="flex-end">
105+
<Flex justifyContent="flex-end">
94106
<Button
95107
onClick={() => window.open(buttonHref)}
96108
size="sm"
@@ -104,9 +116,9 @@ function IAIInformationalPopover({
104116
</Flex>
105117
</PopoverBody>
106118
</PopoverContent>
107-
</Popover>
108-
);
109-
}
110-
}
119+
</Portal>
120+
</Popover>
121+
);
122+
};
111123

112-
export default IAIInformationalPopover;
124+
export default memo(IAIInformationalPopover);

invokeai/frontend/web/src/common/components/IAIMantineMultiSelect.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FormControl, FormLabel, Tooltip } from '@chakra-ui/react';
1+
import { FormControl, FormLabel, Tooltip, forwardRef } from '@chakra-ui/react';
22
import { MultiSelect, MultiSelectProps } from '@mantine/core';
33
import { useAppDispatch } from 'app/store/storeHooks';
44
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
@@ -11,7 +11,7 @@ type IAIMultiSelectProps = Omit<MultiSelectProps, 'label'> & {
1111
label?: string;
1212
};
1313

14-
const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
14+
const IAIMantineMultiSelect = forwardRef((props: IAIMultiSelectProps, ref) => {
1515
const {
1616
searchable = true,
1717
tooltip,
@@ -47,7 +47,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
4747
<MultiSelect
4848
label={
4949
label ? (
50-
<FormControl isDisabled={disabled}>
50+
<FormControl ref={ref} isDisabled={disabled}>
5151
<FormLabel>{label}</FormLabel>
5252
</FormControl>
5353
) : undefined
@@ -63,6 +63,8 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
6363
/>
6464
</Tooltip>
6565
);
66-
};
66+
});
67+
68+
IAIMantineMultiSelect.displayName = 'IAIMantineMultiSelect';
6769

6870
export default memo(IAIMantineMultiSelect);

invokeai/frontend/web/src/common/components/IAIMantineSearchableSelect.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FormControl, FormLabel, Tooltip } from '@chakra-ui/react';
1+
import { FormControl, FormLabel, Tooltip, forwardRef } from '@chakra-ui/react';
22
import { Select, SelectProps } from '@mantine/core';
33
import { useAppDispatch } from 'app/store/storeHooks';
44
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
@@ -17,7 +17,7 @@ type IAISelectProps = Omit<SelectProps, 'label'> & {
1717
inputRef?: RefObject<HTMLInputElement>;
1818
};
1919

20-
const IAIMantineSearchableSelect = (props: IAISelectProps) => {
20+
const IAIMantineSearchableSelect = forwardRef((props: IAISelectProps, ref) => {
2121
const {
2222
searchable = true,
2323
tooltip,
@@ -74,7 +74,7 @@ const IAIMantineSearchableSelect = (props: IAISelectProps) => {
7474
ref={inputRef}
7575
label={
7676
label ? (
77-
<FormControl isDisabled={disabled}>
77+
<FormControl ref={ref} isDisabled={disabled}>
7878
<FormLabel>{label}</FormLabel>
7979
</FormControl>
8080
) : undefined
@@ -92,6 +92,8 @@ const IAIMantineSearchableSelect = (props: IAISelectProps) => {
9292
/>
9393
</Tooltip>
9494
);
95-
};
95+
});
96+
97+
IAIMantineSearchableSelect.displayName = 'IAIMantineSearchableSelect';
9698

9799
export default memo(IAIMantineSearchableSelect);

invokeai/frontend/web/src/common/components/IAIMantineSelect.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FormControl, FormLabel, Tooltip } from '@chakra-ui/react';
1+
import { FormControl, FormLabel, Tooltip, forwardRef } from '@chakra-ui/react';
22
import { Select, SelectProps } from '@mantine/core';
33
import { useMantineSelectStyles } from 'mantine-theme/hooks/useMantineSelectStyles';
44
import { RefObject, memo } from 'react';
@@ -15,7 +15,7 @@ export type IAISelectProps = Omit<SelectProps, 'label'> & {
1515
label?: string;
1616
};
1717

18-
const IAIMantineSelect = (props: IAISelectProps) => {
18+
const IAIMantineSelect = forwardRef((props: IAISelectProps, ref) => {
1919
const { tooltip, inputRef, label, disabled, required, ...rest } = props;
2020

2121
const styles = useMantineSelectStyles();
@@ -25,7 +25,7 @@ const IAIMantineSelect = (props: IAISelectProps) => {
2525
<Select
2626
label={
2727
label ? (
28-
<FormControl isRequired={required} isDisabled={disabled}>
28+
<FormControl ref={ref} isRequired={required} isDisabled={disabled}>
2929
<FormLabel>{label}</FormLabel>
3030
</FormControl>
3131
) : undefined
@@ -37,6 +37,8 @@ const IAIMantineSelect = (props: IAISelectProps) => {
3737
/>
3838
</Tooltip>
3939
);
40-
};
40+
});
41+
42+
IAIMantineSelect.displayName = 'IAIMantineSelect';
4143

4244
export default memo(IAIMantineSelect);

invokeai/frontend/web/src/common/components/IAINumberInput.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
NumberInputStepperProps,
1414
Tooltip,
1515
TooltipProps,
16+
forwardRef,
1617
} from '@chakra-ui/react';
1718
import { useAppDispatch } from 'app/store/storeHooks';
1819
import { stopPastePropagation } from 'common/util/stopPastePropagation';
@@ -50,7 +51,7 @@ interface Props extends Omit<NumberInputProps, 'onChange'> {
5051
/**
5152
* Customized Chakra FormControl + NumberInput multi-part component.
5253
*/
53-
const IAINumberInput = (props: Props) => {
54+
const IAINumberInput = forwardRef((props: Props, ref) => {
5455
const {
5556
label,
5657
isDisabled = false,
@@ -141,6 +142,7 @@ const IAINumberInput = (props: Props) => {
141142
return (
142143
<Tooltip {...tooltipProps}>
143144
<FormControl
145+
ref={ref}
144146
isDisabled={isDisabled}
145147
isInvalid={isInvalid}
146148
{...formControlProps}
@@ -172,6 +174,8 @@ const IAINumberInput = (props: Props) => {
172174
</FormControl>
173175
</Tooltip>
174176
);
175-
};
177+
});
178+
179+
IAINumberInput.displayName = 'IAINumberInput';
176180

177181
export default memo(IAINumberInput);

invokeai/frontend/web/src/common/components/IAISlider.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
SliderTrackProps,
2323
Tooltip,
2424
TooltipProps,
25+
forwardRef,
2526
} from '@chakra-ui/react';
2627
import { useAppDispatch } from 'app/store/storeHooks';
2728
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
@@ -71,7 +72,7 @@ export type IAIFullSliderProps = {
7172
sliderIAIIconButtonProps?: IAIIconButtonProps;
7273
};
7374

74-
const IAISlider = (props: IAIFullSliderProps) => {
75+
const IAISlider = forwardRef((props: IAIFullSliderProps, ref) => {
7576
const [showTooltip, setShowTooltip] = useState(false);
7677
const {
7778
label,
@@ -187,6 +188,7 @@ const IAISlider = (props: IAIFullSliderProps) => {
187188

188189
return (
189190
<FormControl
191+
ref={ref}
190192
onClick={forceInputBlur}
191193
sx={
192194
isCompact
@@ -354,6 +356,8 @@ const IAISlider = (props: IAIFullSliderProps) => {
354356
</HStack>
355357
</FormControl>
356358
);
357-
};
359+
});
360+
361+
IAISlider.displayName = 'IAISlider';
358362

359363
export default memo(IAISlider);

invokeai/frontend/web/src/common/components/IAISwitch.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@ const IAISwitch = (props: IAISwitchProps) => {
7272
);
7373
};
7474

75+
IAISwitch.displayName = 'IAISwitch';
76+
7577
export default memo(IAISwitch);

invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamIterations.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const ParamIterations = ({ asSlider }: Props) => {
6161
}, [dispatch, initial]);
6262

6363
return asSlider || shouldUseSliders ? (
64-
<IAIInformationalPopover details="paramImages">
64+
<IAIInformationalPopover details="paramIterations">
6565
<IAISlider
6666
label={t('parameters.iterations')}
6767
step={step}
@@ -77,7 +77,7 @@ const ParamIterations = ({ asSlider }: Props) => {
7777
/>
7878
</IAIInformationalPopover>
7979
) : (
80-
<IAIInformationalPopover details="paramImages">
80+
<IAIInformationalPopover details="paramIterations">
8181
<IAINumberInput
8282
label={t('parameters.iterations')}
8383
step={step}

0 commit comments

Comments
 (0)