mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
fix(ui): floating button tooltip orientations
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
"previousImage": "Previous Image",
|
||||
"reset": "Reset",
|
||||
"resetUI": "$t(accessibility.reset) UI",
|
||||
"showGalleryPanel": "Show Gallery Panel",
|
||||
"showOptionsPanel": "Show Side Panel",
|
||||
"toggleRightPanel": "Toggle Right Panel (T)",
|
||||
"toggleLeftPanel": "Toggle Left Panel (G)",
|
||||
"uploadImage": "Upload Image"
|
||||
},
|
||||
"boards": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolBboxButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.bbox')} (C)`}
|
||||
tooltip={`${t('controlLayers.tool.bbox')} (C)`}
|
||||
icon={<PiBoundingBoxBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectBbox}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.bbox')} (C)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.bbox')} (C)`}
|
||||
icon={<PiBoundingBoxBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectBbox}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolBrushButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.brush')} (B)`}
|
||||
tooltip={`${t('controlLayers.tool.brush')} (B)`}
|
||||
icon={<PiPaintBrushBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectBrush}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.brush')} (B)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.brush')} (B)`}
|
||||
icon={<PiPaintBrushBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectBrush}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolColorPickerButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.colorPicker')} (I)`}
|
||||
tooltip={`${t('controlLayers.tool.colorPicker')} (I)`}
|
||||
icon={<PiEyedropperBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectColorPicker}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.colorPicker')} (I)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.colorPicker')} (I)`}
|
||||
icon={<PiEyedropperBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectColorPicker}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolEraserButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.eraser')} (E)`}
|
||||
tooltip={`${t('controlLayers.tool.eraser')} (E)`}
|
||||
icon={<PiEraserBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectEraser}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.eraser')} (E)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.eraser')} (E)`}
|
||||
icon={<PiEraserBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectEraser}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolMoveButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.move')} (V)`}
|
||||
tooltip={`${t('controlLayers.tool.move')} (V)`}
|
||||
icon={<PiCursorBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectMove}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.move')} (V)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.move')} (V)`}
|
||||
icon={<PiCursorBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectMove}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolRectButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.rectangle')} (U)`}
|
||||
tooltip={`${t('controlLayers.tool.rectangle')} (U)`}
|
||||
icon={<PiRectangleBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectRect}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.rectangle')} (U)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.rectangle')} (U)`}
|
||||
icon={<PiRectangleBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectRect}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
@@ -21,14 +21,15 @@ export const ToolViewButton = memo(() => {
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.view')} (H)`}
|
||||
tooltip={`${t('controlLayers.tool.view')} (H)`}
|
||||
icon={<PiHandBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectView}
|
||||
/>
|
||||
<Tooltip label={`${t('controlLayers.tool.view')} (H)`} placement="end">
|
||||
<IconButton
|
||||
aria-label={`${t('controlLayers.tool.view')} (H)`}
|
||||
icon={<PiHandBold />}
|
||||
colorScheme={isSelected ? 'invokeBlue' : 'base'}
|
||||
variant="solid"
|
||||
onClick={selectView}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { TooltipProps} from '@invoke-ai/ui-library';
|
||||
import { Divider, Flex, ListItem, Text, Tooltip, UnorderedList } from '@invoke-ai/ui-library';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
@@ -20,19 +21,19 @@ const selectPromptsCount = createSelector(selectParamsSlice, selectDynamicPrompt
|
||||
getShouldProcessPrompt(params.positivePrompt) ? dynamicPrompts.prompts.length : 1
|
||||
);
|
||||
|
||||
type Props = {
|
||||
type Props = TooltipProps & {
|
||||
prepend?: boolean;
|
||||
};
|
||||
|
||||
export const QueueButtonTooltip = (props: PropsWithChildren<Props>) => {
|
||||
export const QueueButtonTooltip = ({ prepend, children, ...rest }: PropsWithChildren<Props>) => {
|
||||
return (
|
||||
<Tooltip label={<TooltipContent prepend={props.prepend} />} maxW={512}>
|
||||
{props.children}
|
||||
<Tooltip label={<TooltipContent prepend={prepend} />} maxW={512} {...rest}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const TooltipContent = memo(({ prepend = false }: Props) => {
|
||||
const TooltipContent = memo(({ prepend = false }: { prepend?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { isReady, reasons } = useIsReadyToEnqueue();
|
||||
const sendToCanvas = useAppSelector(selectSendToCanvas);
|
||||
|
||||
@@ -13,9 +13,9 @@ const FloatingGalleryButton = (props: Props) => {
|
||||
|
||||
return (
|
||||
<Flex pos="absolute" transform="translate(0, -50%)" minW={8} top="50%" insetInlineEnd={2}>
|
||||
<Tooltip label={t('accessibility.showGalleryPanel')} placement="start">
|
||||
<Tooltip label={t('accessibility.toggleRightPanel')} placement="start">
|
||||
<IconButton
|
||||
aria-label={t('accessibility.showGalleryPanel')}
|
||||
aria-label={t('accessibility.toggleRightPanel')}
|
||||
onClick={props.panelApi.toggle}
|
||||
icon={<PiImagesSquareBold />}
|
||||
h={48}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ButtonGroup, Flex, Icon, IconButton, spinAnimation, useShiftModifier } from '@invoke-ai/ui-library';
|
||||
import { ButtonGroup, Flex, Icon, IconButton, spinAnimation, Tooltip, useShiftModifier } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { ToolChooser } from 'features/controlLayers/components/Tool/ToolChooser';
|
||||
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
@@ -54,14 +54,15 @@ const FloatingSidePanelButtons = (props: Props) => {
|
||||
</CanvasManagerProviderGate>
|
||||
)}
|
||||
<ButtonGroup orientation="vertical" h={48}>
|
||||
<IconButton
|
||||
tooltip={t('accessibility.showOptionsPanel')}
|
||||
aria-label={t('accessibility.showOptionsPanel')}
|
||||
onClick={props.panelApi.toggle}
|
||||
icon={<PiSlidersHorizontalBold />}
|
||||
flexGrow={1}
|
||||
/>
|
||||
<QueueButtonTooltip prepend={shift}>
|
||||
<Tooltip label={t('accessibility.toggleLeftPanel')} placement="end">
|
||||
<IconButton
|
||||
aria-label={t('accessibility.toggleLeftPanel')}
|
||||
onClick={props.panelApi.toggle}
|
||||
icon={<PiSlidersHorizontalBold />}
|
||||
flexGrow={1}
|
||||
/>
|
||||
</Tooltip>
|
||||
<QueueButtonTooltip prepend={shift} placement="end">
|
||||
<IconButton
|
||||
aria-label={t('queue.queueBack')}
|
||||
onClick={shift ? queue.queueFront : queue.queueBack}
|
||||
@@ -72,27 +73,30 @@ const FloatingSidePanelButtons = (props: Props) => {
|
||||
flexGrow={1}
|
||||
/>
|
||||
</QueueButtonTooltip>
|
||||
<IconButton
|
||||
isDisabled={cancelCurrent.isDisabled}
|
||||
isLoading={cancelCurrent.isLoading}
|
||||
aria-label={t('queue.cancel')}
|
||||
tooltip={t('queue.cancelTooltip')}
|
||||
icon={<PiXBold />}
|
||||
onClick={cancelCurrent.cancelQueueItem}
|
||||
colorScheme="error"
|
||||
flexGrow={1}
|
||||
/>
|
||||
<IconButton
|
||||
isDisabled={clearQueue.isDisabled}
|
||||
isLoading={clearQueue.isLoading}
|
||||
aria-label={t('queue.clear')}
|
||||
tooltip={t('queue.clearTooltip')}
|
||||
icon={<PiTrashSimpleBold />}
|
||||
colorScheme="error"
|
||||
onClick={clearQueue.openDialog}
|
||||
data-testid={t('queue.clear')}
|
||||
flexGrow={1}
|
||||
/>
|
||||
<Tooltip label={t('queue.cancelTooltip')} placement="end">
|
||||
<IconButton
|
||||
isDisabled={cancelCurrent.isDisabled}
|
||||
isLoading={cancelCurrent.isLoading}
|
||||
aria-label={t('queue.cancelTooltip')}
|
||||
icon={<PiXBold />}
|
||||
onClick={cancelCurrent.cancelQueueItem}
|
||||
colorScheme="error"
|
||||
flexGrow={1}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label={t('queue.clearTooltip')} placement="end">
|
||||
<IconButton
|
||||
isDisabled={clearQueue.isDisabled}
|
||||
isLoading={clearQueue.isLoading}
|
||||
aria-label={t('queue.clearTooltip')}
|
||||
icon={<PiTrashSimpleBold />}
|
||||
colorScheme="error"
|
||||
onClick={clearQueue.openDialog}
|
||||
data-testid={t('queue.clear')}
|
||||
flexGrow={1}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user