Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5abe49f
add android ripple on button
Sep 9, 2022
895ab38
Change files
Sep 9, 2022
dcf7d92
ripple\fixes on FAB, Button
Sep 14, 2022
121b5af
Change files
Sep 14, 2022
3fecd69
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Sep 15, 2022
0b8aadb
make fab collapsible / fix fab bugs
Sep 15, 2022
43c7cbc
Change files
Sep 15, 2022
7443651
Merge branch 'microsoft:main' into fab-update
ayush547 Sep 21, 2022
42d152f
Renamed FAB showChildren to showContent
Sep 21, 2022
6842dbe
Change files
Sep 21, 2022
9816337
Merge branch 'microsoft:main' into fab-update
ayush547 Sep 22, 2022
769f7b3
Revert "Change files"
Sep 22, 2022
acde4eb
Merge branch 'fab-update' into button-android-ripple
Sep 24, 2022
289f4c6
Resolved comments
Sep 29, 2022
eaa33cc
Merged after resolving
Sep 29, 2022
295df7d
Resolve conflicts
Sep 29, 2022
5093cdd
Change files
rurikoaraki Sep 29, 2022
f2c3230
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 4, 2022
da9a082
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 7, 2022
3a71dd8
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 7, 2022
3a88910
Ripple changes and tests updation
Oct 7, 2022
23dcc69
Resolved comments on ripple
Oct 17, 2022
fb4ceb9
Change files
Oct 17, 2022
6d998da
Revert "Change files"
Oct 17, 2022
61b7a5c
Merge Pressable changes
ayush547 Oct 21, 2022
853bacf
Ripple changes for RN Pressable
ayush547 Oct 21, 2022
0755069
Change files
ayush547 Oct 21, 2022
093454d
Merge branch 'button-android-ripple' of https://github.com/ayush547/f…
ayush547 Oct 21, 2022
697d180
Resolved comments
ayush547 Oct 21, 2022
fe2e26c
Resolve comments
ayush547 Oct 24, 2022
66053e4
Typo Fix
ayush547 Oct 24, 2022
24127cf
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 24, 2022
8817b14
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 24, 2022
e069524
Merge branch 'microsoft:main' into button-android-ripple
ayush547 Oct 26, 2022
4a47854
Final Ripple Changes
ayush547 Oct 26, 2022
fdc02a5
Change files
ayush547 Oct 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { stylingSettings } from './ComponentName.styling';
import { compose, mergeProps, withSlots, UseSlots } from '@fluentui-react-native/framework';
import { useComponentName } from './useComponentName';
/**
* A function which determines if a set of styles should be applied to the compoent given the current state and props of the component-name.
* A function which determines if a set of styles should be applied to the component given the current state and props of the component-name.
*
* @param layer The name of the state that is being checked for
* @param userProps The props that were passed into the component-name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Typo Fix",
"packageName": "@fluentui-react-native/avatar",
"email": "ayushsinghs@yahoo.in",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Ripple/Fix on FAB",
"packageName": "@fluentui-react-native/button",
"email": "ruaraki@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Ripple changes for RN Pressable",
"packageName": "@fluentui-react-native/experimental-menu-button",
"email": "ayushsinghs@yahoo.in",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Typo Fix",
"packageName": "@fluentui-react-native/experimental-radio-group",
"email": "ayushsinghs@yahoo.in",
"dependentChangeType": "none"
}
2 changes: 1 addition & 1 deletion packages/components/Avatar/src/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Icon } from '@fluentui-react-native/icon';
import { Svg, Path } from 'react-native-svg';

/**
* A function which determines if a set of styles should be applied to the compoent given the current state and props of the avatar.
* A function which determines if a set of styles should be applied to the component given the current state and props of the avatar.
*
* @param layer The name of the state that is being checked for
* @param state The current state of the avatar
Expand Down
20 changes: 19 additions & 1 deletion packages/components/Button/src/Button.styling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ export const stylingSettings: UseStylingOptions<ButtonProps, ButtonSlotProps, Bu
tokens: [defaultButtonTokens, defaultButtonFontTokens, defaultButtonColorTokens, buttonName],
states: buttonStates,
slotProps: {
...(Platform.OS == 'android' && {
rippleContainer: buildProps(
(tokens: ButtonTokens) => {
return {
style: {
flexDirection: 'row',
alignSelf: 'baseline',
borderRadius: tokens.borderRadius,
overflow: 'hidden',
},
};
},
['borderRadius'],
),
}),
root: buildProps(
(tokens: ButtonTokens, theme: Theme) => ({
style: {
Expand All @@ -45,8 +60,11 @@ export const stylingSettings: UseStylingOptions<ButtonProps, ButtonSlotProps, Bu
...borderStyles.from(tokens, theme),
...layoutStyles.from(tokens, theme),
},
android_ripple: {
color: tokens.rippleColor,
},
}),
['backgroundColor', 'width', ...borderStyles.keys, ...layoutStyles.keys],
['backgroundColor', 'width', 'rippleColor', ...borderStyles.keys, ...layoutStyles.keys],
),
content: buildProps(
(tokens: ButtonTokens, theme: Theme) => {
Expand Down
34 changes: 28 additions & 6 deletions packages/components/Button/src/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx withSlots */
import * as React from 'react';
import { Pressable } from 'react-native';
import { Platform, Pressable, View } from 'react-native';
import { ActivityIndicator } from '@fluentui-react-native/experimental-activity-indicator';
import { buttonName, ButtonType, ButtonProps } from './Button.types';
import { TextV1 as Text } from '@fluentui-react-native/text';
Expand All @@ -9,9 +9,10 @@ import { compose, mergeProps, withSlots, UseSlots } from '@fluentui-react-native
import { useButton } from './useButton';
import { Icon } from '@fluentui-react-native/icon';
import { createIconProps, IPressableState } from '@fluentui-react-native/interactive-hooks';
import { extractOuterStylePropsAndroid } from './ExtractStyle.android';

