From a6ded6984f4ec37f94b22ac4f9157cfe5ee71b78 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Wed, 12 Aug 2026 11:18:38 +0530 Subject: [PATCH 1/9] fix: remove reanimated library from FAB --- .../package.json | 3 +- .../src/FloatingActionButton.tsx | 83 ++++--- .../__tests__/FloatingActionButton.spec.tsx | 10 - .../FloatingActionButton.spec.tsx.snap | 217 ++++++++---------- pnpm-lock.yaml | 41 ---- 5 files changed, 141 insertions(+), 213 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/package.json b/packages/pluggableWidgets/floating-action-button-native/package.json index 5db19bcef..e99ce1a07 100644 --- a/packages/pluggableWidgets/floating-action-button-native/package.json +++ b/packages/pluggableWidgets/floating-action-button-native/package.json @@ -20,8 +20,7 @@ }, "dependencies": { "@mendix/piw-native-utils-internal": "*", - "@mendix/piw-utils-internal": "*", - "react-native-reanimated": "^3.0.0" + "@mendix/piw-utils-internal": "*" }, "devDependencies": { "@mendix/pluggable-widgets-tools": "*" diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index 43fc419a4..572a47c59 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -1,9 +1,8 @@ import { flattenStyles } from "@mendix/piw-native-utils-internal"; import { executeAction } from "@mendix/piw-utils-internal"; import { Icon } from "mendix/components/native/Icon"; -import { Component, JSX } from "react"; -import { Pressable, StyleSheet, Text, View, ViewStyle } from "react-native"; -import Animated, { Easing, interpolate, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated"; +import { Component, JSX, useEffect, useRef } from "react"; +import { Animated, Easing, Pressable, StyleSheet, Text, View, ViewStyle } from "react-native"; import { FloatingActionButtonProps } from "../typings/FloatingActionButtonProps"; import { defaultFloatingActionButtonStyle, FloatingActionButtonStyle } from "./ui/styles"; @@ -27,19 +26,21 @@ interface AnimatedMainIconProps { function AnimatedMainIcon(props: AnimatedMainIconProps): JSX.Element { const { active, hasSecondaryButtons, style, icon, iconActive } = props; - const progress = useSharedValue(active && hasSecondaryButtons ? 1 : 0); - progress.value = withTiming(active && hasSecondaryButtons ? 1 : 0, { - duration: 200, - easing: Easing.out(Easing.ease) - }); + const progress = useRef(new Animated.Value(active && hasSecondaryButtons ? 1 : 0)).current; + + useEffect(() => { + Animated.timing(progress, { + toValue: active && hasSecondaryButtons ? 1 : 0, + duration: 200, + easing: Easing.out(Easing.ease), + useNativeDriver: true + }).start(); + }, [active, hasSecondaryButtons, progress]); - const animatedStyle = useAnimatedStyle(() => ({ - transform: [ - { - rotate: `${interpolate(progress.value, [0, 1], [0, -180])}deg` - } - ] - })); + const rotate = progress.interpolate({ + inputRange: [0, 1], + outputRange: ["0deg", "-180deg"] + }); const iconSource = icon?.value ? icon.value : defaultIconSource; const activeIconSource = iconActive?.value ? iconActive.value : defaultActiveIconSource; @@ -47,7 +48,7 @@ function AnimatedMainIcon(props: AnimatedMainIconProps): JSX.Element { return ( - + @@ -81,32 +82,31 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { onPress } = props; - const progress = useSharedValue(active ? 1 : 0); - progress.value = withTiming(active ? 1 : 0, { - duration: 200, - easing: Easing.out(Easing.ease) - }); + const progress = useRef(new Animated.Value(active ? 1 : 0)).current; + + useEffect(() => { + Animated.timing(progress, { + toValue: active ? 1 : 0, + duration: 200, + easing: Easing.out(Easing.ease), + useNativeDriver: true + }).start(); + }, [active, progress]); const labelOnRight = horizontalPosition === "left"; const labelOnLeft = horizontalPosition === "right"; - const animatedStyle = useAnimatedStyle(() => { - const centerToCenterDistance = - (mainButtonSize + secondaryButtonSize) / 2 + SECONDARY_GAP + index * (secondaryButtonSize + SECONDARY_GAP); + const centerToCenterDistance = + (mainButtonSize + secondaryButtonSize) / 2 + SECONDARY_GAP + index * (secondaryButtonSize + SECONDARY_GAP); - return { - opacity: progress.value, - transform: [ - { - translateY: interpolate( - progress.value, - [0, 1], - [0, direction === "up" ? -centerToCenterDistance : centerToCenterDistance] - ) - }, - { scale: interpolate(progress.value, [0, 1], [0.8, 1]) } - ] - }; + const translateY = progress.interpolate({ + inputRange: [0, 1], + outputRange: [0, direction === "up" ? -centerToCenterDistance : centerToCenterDistance] + }); + + const scale = progress.interpolate({ + inputRange: [0, 1], + outputRange: [0.8, 1] }); const anchorStyle: ViewStyle = { @@ -119,7 +119,14 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { return ( { - const Reanimated = jest.requireActual("react-native-reanimated/lib/module/mock"); - - if (Reanimated?.default && typeof Reanimated.default === "object") { - Reanimated.default.call = () => undefined; - } - - return Reanimated; -}); - describe("FloatingActionButton", () => { let defaultProps: FloatingActionButtonProps; const secondaryButtons = [ diff --git a/packages/pluggableWidgets/floating-action-button-native/src/__tests__/__snapshots__/FloatingActionButton.spec.tsx.snap b/packages/pluggableWidgets/floating-action-button-native/src/__tests__/__snapshots__/FloatingActionButton.spec.tsx.snap index 23cd874cf..534e3c657 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/__tests__/__snapshots__/FloatingActionButton.spec.tsx.snap +++ b/packages/pluggableWidgets/floating-action-button-native/src/__tests__/__snapshots__/FloatingActionButton.spec.tsx.snap @@ -23,30 +23,25 @@ exports[`FloatingActionButton renders correct props with secondary buttons 1`] = } > Date: Wed, 12 Aug 2026 11:46:15 +0530 Subject: [PATCH 2/9] fix: caption value bug fix for horizontal position center --- .../floating-action-button-native/src/FloatingActionButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index 572a47c59..f6bb1baee 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -93,7 +93,7 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { }).start(); }, [active, progress]); - const labelOnRight = horizontalPosition === "left"; + const labelOnRight = horizontalPosition === "left" || horizontalPosition === "center"; const labelOnLeft = horizontalPosition === "right"; const centerToCenterDistance = From 9cd1caf1b86da02aaea321e36f1da32a4daf2cdf Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Wed, 12 Aug 2026 15:37:44 +0530 Subject: [PATCH 3/9] fix: migrated class component to functional component --- .../src/FloatingActionButton.tsx | 299 ++++++++---------- .../src/ui/styles.tsx | 48 ++- 2 files changed, 174 insertions(+), 173 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index f6bb1baee..b8d1df918 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -1,15 +1,15 @@ import { flattenStyles } from "@mendix/piw-native-utils-internal"; import { executeAction } from "@mendix/piw-utils-internal"; import { Icon } from "mendix/components/native/Icon"; -import { Component, JSX, useEffect, useRef } from "react"; -import { Animated, Easing, Pressable, StyleSheet, Text, View, ViewStyle } from "react-native"; +import { JSX, useEffect, useRef, useState } from "react"; +import { Animated, Easing, Pressable, Text, View, ViewStyle } from "react-native"; -import { FloatingActionButtonProps } from "../typings/FloatingActionButtonProps"; -import { defaultFloatingActionButtonStyle, FloatingActionButtonStyle } from "./ui/styles"; - -interface State { - active: boolean; -} +import { + FloatingActionButtonProps, + HorizontalPositionEnum, + VerticalPositionEnum +} from "../typings/FloatingActionButtonProps"; +import { defaultFloatingActionButtonStyle, FloatingActionButtonStyle, styles } from "./ui/styles"; const defaultIconSource = { type: "glyph", iconClass: "glyphicon-plus" } as const; const defaultActiveIconSource = { type: "glyph", iconClass: "glyphicon-remove" } as const; @@ -23,6 +23,66 @@ interface AnimatedMainIconProps { iconActive: FloatingActionButtonProps["iconActive"]; } +interface SecondaryActionItemProps { + active: boolean; + index: number; + direction: "up" | "down"; + horizontalPosition: "left" | "right" | "center"; + name: string; + button: FloatingActionButtonProps["secondaryButtons"][number]; + style: FloatingActionButtonStyle; + mainButtonSize: number; + secondaryButtonSize: number; + onPress: () => void; +} + +function getVerticalOrientation(verticalPosition: VerticalPositionEnum): "up" | "down" { + switch (verticalPosition) { + case "bottom": + return "up"; + case "top": + default: + return "down"; + } +} + +function getPositionStyle( + verticalPosition: VerticalPositionEnum, + horizontalPosition: HorizontalPositionEnum +): ViewStyle { + const positionStyle: ViewStyle = { + position: "absolute", + left: 0, + right: 0, + zIndex: 999 + }; + + switch (verticalPosition) { + case "bottom": + positionStyle.bottom = 0; + break; + case "top": + default: + positionStyle.top = 0; + break; + } + + switch (horizontalPosition) { + case "left": + positionStyle.alignItems = "flex-start"; + break; + case "center": + positionStyle.alignItems = "center"; + break; + case "right": + default: + positionStyle.alignItems = "flex-end"; + break; + } + + return positionStyle; +} + function AnimatedMainIcon(props: AnimatedMainIconProps): JSX.Element { const { active, hasSecondaryButtons, style, icon, iconActive } = props; @@ -55,19 +115,6 @@ function AnimatedMainIcon(props: AnimatedMainIconProps): JSX.Element { ); } -interface SecondaryActionItemProps { - active: boolean; - index: number; - direction: "up" | "down"; - horizontalPosition: "left" | "right" | "center"; - name: string; - button: FloatingActionButtonProps["secondaryButtons"][number]; - style: FloatingActionButtonStyle; - mainButtonSize: number; - secondaryButtonSize: number; - onPress: () => void; -} - function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { const { active, @@ -193,177 +240,85 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { ); } -export class FloatingActionButton extends Component, State> { - readonly state: State = { - active: false - }; - - private readonly onPressHandler = this.onPress.bind(this); - - render(): JSX.Element { - const style = flattenStyles(defaultFloatingActionButtonStyle, this.props.style); - const buttonStyle = { ...style.button }; - delete buttonStyle.rippleColor; +export function FloatingActionButton(props: FloatingActionButtonProps): JSX.Element { + const [active, setActive] = useState(false); + const style = flattenStyles(defaultFloatingActionButtonStyle, props.style); + const buttonStyle = { ...style.button }; + delete buttonStyle.rippleColor; - const mainButtonSize = style.button.size ?? 54; - const secondaryButtonSize = style.secondaryButton.size ?? 40; - const horizontalPosition = this.props.horizontalPosition ?? "right"; - const hasSecondaryButtons = !!this.props.secondaryButtons?.length; + const mainButtonSize = style.button.size ?? 54; + const secondaryButtonSize = style.secondaryButton.size ?? 40; + const horizontalPosition = props.horizontalPosition ?? "right"; + const hasSecondaryButtons = !!props.secondaryButtons?.length; - return ( - - {this.renderButtons(style, mainButtonSize, secondaryButtonSize, horizontalPosition)} + const handlePress = (): void => { + if (props.secondaryButtons?.length) { + setActive(prev => !prev); + return; + } - [ - styles.mainButtonBase, - buttonStyle, - { - width: mainButtonSize, - height: mainButtonSize, - borderRadius: mainButtonSize / 2, - opacity: pressed ? 0.2 : 1 - } - ]} - > - - - - ); - } + executeAction(props.onClick); + }; - private renderButtons( + const renderButtons = ( style: FloatingActionButtonStyle, mainButtonSize: number, secondaryButtonSize: number, horizontalPosition: "left" | "right" | "center" - ): JSX.Element[] | undefined { - return this.props.secondaryButtons?.map((button, index) => ( + ): JSX.Element[] | undefined => { + return props.secondaryButtons?.map((button, index) => ( { - this.setState({ active: false }); + setActive(false); executeAction(button.onClick); }} /> )); - } - - private get verticalOrientation(): "up" | "down" { - switch (this.props.verticalPosition) { - case "bottom": - return "up"; - case "top": - return "down"; - default: - return "down"; - } - } - - private getPositionStyle(): ViewStyle { - const positionStyle: ViewStyle = { - position: "absolute", - left: 0, - right: 0, - zIndex: 999 - }; - - switch (this.props.verticalPosition) { - case "bottom": - positionStyle.bottom = 0; - break; - case "top": - default: - positionStyle.top = 0; - break; - } - - switch (this.props.horizontalPosition) { - case "left": - positionStyle.alignItems = "flex-start"; - break; - case "center": - positionStyle.alignItems = "center"; - break; - case "right": - default: - positionStyle.alignItems = "flex-end"; - break; - } - - return positionStyle; - } - - private onPress(): void { - if (this.props.secondaryButtons?.length) { - // eslint-disable-next-line react/no-access-state-in-setstate - this.setState({ active: !this.state.active }); - return; - } + }; - executeAction(this.props.onClick); - } + return ( + + {renderButtons(style, mainButtonSize, secondaryButtonSize, horizontalPosition)} + + [ + styles.mainButtonBase, + buttonStyle, + { + width: mainButtonSize, + height: mainButtonSize, + borderRadius: mainButtonSize / 2, + opacity: pressed ? 0.2 : 1 + } + ]} + > + + + + ); } - -const styles = StyleSheet.create({ - wrapper: { - justifyContent: "flex-end" - }, - mainButtonBase: { - alignItems: "center", - justifyContent: "center" - }, - secondaryAnchor: { - position: "absolute" - }, - secondaryRow: { - width: "100%", - flexDirection: "row", - alignItems: "center" - }, - rowAlignLeft: { - justifyContent: "flex-start" - }, - rowAlignRight: { - justifyContent: "flex-end" - }, - rowAlignCenter: { - justifyContent: "center" - }, - secondaryButtonBase: { - alignItems: "center", - justifyContent: "center", - flexShrink: 0 - }, - captionInlineContainer: { - flexShrink: 0 - }, - captionBeforeButton: { - marginRight: 8, - alignItems: "flex-end" - }, - captionAfterButton: { - marginLeft: 8, - alignItems: "flex-start" - }, - captionText: { - flexShrink: 0 - } -}); diff --git a/packages/pluggableWidgets/floating-action-button-native/src/ui/styles.tsx b/packages/pluggableWidgets/floating-action-button-native/src/ui/styles.tsx index a6802b783..e6c5dc764 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/ui/styles.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/ui/styles.tsx @@ -1,5 +1,5 @@ import { Style } from "@mendix/piw-native-utils-internal"; -import { TextStyle, ViewStyle } from "react-native"; +import { TextStyle, ViewStyle, StyleSheet } from "react-native"; export interface FloatingActionButtonStyle extends Style { container: ViewStyle; @@ -80,3 +80,49 @@ export const defaultFloatingActionButtonStyle: FloatingActionButtonStyle = { marginHorizontal: 15 } }; + +export const styles = StyleSheet.create({ + wrapper: { + justifyContent: "flex-end" + }, + mainButtonBase: { + alignItems: "center", + justifyContent: "center" + }, + secondaryAnchor: { + position: "absolute" + }, + secondaryRow: { + width: "100%", + flexDirection: "row", + alignItems: "center" + }, + rowAlignLeft: { + justifyContent: "flex-start" + }, + rowAlignRight: { + justifyContent: "flex-end" + }, + rowAlignCenter: { + justifyContent: "center" + }, + secondaryButtonBase: { + alignItems: "center", + justifyContent: "center", + flexShrink: 0 + }, + captionInlineContainer: { + flexShrink: 0 + }, + captionBeforeButton: { + marginRight: 8, + alignItems: "flex-end" + }, + captionAfterButton: { + marginLeft: 8, + alignItems: "flex-start" + }, + captionText: { + flexShrink: 0 + } +}); From ab260594f45bdc488416db3e27a603eb23b167c7 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Wed, 12 Aug 2026 15:48:12 +0530 Subject: [PATCH 4/9] fix: update version and changelog --- .../floating-action-button-native/CHANGELOG.md | 4 ++++ .../floating-action-button-native/package.json | 2 +- .../floating-action-button-native/src/package.xml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/CHANGELOG.md b/packages/pluggableWidgets/floating-action-button-native/CHANGELOG.md index 72f4dfdcd..090c849d4 100644 --- a/packages/pluggableWidgets/floating-action-button-native/CHANGELOG.md +++ b/packages/pluggableWidgets/floating-action-button-native/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +- We have removed the 'react-native-reanimated' library and used Animated API of react native for animation purpose. +- We fixed an issue of secondary button's caption not displayed if its horizontal position is center. +- We refactored code and migrated to functional component. + ## [4.2.1] - 2026-6-10 ### Changed diff --git a/packages/pluggableWidgets/floating-action-button-native/package.json b/packages/pluggableWidgets/floating-action-button-native/package.json index e99ce1a07..03910be78 100644 --- a/packages/pluggableWidgets/floating-action-button-native/package.json +++ b/packages/pluggableWidgets/floating-action-button-native/package.json @@ -1,7 +1,7 @@ { "name": "floating-action-button-native", "widgetName": "FloatingActionButton", - "version": "4.2.1", + "version": "4.3.0", "license": "Apache-2.0", "repository": { "type": "git", diff --git a/packages/pluggableWidgets/floating-action-button-native/src/package.xml b/packages/pluggableWidgets/floating-action-button-native/src/package.xml index af33e8f2d..76a2254ae 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/package.xml +++ b/packages/pluggableWidgets/floating-action-button-native/src/package.xml @@ -1,6 +1,6 @@ - + From e395d4cb13b43becbfccb21c67f6adc91d542853 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 13 Aug 2026 16:39:34 +0530 Subject: [PATCH 5/9] fix: moved interface to typings file --- .../src/FloatingActionButton.tsx | 25 +++---------------- .../typings/FloatingActionButtonProps.d.ts | 21 ++++++++++++++++ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index b8d1df918..c8ca809ba 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -7,7 +7,9 @@ import { Animated, Easing, Pressable, Text, View, ViewStyle } from "react-native import { FloatingActionButtonProps, HorizontalPositionEnum, - VerticalPositionEnum + VerticalPositionEnum, + SecondaryActionItemProps, + AnimatedMainIconProps } from "../typings/FloatingActionButtonProps"; import { defaultFloatingActionButtonStyle, FloatingActionButtonStyle, styles } from "./ui/styles"; @@ -15,27 +17,6 @@ const defaultIconSource = { type: "glyph", iconClass: "glyphicon-plus" } as cons const defaultActiveIconSource = { type: "glyph", iconClass: "glyphicon-remove" } as const; const SECONDARY_GAP = 16; -interface AnimatedMainIconProps { - active: boolean; - hasSecondaryButtons: boolean; - style: FloatingActionButtonStyle; - icon: FloatingActionButtonProps["icon"]; - iconActive: FloatingActionButtonProps["iconActive"]; -} - -interface SecondaryActionItemProps { - active: boolean; - index: number; - direction: "up" | "down"; - horizontalPosition: "left" | "right" | "center"; - name: string; - button: FloatingActionButtonProps["secondaryButtons"][number]; - style: FloatingActionButtonStyle; - mainButtonSize: number; - secondaryButtonSize: number; - onPress: () => void; -} - function getVerticalOrientation(verticalPosition: VerticalPositionEnum): "up" | "down" { switch (verticalPosition) { case "bottom": diff --git a/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts b/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts index 655950d30..27625b6e3 100644 --- a/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts +++ b/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts @@ -63,3 +63,24 @@ export interface FloatingActionButtonPreviewProps { onClick: {} | null; secondaryButtons: SecondaryButtonsPreviewType[]; } + +export interface AnimatedMainIconProps { + active: boolean; + hasSecondaryButtons: boolean; + style: FloatingActionButtonStyle; + icon: FloatingActionButtonProps["icon"]; + iconActive: FloatingActionButtonProps["iconActive"]; +} + +export interface SecondaryActionItemProps { + active: boolean; + index: number; + direction: "up" | "down"; + horizontalPosition: "left" | "right" | "center"; + name: string; + button: FloatingActionButtonProps["secondaryButtons"][number]; + style: FloatingActionButtonStyle; + mainButtonSize: number; + secondaryButtonSize: number; + onPress: () => void; +} From f8c164edd03bd0a1109748f24d04116712594736 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 13 Aug 2026 16:43:16 +0530 Subject: [PATCH 6/9] fix: object destructured instead of deleting property --- .../floating-action-button-native/src/FloatingActionButton.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index c8ca809ba..17c670426 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -224,8 +224,7 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { export function FloatingActionButton(props: FloatingActionButtonProps): JSX.Element { const [active, setActive] = useState(false); const style = flattenStyles(defaultFloatingActionButtonStyle, props.style); - const buttonStyle = { ...style.button }; - delete buttonStyle.rippleColor; + const { rippleColor, ...buttonStyle } = style.button; const mainButtonSize = style.button.size ?? 54; const secondaryButtonSize = style.secondaryButton.size ?? 40; From 1f2f2ac7ea506a180ca1595d85bcdad1bc88c030 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 13 Aug 2026 16:53:20 +0530 Subject: [PATCH 7/9] fix: pnpm lock file fixes --- pnpm-lock.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d819eb290..31887d9d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14616,7 +14616,7 @@ snapshots: react: 19.2.3 react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-is-edge-to-edge@1.3.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): + react-native-is-edge-to-edge@1.3.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) @@ -14676,7 +14676,7 @@ snapshots: react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) react-native-svg: 15.15.4(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): + react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) From 143d1cf7e7aee1a39b2c1495a569f0cf24cd74e3 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 13 Aug 2026 17:18:18 +0530 Subject: [PATCH 8/9] Revert "fix: moved interface to typings file" This reverts commit e395d4cb13b43becbfccb21c67f6adc91d542853. --- .../src/FloatingActionButton.tsx | 25 ++++++++++++++++--- .../typings/FloatingActionButtonProps.d.ts | 21 ---------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index 17c670426..cc9967599 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -7,9 +7,7 @@ import { Animated, Easing, Pressable, Text, View, ViewStyle } from "react-native import { FloatingActionButtonProps, HorizontalPositionEnum, - VerticalPositionEnum, - SecondaryActionItemProps, - AnimatedMainIconProps + VerticalPositionEnum } from "../typings/FloatingActionButtonProps"; import { defaultFloatingActionButtonStyle, FloatingActionButtonStyle, styles } from "./ui/styles"; @@ -17,6 +15,27 @@ const defaultIconSource = { type: "glyph", iconClass: "glyphicon-plus" } as cons const defaultActiveIconSource = { type: "glyph", iconClass: "glyphicon-remove" } as const; const SECONDARY_GAP = 16; +interface AnimatedMainIconProps { + active: boolean; + hasSecondaryButtons: boolean; + style: FloatingActionButtonStyle; + icon: FloatingActionButtonProps["icon"]; + iconActive: FloatingActionButtonProps["iconActive"]; +} + +interface SecondaryActionItemProps { + active: boolean; + index: number; + direction: "up" | "down"; + horizontalPosition: "left" | "right" | "center"; + name: string; + button: FloatingActionButtonProps["secondaryButtons"][number]; + style: FloatingActionButtonStyle; + mainButtonSize: number; + secondaryButtonSize: number; + onPress: () => void; +} + function getVerticalOrientation(verticalPosition: VerticalPositionEnum): "up" | "down" { switch (verticalPosition) { case "bottom": diff --git a/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts b/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts index 27625b6e3..655950d30 100644 --- a/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts +++ b/packages/pluggableWidgets/floating-action-button-native/typings/FloatingActionButtonProps.d.ts @@ -63,24 +63,3 @@ export interface FloatingActionButtonPreviewProps { onClick: {} | null; secondaryButtons: SecondaryButtonsPreviewType[]; } - -export interface AnimatedMainIconProps { - active: boolean; - hasSecondaryButtons: boolean; - style: FloatingActionButtonStyle; - icon: FloatingActionButtonProps["icon"]; - iconActive: FloatingActionButtonProps["iconActive"]; -} - -export interface SecondaryActionItemProps { - active: boolean; - index: number; - direction: "up" | "down"; - horizontalPosition: "left" | "right" | "center"; - name: string; - button: FloatingActionButtonProps["secondaryButtons"][number]; - style: FloatingActionButtonStyle; - mainButtonSize: number; - secondaryButtonSize: number; - onPress: () => void; -} From 9e115b613969532364aaa25a3eee666d9b624f86 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 13 Aug 2026 23:27:58 +0530 Subject: [PATCH 9/9] fix: accessibility support for FAB --- .../src/FloatingActionButton.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx index cc9967599..3878992dd 100644 --- a/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx +++ b/packages/pluggableWidgets/floating-action-button-native/src/FloatingActionButton.tsx @@ -202,6 +202,9 @@ function SecondaryActionItem(props: SecondaryActionItemProps): JSX.Element { [ styles.secondaryButtonBase, style.secondaryButton, @@ -299,6 +302,17 @@ export function FloatingActionButton(props: FloatingActionButtonProps [ styles.mainButtonBase, buttonStyle,