feat(ui): animations for send to alerts

This commit is contained in:
psychedelicious
2024-09-12 23:16:55 +10:00
parent dd3013d333
commit 82df16d8ce

View File

@@ -10,6 +10,7 @@ import {
Spacer,
} from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useBoolean } from 'common/hooks/useBoolean';
import {
setRightPanelTabToGallery,
setRightPanelTabToLayers,
@@ -18,31 +19,12 @@ import { useImageViewer } from 'features/gallery/components/ImageViewer/useImage
import { useCurrentDestination } from 'features/queue/hooks/useCurrentDestination';
import { selectShowSendToAlerts, showSendToAlertsChanged } from 'features/system/store/systemSlice';
import { setActiveTab } from 'features/ui/store/uiSlice';
import type { PropsWithChildren } from 'react';
import { useCallback } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import type { PropsWithChildren, ReactNode } from 'react';
import { useCallback, useMemo } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { PiXBold } from 'react-icons/pi';
const DontShowMeTheseAgainButton = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
dispatch(showSendToAlertsChanged(false));
}, [dispatch]);
return (
<IconButton
variant="link"
icon={<Icon as={PiXBold} fill="base.50 !important" />}
tooltip={t('common.dontShowMeThese')}
aria-label={t('common.dontShowMeThese')}
right={-1}
top={-2}
onClick={onClick}
minW="auto"
/>
);
};
const ActivateImageViewerButton = (props: PropsWithChildren) => {
const imageViewer = useImageViewer();
const onClick = useCallback(() => {
@@ -59,32 +41,26 @@ const ActivateImageViewerButton = (props: PropsWithChildren) => {
export const SendingToGalleryAlert = () => {
const { t } = useTranslation();
const destination = useCurrentDestination();
const showSendToAlerts = useAppSelector(selectShowSendToAlerts);
const isVisible = useMemo(() => {
if (!destination) {
return false;
}
if (!showSendToAlerts) {
return null;
}
if (destination === 'canvas') {
return false;
}
if (!destination) {
return null;
}
if (destination === 'canvas') {
return null;
}
return true;
}, [destination]);
return (
<Alert status="warning" flexDir="column" pointerEvents="auto" borderRadius="base" fontSize="sm" shadow="md">
<Flex w="full" alignItems="center">
<AlertIcon />
<AlertTitle>{t('controlLayers.sendingToGallery')}</AlertTitle>
<Spacer />
<DontShowMeTheseAgainButton />
</Flex>
<AlertDescription>
<AlertWrapper
title={t('controlLayers.sendingToGallery')}
description={
<Trans i18nKey="controlLayers.viewProgressInViewer" components={{ Btn: <ActivateImageViewerButton /> }} />
</AlertDescription>
</Alert>
}
isVisible={isVisible}
/>
);
};
@@ -106,31 +82,80 @@ const ActivateCanvasButton = (props: PropsWithChildren) => {
export const SendingToCanvasAlert = () => {
const { t } = useTranslation();
const destination = useCurrentDestination();
const showSendToAlerts = useAppSelector(selectShowSendToAlerts);
const isVisible = useMemo(() => {
if (!destination) {
return false;
}
if (!showSendToAlerts) {
return null;
}
if (destination !== 'canvas') {
return false;
}
if (!destination) {
return null;
}
if (destination !== 'canvas') {
return null;
}
return true;
}, [destination]);
return (
<Alert status="warning" flexDir="column" pointerEvents="auto" borderRadius="base" fontSize="sm" shadow="md">
<Flex w="full" alignItems="center">
<AlertIcon />
<AlertTitle>{t('controlLayers.sendingToCanvas')}</AlertTitle>
<Spacer />
<DontShowMeTheseAgainButton />
</Flex>
<AlertDescription>
<AlertWrapper
title={t('controlLayers.sendingToCanvas')}
description={
<Trans i18nKey="controlLayers.viewProgressOnCanvas" components={{ Btn: <ActivateCanvasButton /> }} />
</AlertDescription>
</Alert>
}
isVisible={isVisible}
/>
);
};
const AlertWrapper = ({
title,
description,
isVisible,
}: {
title: ReactNode;
description: ReactNode;
isVisible: boolean;
}) => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const showSendToAlerts = useAppSelector(selectShowSendToAlerts);
const isHovered = useBoolean(false);
const onClickDontShowMeThese = useCallback(() => {
dispatch(showSendToAlertsChanged(false));
isHovered.setFalse();
}, [dispatch, isHovered]);
return (
<AnimatePresence>
{(isVisible || isHovered.isTrue) && showSendToAlerts && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { duration: 0.1, ease: 'easeOut' } }}
exit={{
opacity: 0,
transition: { duration: 0.1, delay: !isHovered.isTrue ? 1 : 0.1, ease: 'easeIn' },
}}
onMouseEnter={isHovered.setTrue}
onMouseLeave={isHovered.setFalse}
>
<Alert status="warning" flexDir="column" pointerEvents="auto" borderRadius="base" fontSize="sm" shadow="md">
<Flex w="full" alignItems="center">
<AlertIcon />
<AlertTitle>{title}</AlertTitle>
<Spacer />
<IconButton
variant="link"
icon={<Icon as={PiXBold} fill="base.50 !important" />}
tooltip={t('common.dontShowMeThese')}
aria-label={t('common.dontShowMeThese')}
right={-1}
top={-2}
onClick={onClickDontShowMeThese}
minW="auto"
/>
</Flex>
<AlertDescription>{description}</AlertDescription>
</Alert>
</motion.div>
)}
</AnimatePresence>
);
};