Skip to content
Merged
27 changes: 20 additions & 7 deletions src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ type ButtonProps = Partial<ChildrenProps> & {

/** Boolean whether to display the right icon */
shouldShowRightIcon?: boolean;

/** Whether the button should use split style or not */
isSplitButton?: boolean;
};

type KeyboardShortcutComponentProps = Pick<ButtonProps, 'isDisabled' | 'isLoading' | 'onPress' | 'pressOnEnter' | 'allowBubble' | 'enterKeyEventListenerPriority'>;
Expand Down Expand Up @@ -198,6 +201,7 @@ function Button(

id = '',
accessibilityLabel = '',
isSplitButton = false,
...rest
}: ButtonProps,
ref: ForwardedRef<View | HTMLDivElement>,
Expand Down Expand Up @@ -253,13 +257,22 @@ function Button(
</View>
{shouldShowRightIcon && (
<View style={[styles.justifyContentCenter, large ? styles.ml2 : styles.ml1, iconRightStyles]}>
<Icon
src={iconRight}
fill={iconFill ?? (success || danger ? theme.textLight : theme.icon)}
small={small}
medium={medium}
large={large}
/>
{!isSplitButton ? (
<Icon
src={iconRight}
fill={iconFill ?? (success || danger ? theme.textLight : theme.icon)}
small={medium}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was it set like that? is there any specific reason? Right now I need to add small icon handling and I'll adjust it in this way:

small={small}
medium={medium}
large={large}

may it broke something?
@nkdengineer

medium={large}
/>
) : (
<Icon
src={iconRight}
Comment thread
nkdengineer marked this conversation as resolved.
fill={iconFill ?? (success || danger ? theme.textLight : theme.icon)}
small={small}
medium={medium}
large={large}
/>
)}
</View>
)}
</View>
Expand Down
63 changes: 35 additions & 28 deletions src/components/ButtonWithDropdownMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {ButtonWithDropdownMenuProps} from './types';

function ButtonWithDropdownMenu<IValueType>({
success = false,
isSplitButton = true,
isLoading = false,
isDisabled = false,
pressOnEnter = false,
Expand All @@ -40,7 +41,7 @@ function ButtonWithDropdownMenu<IValueType>({
const [isMenuVisible, setIsMenuVisible] = useState(false);
const [popoverAnchorPosition, setPopoverAnchorPosition] = useState<AnchorPosition | null>(null);
const {windowWidth, windowHeight} = useWindowDimensions();
const caretButton = useRef<View & HTMLDivElement>(null);
const caretButton = useRef<View | HTMLDivElement | null>(null);
const selectedItem = options[selectedItemIndex] || options[0];
const innerStyleDropButton = StyleUtils.getDropDownButtonHeight(buttonSize);
const isButtonSizeLarge = buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE;
Expand All @@ -64,51 +65,57 @@ function ButtonWithDropdownMenu<IValueType>({
});
}
}, [windowWidth, windowHeight, isMenuVisible, anchorAlignment.vertical]);

return (
<View style={wrapperStyle}>
{shouldAlwaysShowDropdownMenu || options.length > 1 ? (
<View style={[styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, style]}>
<Button
success={success}
pressOnEnter={pressOnEnter}
ref={buttonRef}
onPress={(event) => onPress(event, selectedItem.value)}
ref={(ref) => {
caretButton.current = ref;

@rushatgabhane rushatgabhane Aug 21, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}}
Comment on lines +75 to +77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caused style regression
More details (root cause & solution): #46127 (comment)

onPress={(event) => (!isSplitButton ? setIsMenuVisible(!isMenuVisible) : onPress(event, selectedItem.value))}
text={customText ?? selectedItem.text}
isDisabled={isDisabled || !!selectedItem.disabled}
isLoading={isLoading}
shouldRemoveRightBorderRadius
style={[styles.flex1, styles.pr0]}
large={isButtonSizeLarge}
medium={!isButtonSizeLarge}
innerStyles={[innerStyleDropButton, customText !== undefined && styles.cursorDefault, customText !== undefined && styles.pointerEventsNone]}
innerStyles={[innerStyleDropButton, !isSplitButton && styles.dropDownButtonCartIconView]}
enterKeyEventListenerPriority={enterKeyEventListenerPriority}
iconRight={Expensicons.DownArrow}
shouldShowRightIcon={!isSplitButton}
isSplitButton={isSplitButton}
/>

<Button
ref={caretButton}
success={success}
isDisabled={isDisabled}
style={[styles.pl0]}
onPress={() => setIsMenuVisible(!isMenuVisible)}
shouldRemoveLeftBorderRadius
large={isButtonSizeLarge}
medium={!isButtonSizeLarge}
innerStyles={[styles.dropDownButtonCartIconContainerPadding, innerStyleDropButton]}
enterKeyEventListenerPriority={enterKeyEventListenerPriority}
>
<View style={[styles.dropDownButtonCartIconView, innerStyleDropButton]}>
<View style={[success ? styles.buttonSuccessDivider : styles.buttonDivider]} />
<View style={[isButtonSizeLarge ? styles.dropDownLargeButtonArrowContain : styles.dropDownMediumButtonArrowContain]}>
<Icon
medium={isButtonSizeLarge}
small={!isButtonSizeLarge}
src={Expensicons.DownArrow}
fill={success ? theme.buttonSuccessText : theme.icon}
/>
{isSplitButton && (
<Button
ref={caretButton}
success={success}
isDisabled={isDisabled}
style={[styles.pl0]}
onPress={() => setIsMenuVisible(!isMenuVisible)}
shouldRemoveLeftBorderRadius
large={isButtonSizeLarge}
medium={!isButtonSizeLarge}
innerStyles={[styles.dropDownButtonCartIconContainerPadding, innerStyleDropButton]}
enterKeyEventListenerPriority={enterKeyEventListenerPriority}
>
<View style={[styles.dropDownButtonCartIconView, innerStyleDropButton]}>
<View style={[success ? styles.buttonSuccessDivider : styles.buttonDivider]} />
<View style={[isButtonSizeLarge ? styles.dropDownLargeButtonArrowContain : styles.dropDownMediumButtonArrowContain]}>
<Icon
medium={isButtonSizeLarge}
small={!isButtonSizeLarge}
src={Expensicons.DownArrow}
fill={success ? theme.buttonSuccessText : theme.icon}
/>
</View>
</View>
</View>
</Button>
</Button>
)}
</View>
) : (
<Button
Expand Down
3 changes: 3 additions & 0 deletions src/components/ButtonWithDropdownMenu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ type ButtonWithDropdownMenuProps<TValueType> = {

/** Additional style to add to the wrapper */
wrapperStyle?: StyleProp<ViewStyle>;

/** Whether the button should use split style or not */
isSplitButton?: boolean;
};

export type {PaymentType, WorkspaceMemberBulkActionType, WorkspaceDistanceRatesBulkActionType, DropdownOption, ButtonWithDropdownMenuProps, WorkspaceTaxRatesBulkActionType};
1 change: 1 addition & 0 deletions src/pages/workspace/WorkspaceMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft,
onPress={() => null}
options={getBulkActionsButtonOptions()}
buttonRef={dropdownButtonRef}
isSplitButton={false}
style={[isSmallScreenWidth && styles.flexGrow1]}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ function WorkspaceCategoriesPage({policy, route}: WorkspaceCategoriesPageProps)
buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
customText={translate('workspace.common.selected', {selectedNumber: selectedCategoriesArray.length})}
options={options}
isSplitButton={false}
style={[isSmallScreenWidth && styles.flexGrow1, isSmallScreenWidth && styles.mb3]}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ function PolicyDistanceRatesPage({policy, route}: PolicyDistanceRatesPageProps)
buttonRef={dropdownButtonRef}
style={[isSmallScreenWidth && styles.flexGrow1]}
wrapperStyle={styles.w100}
isSplitButton={false}
/>
)}
</View>
Expand Down
1 change: 1 addition & 0 deletions src/pages/workspace/tags/WorkspaceTagsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ function WorkspaceTagsPage({policyTags, route}: WorkspaceTagsPageProps) {
onPress={() => null}
shouldAlwaysShowDropdownMenu
pressOnEnter
isSplitButton={false}
buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
customText={translate('workspace.common.selected', {selectedNumber: selectedTagsArray.length})}
options={options}
Expand Down
1 change: 1 addition & 0 deletions src/pages/workspace/taxes/WorkspaceTaxesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ function WorkspaceTaxesPage({
customText={translate('workspace.common.selected', {selectedNumber: selectedTaxesIDs.length})}
shouldAlwaysShowDropdownMenu
pressOnEnter
isSplitButton={false}
style={[isSmallScreenWidth && styles.w50, isSmallScreenWidth && styles.mb3]}
/>
);
Expand Down