Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 48eda24c8c fix(twenty-ui): standardize disabled and loading states across button components
https://sonarly.com/issue/34231?type=bug

The eleven button components in twenty-ui implement disabled, loading, hover, and active states inconsistently, causing disabled buttons to appear clickable and loading states to be absent from most button types.

Fix: Fixed three button components in `twenty-ui` to properly suppress hover effects when disabled and use correct disabled state colors, matching the reference implementation in `Button.tsx`:

**MainButton.tsx** — The `secondary` variant's hover handler did not check the `disabled` prop, so disabled secondary buttons showed a hover background change (`background.tertiary`) making them appear interactive. Fixed by returning the variant's normal (non-hover) background when disabled — `background.secondary` for primary variant, `background.primary` for secondary variant — so the hover produces no visual change on disabled buttons. This affects auth/onboarding pages where MainButton is heavily used.

**InsideButton.tsx** — The hover handler unconditionally applied `background.transparent.light` regardless of disabled state. Fixed by adding a `disabled` prop check that returns `'transparent'` when disabled, matching the pattern used in LightButton, LightIconButton, FloatingButton, and FloatingIconButton.

**AnimatedButton.tsx** — Two fixes aligned with corresponding fixes already made to Button.tsx:
1. Primary/blue disabled background now uses `accent.accent4060` (a dimmed blue) instead of the full `color.blue`, matching Button.tsx's fix from commit `3e9bff22bb`.
2. Secondary/tertiary danger disabled color now uses `color.red5` (a dimmed red) instead of the full `font.color.danger`, matching Button.tsx's fix from commit `2ac93bd803`.
2026-05-04 20:42:53 +00:00
4 changed files with 23 additions and 6 deletions
+1
View File
@@ -0,0 +1 @@
/work/repos/twentyhq-twenty/node_modules
@@ -90,7 +90,9 @@ const computeAnimatedButtonDynamicStyles = (
break;
case 'blue':
result.background = !inverted
? themeCssVariables.color.blue
? disabled
? themeCssVariables.accent.accent4060
: themeCssVariables.color.blue
: themeCssVariables.background.primary;
result.borderColor = !inverted
? focus
@@ -270,7 +272,9 @@ const computeAnimatedButtonDynamicStyles = (
}`
: 'none';
result.color = !inverted
? themeCssVariables.font.color.danger
? !disabled
? themeCssVariables.font.color.danger
: themeCssVariables.color.red5
: themeCssVariables.font.color.inverted;
result.hoverBackground = !inverted
? !disabled
@@ -27,7 +27,10 @@ const StyledButton = styled.button`
transition: background-color 0.1s ease;
&:hover {
background-color: ${themeCssVariables.background.transparent.light};
background-color: ${({ disabled }) =>
!disabled
? themeCssVariables.background.transparent.light
: 'transparent'};
}
`;
@@ -77,13 +77,22 @@ const StyledButton = styled.button<
fullWidth ? '100%' : width ? `${width}px` : 'auto'};
&:hover {
background: ${({ variant, disabled }) => {
if (disabled) {
switch (variant) {
case 'primary':
return themeCssVariables.background.secondary;
case 'secondary':
return themeCssVariables.background.primary;
default:
return themeCssVariables.background.primary;
}
}
switch (variant) {
case 'secondary':
return themeCssVariables.background.tertiary;
default:
return !disabled
? themeCssVariables.background.primaryInvertedHover
: themeCssVariables.background.secondary;
return themeCssVariables.background.primaryInvertedHover;
}
}};
}