mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): use stable objects for animation/native element styles
This commit is contained in:
committed by
Kent Keirsey
parent
f5194f9e2d
commit
ca4b8e65c1
@@ -1,5 +1,6 @@
|
||||
import type { ChakraProps } from '@chakra-ui/react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { RgbaColorPicker } from 'react-colorful';
|
||||
import type {
|
||||
@@ -14,20 +15,22 @@ type IAIColorPickerProps = ColorPickerBaseProps<RgbaColor> & {
|
||||
withNumberInput?: boolean;
|
||||
};
|
||||
|
||||
const colorPickerStyles: NonNullable<ChakraProps['sx']> = {
|
||||
const colorPickerPointerStyles: NonNullable<ChakraProps['sx']> = {
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderColor: 'base.100',
|
||||
};
|
||||
|
||||
const sx: ChakraProps['sx'] = {
|
||||
'.react-colorful__hue-pointer': colorPickerStyles,
|
||||
'.react-colorful__saturation-pointer': colorPickerStyles,
|
||||
'.react-colorful__alpha-pointer': colorPickerStyles,
|
||||
'.react-colorful__hue-pointer': colorPickerPointerStyles,
|
||||
'.react-colorful__saturation-pointer': colorPickerPointerStyles,
|
||||
'.react-colorful__alpha-pointer': colorPickerPointerStyles,
|
||||
gap: 2,
|
||||
flexDir: 'column',
|
||||
};
|
||||
|
||||
const colorPickerStyles: CSSProperties = { width: '100%' };
|
||||
|
||||
const numberInputWidth: ChakraProps['w'] = '4.2rem';
|
||||
|
||||
const IAIColorPicker = (props: IAIColorPickerProps) => {
|
||||
@@ -53,7 +56,7 @@ const IAIColorPicker = (props: IAIColorPickerProps) => {
|
||||
<RgbaColorPicker
|
||||
color={color}
|
||||
onChange={onChange}
|
||||
style={{ width: '100%' }}
|
||||
style={colorPickerStyles}
|
||||
{...rest}
|
||||
/>
|
||||
{withNumberInput && (
|
||||
|
||||
@@ -112,7 +112,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
||||
isDisabled: isUploadDisabled,
|
||||
});
|
||||
|
||||
const uploadButtonStyles = useMemo(() => {
|
||||
const uploadButtonStyles = useMemo<SystemStyleObject>(() => {
|
||||
const styles: SystemStyleObject = {
|
||||
minH: minSize,
|
||||
w: 'full',
|
||||
@@ -134,6 +134,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
||||
},
|
||||
});
|
||||
}
|
||||
return styles;
|
||||
}, [isUploadDisabled, minSize]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import type { AnimationProps } from 'framer-motion';
|
||||
import { motion } from 'framer-motion';
|
||||
import type { ReactNode } from 'react';
|
||||
import { memo, useRef } from 'react';
|
||||
@@ -9,23 +10,27 @@ type Props = {
|
||||
label?: ReactNode;
|
||||
};
|
||||
|
||||
const initial: AnimationProps['initial'] = {
|
||||
opacity: 0,
|
||||
};
|
||||
const animate: AnimationProps['animate'] = {
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
};
|
||||
const exit: AnimationProps['exit'] = {
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
};
|
||||
|
||||
export const IAIDropOverlay = (props: Props) => {
|
||||
const { isOver, label = 'Drop' } = props;
|
||||
const motionId = useRef(uuidv4());
|
||||
return (
|
||||
<motion.div
|
||||
key={motionId.current}
|
||||
initial={{
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
initial={initial}
|
||||
animate={animate}
|
||||
exit={exit}
|
||||
>
|
||||
<Flex position="absolute" top={0} insetInlineStart={0} w="full" h="full">
|
||||
<Flex
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import type { AnimationProps } from 'framer-motion';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import type { KeyboardEvent, ReactNode } from 'react';
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
@@ -155,17 +156,9 @@ const ImageUploader = (props: ImageUploaderProps) => {
|
||||
{isDragActive && isHandlingUpload && (
|
||||
<motion.div
|
||||
key="image-upload-overlay"
|
||||
initial={{
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
initial={initial}
|
||||
animate={animate}
|
||||
exit={exit}
|
||||
>
|
||||
<ImageUploadOverlay
|
||||
isDragAccept={isDragAccept}
|
||||
@@ -180,3 +173,15 @@ const ImageUploader = (props: ImageUploaderProps) => {
|
||||
};
|
||||
|
||||
export default memo(ImageUploader);
|
||||
|
||||
const initial: AnimationProps['initial'] = {
|
||||
opacity: 0,
|
||||
};
|
||||
const animate: AnimationProps['animate'] = {
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
};
|
||||
const exit: AnimationProps['exit'] = {
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user