Skip to content

Commit 8e93b7a

Browse files
Copilotlstein
andcommitted
fix(frontend) Make informational tooltips respect the shouldEnableInformationalPopovers setting
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
1 parent ec2eedb commit 8e93b7a

100 files changed

Lines changed: 809 additions & 644 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { TooltipProps } from '@invoke-ai/ui-library';
2+
import { Tooltip } from '@invoke-ai/ui-library';
3+
import { useAppSelector } from 'app/store/storeHooks';
4+
import { selectSystemShouldEnableInformationalPopovers } from 'features/system/store/systemSlice';
5+
import type { PropsWithChildren } from 'react';
6+
import { memo } from 'react';
7+
8+
/**
9+
* A Tooltip component that respects the user's "Enable Informational Popovers" setting.
10+
* When the setting is disabled, this component returns its children without a tooltip wrapper.
11+
*/
12+
export const IAITooltip = memo(({ children, ...rest }: PropsWithChildren<TooltipProps>) => {
13+
const shouldEnableInformationalPopovers = useAppSelector(selectSystemShouldEnableInformationalPopovers);
14+
15+
if (!shouldEnableInformationalPopovers) {
16+
return children;
17+
}
18+
19+
return <Tooltip {...rest}>{children}</Tooltip>;
20+
});
21+
22+
IAITooltip.displayName = 'IAITooltip';

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { MenuItemProps } from '@invoke-ai/ui-library';
2-
import { Flex, MenuItem, Tooltip } from '@invoke-ai/ui-library';
2+
import { Flex, MenuItem } from '@invoke-ai/ui-library';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import type { ReactNode } from 'react';
45

