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",
|
||||
"enableRegionalPrompts": "Enable $t(regionalPrompts.regionalPrompts)",
|
||||
"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';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import type { RgbColor } from 'react-colorful';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiEyedropperBold } from 'react-icons/pi';
|
||||
import { assert } from 'tsafe';
|
||||
|
||||
@ -17,6 +18,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const RPLayerColorPicker = memo(({ layerId }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const selectColor = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => {
|
||||
@ -37,7 +39,13 @@ export const RPLayerColorPicker = memo(({ layerId }: Props) => {
|
||||
return (
|
||||
<Popover isLazy>
|
||||
<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>
|
||||
<PopoverContent>
|
||||
<PopoverBody minH={64}>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { rgbColorToString } from 'features/canvas/util/colorToString';
|
||||
import { RPLayerActionsButtonGroup } from 'features/regionalPrompts/components/RPLayerActionsButtonGroup';
|
||||
import { RPLayerAutoNegativeCombobox } from 'features/regionalPrompts/components/RPLayerAutoNegativeCombobox';
|
||||
import { RPLayerColorPicker } from 'features/regionalPrompts/components/RPLayerColorPicker';
|
||||
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 gap={2} alignItems="center">
|
||||
<RPLayerMenu layerId={layerId} />
|
||||
<RPLayerColorPicker layerId={layerId} />
|
||||
<RPLayerVisibilityToggle layerId={layerId} />
|
||||
<Spacer />
|
||||
<RPLayerAutoNegativeCombobox layerId={layerId} />
|
||||
<RPLayerMenu layerId={layerId} />
|
||||
<RPLayerActionsButtonGroup layerId={layerId} />
|
||||
</Flex>
|
||||
<RPLayerPositivePrompt layerId={layerId} />
|
||||
<RPLayerNegativePrompt layerId={layerId} />
|
||||
|
@ -3,6 +3,7 @@ import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useLayerIsVisible } from 'features/regionalPrompts/hooks/layerStateHooks';
|
||||
import { rpLayerIsVisibleToggled } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
|
||||
|
||||
type Props = {
|
||||
@ -10,6 +11,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const isVisible = useLayerIsVisible(layerId);
|
||||
const onClick = useCallback(() => {
|
||||
@ -19,7 +21,8 @@ export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => {
|
||||
return (
|
||||
<IconButton
|
||||
size="sm"
|
||||
aria-label="Toggle layer visibility"
|
||||
aria-label={t('regionalPrompts.toggleVisibility')}
|
||||
tooltip={t('regionalPrompts.toggleVisibility')}
|
||||
variant={isVisible ? 'outline' : 'ghost'}
|
||||
icon={isVisible ? <PiEyeBold /> : <PiEyeClosedBold />}
|
||||
onClick={onClick}
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { AddLayerButton } from 'features/regionalPrompts/components/AddLayerButton';
|
||||
import { BrushSize } from 'features/regionalPrompts/components/BrushSize';
|
||||
import { DeleteAllLayersButton } from 'features/regionalPrompts/components/DeleteAllLayersButton';
|
||||
@ -43,9 +44,13 @@ export const RegionalPromptsEditor = memo(() => {
|
||||
<RPEnabledSwitch />
|
||||
<BrushSize />
|
||||
<PromptLayerOpacity />
|
||||
{rpLayerIdsReversed.map((id) => (
|
||||
<RPLayerListItem key={id} layerId={id} />
|
||||
))}
|
||||
<ScrollableContent>
|
||||
<Flex flexDir="column" gap={2}>
|
||||
{rpLayerIdsReversed.map((id) => (
|
||||
<RPLayerListItem key={id} layerId={id} />
|
||||
))}
|
||||
</Flex>
|
||||
</ScrollableContent>
|
||||
</Flex>
|
||||
<StageComponent />
|
||||
</Flex>
|
||||
|
@ -7,9 +7,12 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
const TextToImageTab = () => {
|
||||
const { t } = useTranslation();
|
||||
const noOfRPLayers = useAppSelector(
|
||||
(s) => s.regionalPrompts.present.layers.filter((l) => l.kind === 'regionalPromptLayer' && l.isVisible).length
|
||||
);
|
||||
const noOfRPLayers = useAppSelector((s) => {
|
||||
if (!s.regionalPrompts.present.isEnabled) {
|
||||
return 0;
|
||||
}
|
||||
return s.regionalPrompts.present.layers.filter((l) => l.kind === 'regionalPromptLayer' && l.isVisible).length;
|
||||
});
|
||||
return (
|
||||
<Box position="relative" w="full" h="full" p={2} borderRadius="base">
|
||||
<Tabs variant="line" isLazy={true} display="flex" flexDir="column" w="full" h="full">
|
||||
|
Loading…
Reference in New Issue
Block a user