/**
* A function which determines if a set of styles should be applied to the compoent given the current state and props of the button.
* A function which determines if a set of styles should be applied to the component given the current state and props of the button.
*
* @param layer The name of the state that is being checked for
* @param state The current state of the button
Expand Down Expand Up @@ -39,11 +40,13 @@ export const Button = compose<ButtonType>({
...stylingSettings,
slots: {
root: Pressable,
rippleContainer: View,
icon: Icon,
content: Text,
},
useRender: (userProps: ButtonProps, useSlots: UseSlots<ButtonType>) => {
const button = useButton(userProps);

const iconProps = createIconProps(userProps.icon);
// grab the styled slots
const Slots = useSlots(userProps, (layer) => buttonLookup(layer, button.state, userProps));
Expand All @@ -69,18 +72,37 @@ export const Button = compose<ButtonType>({
}
});
}
const label = accessibilityLabel ?? childText;

return (
<Slots.root {...mergedProps} accessibilityLabel={label}>
const label = accessibilityLabel ?? childText;
const buttonContent = (
<React.Fragment>
{loading && <ActivityIndicator />}
{shouldShowIcon && iconPosition === 'before' && <Slots.icon {...iconProps} />}
{React.Children.map(children, (child) =>
typeof child === 'string' ? <Slots.content key="content">{child}</Slots.content> : child,
)}
{shouldShowIcon && iconPosition === 'after' && <Slots.icon {...iconProps} />}
</Slots.root>
</React.Fragment>
);

const hasRipple = Platform.OS === 'android';
if (hasRipple) {
const [outerStyleProps, innerStyleProps] = extractOuterStylePropsAndroid(mergedProps.style);
return (
<Slots.rippleContainer style={outerStyleProps}>
{/* RN Pressable needs to be wrapped with a root view to support curved edges */}
<Slots.root accessibilityLabel={label} {...mergedProps} style={innerStyleProps}>
{buttonContent}
</Slots.root>
</Slots.rippleContainer>
);
} else {
return (
<Slots.root {...mergedProps} accessibilityLabel={label}>
{buttonContent}
</Slots.root>
);
}
};
},
});
7 changes: 7 additions & 0 deletions packages/components/Button/src/Button.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FontTokens, IBorderTokens, IColorTokens, IShadowTokens, LayoutTokens }
import { IFocusable, InteractionEvent, PressablePropsExtended, PressableState } from '@fluentui-react-native/interactive-hooks';
import { IconProps, IconSourcesType } from '@fluentui-react-native/icon';
import { ShadowToken } from '@fluentui-react-native/theme-types';
import { IViewProps } from '@fluentui-react-native/adapters';