56
type Props = MenuItemProps & {
@@ -9,7 +10,7 @@ type Props = MenuItemProps & {
910

1011
export const IconMenuItem = ({ tooltip, icon, ...props }: Props) => {
1112
return (
12-
<Tooltip label={tooltip} placement="top" gutter={12}>
13+
<IAITooltip label={tooltip} placement="top" gutter={12}>
1314
<MenuItem
1415
display="flex"
1516
alignItems="center"
@@ -21,7 +22,7 @@ export const IconMenuItem = ({ tooltip, icon, ...props }: Props) => {
2122
>
2223
{icon}
2324
</MenuItem>
24-
</Tooltip>
25+
</IAITooltip>
2526
);
2627
};
2728

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListGlobalActionBarAddLayerMenu.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { IconButton, Menu, MenuButton, MenuGroup, MenuItem, MenuList } from '@invoke-ai/ui-library';
2+
import { IAITooltip } from 'common/components/IAITooltip';
23
import {
34
useAddControlLayer,
45
useAddInpaintMask,
@@ -26,17 +27,18 @@ export const EntityListGlobalActionBarAddLayerMenu = memo(() => {
2627

2728
return (
2829
<Menu>
29-
<MenuButton
30-
as={IconButton}
31-
minW={8}
32-
variant="link"
33-
alignSelf="stretch"
34-
tooltip={t('controlLayers.addLayer')}
35-
aria-label={t('controlLayers.addLayer')}
36-
icon={<PiPlusBold />}
37-
data-testid="control-layers-add-layer-menu-button"
38-
isDisabled={isBusy}
39-
/>
30+
<IAITooltip label={t('controlLayers.addLayer')}>
31+
<MenuButton
32+
as={IconButton}
33+
minW={8}
34+
variant="link"
35+
alignSelf="stretch"
36+
aria-label={t('controlLayers.addLayer')}
37+
icon={<PiPlusBold />}
38+
data-testid="control-layers-add-layer-menu-button"
39+
isDisabled={isBusy}
40+
/>
41+
</IAITooltip>
4042
<MenuList>
4143
<MenuGroup title={t('controlLayers.regional')}>
4244
<MenuItem icon={<PiPlusBold />} onClick={addInpaintMask} isDisabled={!isInpaintLayerEnabled}>

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarDuplicateButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
45
import { entityDuplicated } from 'features/controlLayers/store/canvasSlice';
56
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
@@ -20,16 +21,17 @@ export const EntityListSelectedEntityActionBarDuplicateButton = memo(() => {
2021
}, [dispatch, selectedEntityIdentifier]);
2122

2223
return (
23-
<IconButton
24-
onClick={onClick}
25-
isDisabled={!selectedEntityIdentifier || isBusy}
26-
minW={8}
27-
variant="link"
28-
alignSelf="stretch"
29-
aria-label={t('controlLayers.duplicate')}
30-
tooltip={t('controlLayers.duplicate')}
31-
icon={<PiCopyFill />}
32-
/>
24+
<IAITooltip label={t('controlLayers.duplicate')}>
25+
<IconButton
26+
onClick={onClick}
27+
isDisabled={!selectedEntityIdentifier || isBusy}
28+
minW={8}
29+
variant="link"
30+
alignSelf="stretch"
31+
aria-label={t('controlLayers.duplicate')}
32+
icon={<PiCopyFill />}
33+
/>
34+
</IAITooltip>
3335
);
3436
});
3537

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarFill.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
PopoverContent,
77
PopoverTrigger,
88
Portal,
9-
Tooltip,
109
} from '@invoke-ai/ui-library';
1110
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
11+
import { IAITooltip } from 'common/components/IAITooltip';
1212
import RgbColorPicker from 'common/components/ColorPicker/RgbColorPicker';
1313
import { rgbColorToString } from 'common/util/colorCodeTransformers';
1414
import { MaskFillStyle } from 'features/controlLayers/components/common/MaskFillStyle';
@@ -56,8 +56,8 @@ export const EntityListSelectedEntityActionBarFill = memo(() => {
5656
return (
5757
<Popover isLazy>
5858
<PopoverTrigger>
59-
<Flex role="button" aria-label={t('controlLayers.maskFill')} tabIndex={-1} w={8} h={8}>
60-
<Tooltip label={t('controlLayers.maskFill')}>
59+
<IAITooltip label={t('controlLayers.maskFill')}>
60+
<Flex role="button" aria-label={t('controlLayers.maskFill')} tabIndex={-1} w={8} h={8}>
6161
<Flex w="full" h="full" alignItems="center" justifyContent="center">
6262
<Box
6363
borderRadius="full"
@@ -68,8 +68,8 @@ export const EntityListSelectedEntityActionBarFill = memo(() => {
6868
bg={rgbColorToString(fill.color)}
6969
/>
7070
</Flex>
71-
</Tooltip>
72-
</Flex>
71+
</Flex>
72+
</IAITooltip>
7373
</PopoverTrigger>
7474
<Portal>
7575
<PopoverContent>

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarFilterButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useEntityFilter } from 'features/controlLayers/hooks/useEntityFilter';
45
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
56
import { isFilterableEntityIdentifier } from 'features/controlLayers/store/types';
@@ -21,16 +22,17 @@ export const EntityListSelectedEntityActionBarFilterButton = memo(() => {
2122
}
2223

2324
return (
24-
<IconButton
25-
onClick={filter.start}
26-
isDisabled={filter.isDisabled}
27-
minW={8}
28-
variant="link"
29-
alignSelf="stretch"
30-
aria-label={t('controlLayers.filter.filter')}
31-
tooltip={t('controlLayers.filter.filter')}
32-
icon={<PiShootingStarFill />}
33-
/>
25+
<IAITooltip label={t('controlLayers.filter.filter')}>
26+
<IconButton
27+
onClick={filter.start}
28+
isDisabled={filter.isDisabled}
29+
minW={8}
30+
variant="link"
31+
alignSelf="stretch"
32+
aria-label={t('controlLayers.filter.filter')}
33+
icon={<PiShootingStarFill />}
34+
/>
35+
</IAITooltip>
3436
);
3537
});
3638

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarInvertMaskButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
45
import { useInvertMask } from 'features/controlLayers/hooks/useInvertMask';
56
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
@@ -23,16 +24,17 @@ export const EntityListSelectedEntityActionBarInvertMaskButton = memo(() => {
2324
}
2425

2526
return (
26-
<IconButton
27-
onClick={invertMask}
28-
isDisabled={isBusy}
29-
minW={8}
30-
variant="link"
31-
alignSelf="stretch"
32-
aria-label={t('controlLayers.invertMask')}
33-
tooltip={t('controlLayers.invertMask')}
34-
icon={<PiSelectionInverseBold />}
35-
/>
27+
<IAITooltip label={t('controlLayers.invertMask')}>
28+
<IconButton
29+
onClick={invertMask}
30+
isDisabled={isBusy}
31+
minW={8}
32+
variant="link"
33+
alignSelf="stretch"
34+
aria-label={t('controlLayers.invertMask')}
35+
icon={<PiSelectionInverseBold />}
36+
/>
37+
</IAITooltip>
3638
);
3739
});
3840

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarSaveToAssetsButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext';
45
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
56
import { useSaveLayerToAssets } from 'features/controlLayers/hooks/useSaveLayerToAssets';
@@ -28,16 +29,17 @@ export const EntityListSelectedEntityActionBarSaveToAssetsButton = memo(() => {
2829
}
2930

3031
return (
31-
<IconButton
32-
onClick={onClick}
33-
isDisabled={!selectedEntityIdentifier || isBusy}
34-
minW={8}
35-
variant="link"
36-
alignSelf="stretch"
37-
aria-label={t('controlLayers.saveLayerToAssets')}
38-
tooltip={t('controlLayers.saveLayerToAssets')}
39-
icon={<PiFloppyDiskBold />}
40-
/>
32+
<IAITooltip label={t('controlLayers.saveLayerToAssets')}>
33+
<IconButton
34+
onClick={onClick}
35+
isDisabled={!selectedEntityIdentifier || isBusy}
36+
minW={8}
37+
variant="link"
38+
alignSelf="stretch"
39+
aria-label={t('controlLayers.saveLayerToAssets')}
40+
icon={<PiFloppyDiskBold />}
41+
/>
42+
</IAITooltip>
4143
);
4244
});
4345

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarSelectObjectButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useEntitySegmentAnything } from 'features/controlLayers/hooks/useEntitySegmentAnything';
45
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
56
import { isSegmentableEntityIdentifier } from 'features/controlLayers/store/types';
@@ -21,16 +22,17 @@ export const EntityListSelectedEntityActionBarSelectObjectButton = memo(() => {
2122
}
2223

2324
return (
24-
<IconButton
25-
onClick={segment.start}
26-
isDisabled={segment.isDisabled}
27-
minW={8}
28-
variant="link"
29-
alignSelf="stretch"
30-
aria-label={t('controlLayers.selectObject.selectObject')}
31-
tooltip={t('controlLayers.selectObject.selectObject')}
32-
icon={<PiShapesFill />}
33-
/>
25+
<IAITooltip label={t('controlLayers.selectObject.selectObject')}>
26+
<IconButton
27+
onClick={segment.start}
28+
isDisabled={segment.isDisabled}
29+
minW={8}
30+
variant="link"
31+
alignSelf="stretch"
32+
aria-label={t('controlLayers.selectObject.selectObject')}
33+
icon={<PiShapesFill />}
34+
/>
35+
</IAITooltip>
3436
);
3537
});
3638

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarTransformButton.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IconButton } from '@invoke-ai/ui-library';
22
import { useAppSelector } from 'app/store/storeHooks';
3+
import { IAITooltip } from 'common/components/IAITooltip';
34
import { useEntityTransform } from 'features/controlLayers/hooks/useEntityTransform';
45
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
56
import { isTransformableEntityIdentifier } from 'features/controlLayers/store/types';
@@ -21,16 +22,17 @@ export const EntityListSelectedEntityActionBarTransformButton = memo(() => {
2122
}
2223

2324
return (
24-
<IconButton
25-
onClick={transform.start}
26-
isDisabled={transform.isDisabled}
27-
minW={8}
28-
variant="link"
29-
alignSelf="stretch"
30-
aria-label={t('controlLayers.transform.transform')}
31-
tooltip={t('controlLayers.transform.transform')}
32-
icon={<PiFrameCornersBold />}
33-
/>
25+
<IAITooltip label={t('controlLayers.transform.transform')}>
26+
<IconButton
27+
onClick={transform.start}
28+
isDisabled={transform.isDisabled}
29+
minW={8}
30+
variant="link"
31+
alignSelf="stretch"
32+
aria-label={t('controlLayers.transform.transform')}
33+
icon={<PiFrameCornersBold />}
34+
/>
35+
</IAITooltip>
3436
);
3537
});
3638

0 commit comments

Comments
 (0)