From fc39f35cedfcd8ca02d3ded641d3d86c80a48a7c Mon Sep 17 00:00:00 2001 From: Balaji Krishnamurthy <107975017+BKM14@users.noreply.github.com> Date: Wed, 20 Aug 2025 15:39:06 +0530 Subject: [PATCH] Animate between IconX and IconReload (#13949) Closes #13866 An animation of 150ms has been introduced to all icons that are rendered inside `OverridableCheckbox`. Attaching a recording of the same. [Loom Recording](https://www.loom.com/share/65293c13171a4bf8934c577eecbca9a0) --- .../components/OverridableCheckbox.tsx | 29 ++++++++---- .../animation/components/AnimatedRotate.tsx | 46 +++++++++++++++++++ packages/twenty-ui/src/utilities/index.ts | 1 + 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 packages/twenty-ui/src/utilities/animation/components/AnimatedRotate.tsx diff --git a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/OverridableCheckbox.tsx b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/OverridableCheckbox.tsx index d899505585..1b76ce1798 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/OverridableCheckbox.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/OverridableCheckbox.tsx @@ -2,6 +2,7 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { IconReload, IconX } from 'twenty-ui/display'; import { Checkbox } from 'twenty-ui/input'; +import { AnimatedRotate } from 'twenty-ui/utilities'; export type OverridableCheckboxType = 'default' | 'override' | 'no_cta'; @@ -60,10 +61,12 @@ export const OverridableCheckbox = ({ isDisabled={disabled} > {!disabled && ( - + + + )} @@ -79,17 +82,25 @@ export const OverridableCheckbox = ({ onClick={disabled ? undefined : onChange} isDisabled={disabled} > - + + + )} {type === 'no_cta' && ( - + + + )} diff --git a/packages/twenty-ui/src/utilities/animation/components/AnimatedRotate.tsx b/packages/twenty-ui/src/utilities/animation/components/AnimatedRotate.tsx new file mode 100644 index 0000000000..aaa3fb8c42 --- /dev/null +++ b/packages/twenty-ui/src/utilities/animation/components/AnimatedRotate.tsx @@ -0,0 +1,46 @@ +import { useTheme } from '@emotion/react'; +import { type AnimationDuration } from '@ui/theme'; +import { type HTMLMotionProps, motion } from 'framer-motion'; + +type AnimatedRotateProps = Omit< + HTMLMotionProps<'div'>, + 'initial' | 'animate' | 'transition' | 'exit' +> & { + duration?: AnimationDuration; + animateOnHover?: boolean; +}; + +export const AnimatedRotate = ({ + children, + duration = 'fast', + animateOnHover, +}: AnimatedRotateProps): JSX.Element => { + const theme = useTheme(); + const initial = { opacity: 0, rotate: -90 }; + const animate = { opacity: 1, rotate: 0 }; + const exit = { opacity: 0, rotate: 90 }; + const transition = { + duration: theme.animation.duration[duration], + }; + + return ( + + {children} + + ); +}; diff --git a/packages/twenty-ui/src/utilities/index.ts b/packages/twenty-ui/src/utilities/index.ts index 4ad512a6d3..19f114593e 100644 --- a/packages/twenty-ui/src/utilities/index.ts +++ b/packages/twenty-ui/src/utilities/index.ts @@ -12,6 +12,7 @@ export { AnimatedContainer } from './animation/components/AnimatedContainer'; export { AnimatedEaseIn } from './animation/components/AnimatedEaseIn'; export { AnimatedEaseInOut } from './animation/components/AnimatedEaseInOut'; export { AnimatedFadeOut } from './animation/components/AnimatedFadeOut'; +export { AnimatedRotate } from './animation/components/AnimatedRotate'; export { AnimatedTextWord } from './animation/components/AnimatedTextWord'; export { AnimatedTranslation } from './animation/components/AnimatedTranslation'; export { stringToHslColor } from './color/utils/stringToHslColor';