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';