mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): rp ui styling
This commit is contained in:
parent
c613839740
commit
d43f9732ab
@ -1519,6 +1519,8 @@
|
|||||||
"regionalPrompts": "Regional Prompts",
|
"regionalPrompts": "Regional Prompts",
|
||||||
"enableRegionalPrompts": "Enable $t(regionalPrompts.regionalPrompts)",
|
"enableRegionalPrompts": "Enable $t(regionalPrompts.regionalPrompts)",
|
||||||
"layerOpacity": "Layer Opacity",
|
"layerOpacity": "Layer Opacity",
|
||||||
"autoNegative": "Auto Negative"
|
"autoNegative": "Auto Negative",
|
||||||
|
"toggleVisibility": "Toggle Layer Visibility",
|
||||||
|
"resetRegion": "Reset Region"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import { ButtonGroup, IconButton } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
|
import { layerDeleted, rpLayerReset } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { PiArrowCounterClockwiseBold, PiTrashSimpleBold } from 'react-icons/pi';
|
||||||
|
|
||||||
|
type Props = { layerId: string };
|
||||||
|
|
||||||
|
export const RPLayerActionsButtonGroup = memo(({ layerId }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const deleteLayer = useCallback(() => {
|
||||||
|
dispatch(layerDeleted(layerId));
|
||||||
|
}, [dispatch, layerId]);
|
||||||
|
const resetLayer = useCallback(() => {
|
||||||
|
dispatch(rpLayerReset(layerId));
|
||||||
|
}, [dispatch, layerId]);
|
||||||
|
return (
|
||||||
|
<ButtonGroup isAttached={false}>
|
||||||
|
<IconButton
|
||||||
|
size="sm"
|
||||||
|
aria-label={t('regionalPrompts.resetRegion')}
|
||||||
|
tooltip={t('regionalPrompts.resetRegion')}
|
||||||
|
icon={<PiArrowCounterClockwiseBold />}
|
||||||
|
onClick={resetLayer}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
size="sm"
|
||||||
|
colorScheme="error"
|
||||||
|
aria-label={t('common.delete')}
|
||||||
|
tooltip={t('common.delete')}
|
||||||
|
icon={<PiTrashSimpleBold />}
|
||||||
|
onClick={deleteLayer}
|
||||||
|
/>
|
||||||
|
</ButtonGroup>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
RPLayerActionsButtonGroup.displayName = 'RPLayerActionsButtonGroup';
|
@ -9,6 +9,7 @@ import {
|
|||||||
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { RgbColor } from 'react-colorful';
|
import type { RgbColor } from 'react-colorful';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiEyedropperBold } from 'react-icons/pi';
|
import { PiEyedropperBold } from 'react-icons/pi';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const RPLayerColorPicker = memo(({ layerId }: Props) => {
|
export const RPLayerColorPicker = memo(({ layerId }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const selectColor = useMemo(
|
const selectColor = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => {
|
createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => {
|
||||||
@ -37,7 +39,13 @@ export const RPLayerColorPicker = memo(({ layerId }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Popover isLazy>
|
<Popover isLazy>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<IconButton aria-label="color picker" size="sm" borderRadius="base" icon={<PiEyedropperBold />} />
|
<IconButton
|
||||||
|
tooltip={t('unifiedCanvas.colorPicker')}
|
||||||
|
aria-label={t('unifiedCanvas.colorPicker')}
|
||||||
|
size="sm"
|
||||||
|
borderRadius="base"
|
||||||
|
icon={<PiEyedropperBold />}
|
||||||
|
/>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<PopoverBody minH={64}>
|
<PopoverBody minH={64}>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { rgbColorToString } from 'features/canvas/util/colorToString';
|
import { rgbColorToString } from 'features/canvas/util/colorToString';
|
||||||
|
import { RPLayerActionsButtonGroup } from 'features/regionalPrompts/components/RPLayerActionsButtonGroup';
|
||||||
import { RPLayerAutoNegativeCombobox } from 'features/regionalPrompts/components/RPLayerAutoNegativeCombobox';
|
import { RPLayerAutoNegativeCombobox } from 'features/regionalPrompts/components/RPLayerAutoNegativeCombobox';
|
||||||
import { RPLayerColorPicker } from 'features/regionalPrompts/components/RPLayerColorPicker';
|
import { RPLayerColorPicker } from 'features/regionalPrompts/components/RPLayerColorPicker';
|
||||||
import { RPLayerMenu } from 'features/regionalPrompts/components/RPLayerMenu';
|
import { RPLayerMenu } from 'features/regionalPrompts/components/RPLayerMenu';
|
||||||
@ -39,11 +40,12 @@ export const RPLayerListItem = memo(({ layerId }: Props) => {
|
|||||||
>
|
>
|
||||||
<Flex flexDir="column" gap={2} w="full" bg="base.850" borderRadius="base" p={2}>
|
<Flex flexDir="column" gap={2} w="full" bg="base.850" borderRadius="base" p={2}>
|
||||||
<Flex gap={2} alignItems="center">
|
<Flex gap={2} alignItems="center">
|
||||||
|
<RPLayerMenu layerId={layerId} />
|
||||||
<RPLayerColorPicker layerId={layerId} />
|
<RPLayerColorPicker layerId={layerId} />
|
||||||
<RPLayerVisibilityToggle layerId={layerId} />
|
<RPLayerVisibilityToggle layerId={layerId} />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<RPLayerAutoNegativeCombobox layerId={layerId} />
|
<RPLayerAutoNegativeCombobox layerId={layerId} />
|
||||||
<RPLayerMenu layerId={layerId} />
|
<RPLayerActionsButtonGroup layerId={layerId} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<RPLayerPositivePrompt layerId={layerId} />
|
<RPLayerPositivePrompt layerId={layerId} />
|
||||||
<RPLayerNegativePrompt layerId={layerId} />
|
<RPLayerNegativePrompt layerId={layerId} />
|
||||||
|
@ -3,6 +3,7 @@ import { useAppDispatch } from 'app/store/storeHooks';
|
|||||||
import { useLayerIsVisible } from 'features/regionalPrompts/hooks/layerStateHooks';
|
import { useLayerIsVisible } from 'features/regionalPrompts/hooks/layerStateHooks';
|
||||||
import { rpLayerIsVisibleToggled } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
import { rpLayerIsVisibleToggled } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
|
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -10,6 +11,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => {
|
export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isVisible = useLayerIsVisible(layerId);
|
const isVisible = useLayerIsVisible(layerId);
|
||||||
const onClick = useCallback(() => {
|
const onClick = useCallback(() => {
|
||||||
@ -19,7 +21,8 @@ export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
aria-label="Toggle layer visibility"
|
aria-label={t('regionalPrompts.toggleVisibility')}
|
||||||
|
tooltip={t('regionalPrompts.toggleVisibility')}
|
||||||
variant={isVisible ? 'outline' : 'ghost'}
|
variant={isVisible ? 'outline' : 'ghost'}
|
||||||
icon={isVisible ? <PiEyeBold /> : <PiEyeClosedBold />}
|
icon={isVisible ? <PiEyeBold /> : <PiEyeClosedBold />}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library';
|
import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import { AddLayerButton } from 'features/regionalPrompts/components/AddLayerButton';
|
import { AddLayerButton } from 'features/regionalPrompts/components/AddLayerButton';
|
||||||
import { BrushSize } from 'features/regionalPrompts/components/BrushSize';
|
import { BrushSize } from 'features/regionalPrompts/components/BrushSize';
|
||||||
import { DeleteAllLayersButton } from 'features/regionalPrompts/components/DeleteAllLayersButton';
|
import { DeleteAllLayersButton } from 'features/regionalPrompts/components/DeleteAllLayersButton';
|
||||||
@ -43,10 +44,14 @@ export const RegionalPromptsEditor = memo(() => {
|
|||||||
<RPEnabledSwitch />
|
<RPEnabledSwitch />
|
||||||
<BrushSize />
|
<BrushSize />
|
||||||
<PromptLayerOpacity />
|
<PromptLayerOpacity />
|
||||||
|
<ScrollableContent>
|
||||||
|
<Flex flexDir="column" gap={2}>
|
||||||
{rpLayerIdsReversed.map((id) => (
|
{rpLayerIdsReversed.map((id) => (
|
||||||
<RPLayerListItem key={id} layerId={id} />
|
<RPLayerListItem key={id} layerId={id} />
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</ScrollableContent>
|
||||||
|
</Flex>
|
||||||
<StageComponent />
|
<StageComponent />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -7,9 +7,12 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
const TextToImageTab = () => {
|
const TextToImageTab = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const noOfRPLayers = useAppSelector(
|
const noOfRPLayers = useAppSelector((s) => {
|
||||||
(s) => s.regionalPrompts.present.layers.filter((l) => l.kind === 'regionalPromptLayer' && l.isVisible).length
|
if (!s.regionalPrompts.present.isEnabled) {
|
||||||
);
|
return 0;
|
||||||
|
}
|
||||||
|
return s.regionalPrompts.present.layers.filter((l) => l.kind === 'regionalPromptLayer' && l.isVisible).length;
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<Box position="relative" w="full" h="full" p={2} borderRadius="base">
|
<Box position="relative" w="full" h="full" p={2} borderRadius="base">
|
||||||
<Tabs variant="line" isLazy={true} display="flex" flexDir="column" w="full" h="full">
|
<Tabs variant="line" isLazy={true} display="flex" flexDir="column" w="full" h="full">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user