feat(ui): collapsible entity groups

This commit is contained in:
psychedelicious 2024-08-27 17:59:21 +10:00
parent 74791cc490
commit e91c7c5a30
3 changed files with 55 additions and 12 deletions

View File

@ -11,7 +11,7 @@ import { memo } from 'react';
export const CanvasEntityList = memo(() => { export const CanvasEntityList = memo(() => {
return ( return (
<ScrollableContent> <ScrollableContent>
<Flex flexDir="column" gap={4} pt={2} data-testid="control-layers-layer-list" w="full" h="full"> <Flex flexDir="column" gap={2} pt={2} data-testid="control-layers-layer-list" w="full" h="full">
<CanvasEntityOpacity /> <CanvasEntityOpacity />
<InpaintMaskList /> <InpaintMaskList />
<RegionalGuidanceEntityList /> <RegionalGuidanceEntityList />

View File

@ -1,27 +1,65 @@
import { Flex, Spacer, Text } from '@invoke-ai/ui-library'; import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { Button, Collapse, Flex, Icon, Spacer, Text } from '@invoke-ai/ui-library';
import { useBoolean } from 'common/hooks/useBoolean';
import { CanvasEntityTypeIsHiddenToggle } from 'features/controlLayers/components/common/CanvasEntityTypeIsHiddenToggle'; import { CanvasEntityTypeIsHiddenToggle } from 'features/controlLayers/components/common/CanvasEntityTypeIsHiddenToggle';
import { useEntityTypeTitle } from 'features/controlLayers/hooks/useEntityTypeTitle'; import { useEntityTypeTitle } from 'features/controlLayers/hooks/useEntityTypeTitle';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types'; import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import type { PropsWithChildren } from 'react'; import type { PropsWithChildren } from 'react';
import { memo } from 'react'; import { memo } from 'react';
import { PiCaretDownBold } from 'react-icons/pi';
type Props = PropsWithChildren<{ type Props = PropsWithChildren<{
isSelected: boolean; isSelected: boolean;
type: CanvasEntityIdentifier['type']; type: CanvasEntityIdentifier['type'];
}>; }>;
const _hover: SystemStyleObject = {
opacity: 1,
};
export const CanvasEntityGroupList = memo(({ isSelected, type, children }: Props) => { export const CanvasEntityGroupList = memo(({ isSelected, type, children }: Props) => {
const title = useEntityTypeTitle(type); const title = useEntityTypeTitle(type);
const collapse = useBoolean(true);
return ( return (
<Flex flexDir="column" gap={2}> <Flex flexDir="column" w="full">
<Flex justifyContent="space-between" alignItems="center" gap={3}> <Flex w="full">
<Text color={isSelected ? 'base.200' : 'base.500'} fontWeight="semibold" userSelect="none"> <Flex
{title} flexGrow={1}
</Text> as={Button}
<Spacer /> onClick={collapse.toggle}
justifyContent="space-between"
alignItems="center"
gap={3}
variant="unstyled"
p={0}
h={8}
>
<Icon
boxSize={4}
as={PiCaretDownBold}
transform={collapse.isTrue ? undefined : 'rotate(-90deg)'}
fill={isSelected ? 'invokeBlue.300' : 'base.300'}
transitionProperty="common"
transitionDuration="fast"
/>
<Text
fontWeight="semibold"
color={isSelected ? 'invokeBlue.300' : 'base.300'}
userSelect="none"
transitionProperty="common"
transitionDuration="fast"
>
{title}
</Text>
<Spacer />
</Flex>
{type !== 'ip_adapter' && <CanvasEntityTypeIsHiddenToggle type={type} />} {type !== 'ip_adapter' && <CanvasEntityTypeIsHiddenToggle type={type} />}
</Flex> </Flex>
{children} <Collapse in={collapse.isTrue}>
<Flex flexDir="column" gap={2} pt={2}>
{children}
</Flex>
</Collapse>
</Flex> </Flex>
); );
}); });

View File

@ -4,6 +4,7 @@ import { useEntityTypeIsHidden } from 'features/controlLayers/hooks/useEntityTyp
import { useEntityTypeString } from 'features/controlLayers/hooks/useEntityTypeString'; import { useEntityTypeString } from 'features/controlLayers/hooks/useEntityTypeString';
import { allEntitiesOfTypeIsHiddenToggled } from 'features/controlLayers/store/canvasSlice'; import { allEntitiesOfTypeIsHiddenToggled } from 'features/controlLayers/store/canvasSlice';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types'; import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import type { MouseEventHandler } from 'react';
import { memo, useCallback } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi'; import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
@ -17,9 +18,13 @@ export const CanvasEntityTypeIsHiddenToggle = memo(({ type }: Props) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const isHidden = useEntityTypeIsHidden(type); const isHidden = useEntityTypeIsHidden(type);
const typeString = useEntityTypeString(type); const typeString = useEntityTypeString(type);
const onClick = useCallback(() => { const onClick = useCallback<MouseEventHandler>(
dispatch(allEntitiesOfTypeIsHiddenToggled({ type })); (e) => {
}, [dispatch, type]); e.stopPropagation();
dispatch(allEntitiesOfTypeIsHiddenToggled({ type }));
},
[dispatch, type]
);
return ( return (
<IconButton <IconButton