export const buttonName = 'Button';
export type ButtonSize = 'small' | 'medium' | 'large';
Expand All @@ -17,6 +18,11 @@ export interface ButtonCoreTokens extends LayoutTokens, FontTokens, IBorderToken
*/
iconColor?: ColorValue;

/**
* Ripple color for Android.
*/
rippleColor?: ColorValue;

/**
* The size of the icon.
*/
Expand Down Expand Up @@ -154,6 +160,7 @@ export interface ButtonInfo {

export interface ButtonSlotProps {
root: React.PropsWithRef<PressablePropsExtended>;
rippleContainer?: IViewProps; // Android only
icon: IconProps;
content: TextProps;
}
Expand Down
1 change: 1 addition & 0 deletions packages/components/Button/src/ButtonColorTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultButtonColorTokens: TokenSettings<ButtonTokens, Theme> = (t:
color: t.colors.buttonText,
borderColor: t.colors.buttonBorder,
iconColor: t.colors.buttonIcon,
rippleColor: t.colors.defaultPressedBackground, // Android only
disabled: {
backgroundColor: t.colors.defaultDisabledBackground,
color: t.colors.defaultDisabledContent,
Expand Down
57 changes: 57 additions & 0 deletions packages/components/Button/src/ExtractStyle.android.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { memoize } from '@fluentui-react-native/framework';
import { ViewStyle } from 'react-native';

/**
* React Native's Pressable does not support curved edges.
* It needs to be wrapped inside another view and have border set there.
* This function extracts styles that should be applied on the outer view.
*
* @param style Styling that is to be applied on the component
* @returns Array containing split styles that are to be applied on the inner and outer views
*/

export const extractOuterStylePropsAndroid = memoize((style: ViewStyle = {}): [outerStyleProps: ViewStyle, innerStyleProps: ViewStyle] => {
const {
margin,
marginTop,
marginBottom,
marginLeft,
marginRight,
marginStart,
marginEnd,
marginVertical,
marginHorizontal,
start,
end,
left,
right,
top,
bottom,
display,
opacity,
...restOfProps
} = style;

return [
{
margin,
marginTop,
marginBottom,
marginLeft,
marginRight,
marginStart,
marginEnd,
marginVertical,
marginHorizontal,
start,
end,
left,
right,
top,
bottom,
display,
opacity,
},
{ borderWidth: 0, ...restOfProps },
];
});
27 changes: 23 additions & 4 deletions packages/components/Button/src/FAB/FAB.styling.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import { ButtonCoreTokens, ButtonCoreProps } from '../Button.types';
import { FABSlotProps } from './FAB.types';
import { ButtonCoreTokens } from '../Button.types';
import { FABProps, FABSlotProps } from './FAB.types';
import { Theme, UseStylingOptions, buildProps } from '@fluentui-react-native/framework';
import { borderStyles, layoutStyles, fontStyles, shadowStyles } from '@fluentui-react-native/tokens';
import { buttonCoreStates } from '../Button.styling';
import { getTextMarginAdjustment } from '@fluentui-react-native/styling-utils';
import { Platform } from 'react-native';
import { defaultFABTokens } from './FABTokens';
import { defaultFABColorTokens } from './FABColorTokens';

export const stylingSettings: UseStylingOptions<ButtonCoreProps, FABSlotProps, ButtonCoreTokens> = {
export const stylingSettings: UseStylingOptions<FABProps, FABSlotProps, ButtonCoreTokens> = {
tokens: [defaultFABTokens, defaultFABColorTokens],
states: [...buttonCoreStates],
slotProps: {
...(Platform.OS == 'android' && {
rippleContainer: buildProps(
(tokens: ButtonCoreTokens) => {
return {
style: {
flexDirection: 'row',
alignSelf: 'baseline',
borderRadius: tokens.borderRadius,
overflow: 'hidden',
},
};
},
['borderRadius'],
),
}),
root: buildProps(
(tokens: ButtonCoreTokens, theme: Theme) => ({
style: {
Expand All @@ -25,9 +41,12 @@ export const stylingSettings: UseStylingOptions<ButtonCoreProps, FABSlotProps, B
...layoutStyles.from(tokens, theme),
...shadowStyles.from(tokens, theme),
},
android_ripple: {
color: tokens.rippleColor,
},
elevation: tokens.elevation,
}),
['backgroundColor', 'width', 'elevation', ...borderStyles.keys, ...layoutStyles.keys, ...shadowStyles.keys],
['backgroundColor', 'width', 'elevation', 'rippleColor', ...borderStyles.keys, ...layoutStyles.keys, ...shadowStyles.keys],
),
content: buildProps(
(tokens: ButtonCoreTokens, theme: Theme) => ({
Expand Down
1 change: 1 addition & 0 deletions packages/components/Button/src/FAB/FABColorTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultFABColorTokens: TokenSettings<ButtonCoreTokens, Theme> = (t:
color: t.colors.brandedContent,
borderColor: t.colors.brandedBorder,
iconColor: t.colors.brandedIcon,
rippleColor: t.colors.defaultPressedBackground, // Android only
disabled: {
backgroundColor: t.colors.brandedDisabledBackground,
color: t.colors.brandedDisabledContent,
Expand Down
32 changes: 25 additions & 7 deletions packages/components/Button/src/FAB/FABCore.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx withSlots */
import * as React from 'react';
import { Platform, View } from 'react-native';
import { Platform, Pressable, View } from 'react-native';
import { fabName, FABProps, FABType } from './FAB.types';
import { TextV1 as Text } from '@fluentui-react-native/text';
import { stylingSettings } from './FAB.styling';
Expand All @@ -9,9 +9,10 @@ import { useButton } from '../useButton';
import { Icon } from '@fluentui-react-native/icon';
import { createIconProps, IPressableState } from '@fluentui-react-native/interactive-hooks';
import { Shadow } from '@fluentui-react-native/experimental-shadow';
import { extractOuterStylePropsAndroid } from '../ExtractStyle.android';

/**
* A function which determines if a set of styles should be applied to the compoent given the current state and props of the button.
* A function which determines if a set of styles should be applied to the component given the current state and props of the button.
*
* @param layer The name of the state that is being checked for
* @param state The current state of the button
Expand All @@ -28,9 +29,10 @@ export const FAB = compose<FABType>({
displayName: fabName,
...stylingSettings,
slots: {
root: View,
root: Pressable,
icon: Icon,
content: Text,
rippleContainer: View,
shadow: Shadow,
},
useRender: (userProps: FABProps, useSlots: UseSlots<FABType>) => {
Expand Down Expand Up @@ -64,21 +66,37 @@ export const FAB = compose<FABType>({
}
const label = accessibilityLabel ?? childText;

const fabWithoutShadow = (
<Slots.root {...mergedProps} accessibilityLabel={label}>
const buttonContent = (
<React.Fragment>
{icon && <Slots.icon {...iconProps} />}
{showContent &&
React.Children.map(children, (child) =>
typeof child === 'string' ? <Slots.content key="content">{child}</Slots.content> : child,
)}
</React.Fragment>
);
const buttonContentWithRoot = (
<Slots.root {...mergedProps} accessibilityLabel={label}>
{buttonContent}
</Slots.root>
);

const hasShadow = Platform.OS === 'ios';
const hasRipple = Platform.OS === 'android';

if (hasShadow) {
return <Slots.shadow>{fabWithoutShadow}</Slots.shadow>;
return <Slots.shadow>{buttonContentWithRoot}</Slots.shadow>;
} else if (hasRipple) {
const [outerStyleProps, innerStyleProps] = extractOuterStylePropsAndroid(mergedProps.style);
return (
<Slots.rippleContainer style={outerStyleProps}>
<Slots.root accessibilityLabel={label} {...mergedProps} style={innerStyleProps}>
{buttonContent}
</Slots.root>
</Slots.rippleContainer>
);
} else {
return fabWithoutShadow;
return buttonContentWithRoot;
}
};
},
Expand Down
Loading