Skip to content

Commit 352539f

Browse files
authored
FloatingButton - add 'fullWidth' prop (#2974)
* FloatingButton - add 'fullWidth' prop * fix comments * fix padding in horizontal and center in vertical
1 parent e94e56e commit 352539f

File tree

4 files changed

+88
-26
lines changed

4 files changed

+88
-26
lines changed

demo/src/screens/componentScreens/FloatingButtonScreen.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export default class FloatingButtonScreen extends Component<{}, State> {
1313
state = {
1414
showButton: true,
1515
showSecondary: true,
16-
showVertical: true
16+
showVertical: true,
17+
fullWidth: false
1718
};
1819

1920
notNow = () => {
@@ -34,6 +35,7 @@ export default class FloatingButtonScreen extends Component<{}, State> {
3435
Trigger Floating Button
3536
</Text>
3637
{renderBooleanOption.call(this, 'Show Floating Button', 'showButton')}
38+
{renderBooleanOption.call(this, 'Full Width Button', 'fullWidth')}
3739
{renderBooleanOption.call(this, 'Show Secondary Button', 'showSecondary')}
3840
{renderBooleanOption.call(this, 'Button Layout Vertical', 'showVertical')}
3941

@@ -64,6 +66,7 @@ export default class FloatingButtonScreen extends Component<{}, State> {
6466

6567
<FloatingButton
6668
visible={this.state.showButton}
69+
fullWidth={this.state.fullWidth}
6770
button={{
6871
label: 'Approve',
6972
onPress: this.close
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react';
2+
import {render} from '@testing-library/react-native';
3+
import FloatingButton/* , {FloatingButtonLayouts} */ from '../index';
4+
import {ButtonDriver} from '../../button/Button.driver.new';
5+
6+
const TEST_ID = 'floating_button';
7+
const button = {
8+
label: 'First'
9+
};
10+
const secondaryButton = {
11+
label: 'Second'
12+
};
13+
// buttonLayout={showVertical ? FloatingButtonLayouts.VERTICAL : FloatingButtonLayouts.HORIZONTAL}
14+
15+
16+
const TestCase = (props) => {
17+
return <FloatingButton {...props} testID={TEST_ID}/>;
18+
};
19+
20+
describe('FloatingButton', () => {
21+
describe('visible', () => {
22+
it('should render a button according to visibility', async () => {
23+
const props = {};
24+
const renderTree = render(<TestCase {...props}/>);
25+
const buttonDriver = ButtonDriver({renderTree, testID: `${TEST_ID}.button`});
26+
expect(await buttonDriver.exists()).not.toBeTruthy();
27+
28+
renderTree.rerender(<TestCase visible/>);
29+
expect(await buttonDriver.exists()).toBeTruthy();
30+
});
31+
});
32+
33+
describe('buttons', () => {
34+
it('should render a button', async () => {
35+
const props = {visible: true};
36+
const renderTree = render(<TestCase {...props}/>);
37+
const buttonDriver = ButtonDriver({renderTree, testID: `${TEST_ID}.button`});
38+
expect(await buttonDriver.exists()).toBeTruthy();
39+
});
40+
41+
it('should not render a secondary button', async () => {
42+
const props = {visible: true};
43+
const renderTree = render(<TestCase {...props}/>);
44+
const buttonDriver = ButtonDriver({renderTree, testID: `${TEST_ID}.secondaryButton`});
45+
expect(await buttonDriver.exists()).not.toBeTruthy();
46+
});
47+
48+
it('should render a button with a label', async () => {
49+
const props = {visible: true, button};
50+
const renderTree = render(<TestCase {...props}/>);
51+
const buttonDriver = ButtonDriver({renderTree, testID: `${TEST_ID}.button`});
52+
expect(await buttonDriver.getLabel().getText()).toEqual(button.label);
53+
});
54+
55+
it('should render secondary button with label', async () => {
56+
const props = {visible: true, secondaryButton};
57+
const renderTree = render(<TestCase {...props}/>);
58+
const buttonDriver = ButtonDriver({renderTree, testID: `${TEST_ID}.secondaryButton`});
59+
expect(await buttonDriver.getLabel().getText()).toEqual(secondaryButton.label);
60+
});
61+
});
62+
});

src/components/floatingButton/floatingButton.api.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"type": "number",
1717
"description": "The bottom margin of the button, or secondary button if passed"
1818
},
19+
{"name": "fullWidth", "type": "boolean", "description": "Whether the buttons get the container's full with", "note": "Relevant to vertical layout only"},
20+
{"name": "buttonLayout", "type": "FloatingButtonLayouts", "description": "Button layout direction: vertical or horizontal"},
1921
{"name": "duration", "type": "number", "description": "The duration of the button's animations (show/hide)"},
2022
{"name": "withoutAnimation", "type": "boolean", "description": "Whether to show/hide the button without animation"},
2123
{"name": "hideBackgroundOverlay", "type": "boolean", "description": "Whether to show background overlay"},

src/components/floatingButton/index.tsx

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import {StyleSheet, Animated} from 'react-native';
33
import {Constants, asBaseComponent} from '../../commons/new';
44
import {Colors, Spacings} from '../../style';
55
import View from '../view';
6-
import Button, {ButtonProps} from '../button';
76
import Image from '../image';
7+
import Button, {ButtonProps} from '../button';
88

99
export enum FloatingButtonLayouts {
1010
VERTICAL = 'Vertical',
@@ -27,6 +27,14 @@ export interface FloatingButtonProps {
2727
* The bottom margin of the button, or secondary button if passed
2828
*/
2929
bottomMargin?: number;
30+
/**
31+
* Whether the buttons get the container's full with (vertical layout only)
32+
*/
33+
fullWidth?: boolean;
34+
/**
35+
* Button layout direction: vertical or horizontal
36+
*/
37+
buttonLayout?: FloatingButtonLayouts | `${FloatingButtonLayouts}`;
3038
/**
3139
* The duration of the button's animations (show/hide)
3240
*/
@@ -46,10 +54,6 @@ export interface FloatingButtonProps {
4654
* <TestID>.secondaryButton - the floatingButton secondaryButton
4755
*/
4856
testID?: string;
49-
/**
50-
* Button layout direction: vertical or horizontal
51-
*/
52-
buttonLayout?: FloatingButtonLayouts | `${FloatingButtonLayouts}`;
5357
}
5458

5559
const gradientImage = () => require('./gradient.png');
@@ -156,35 +160,26 @@ class FloatingButton extends PureComponent<FloatingButtonProps> {
156160
const {secondaryButton, bottomMargin, testID, buttonLayout} = this.props;
157161

158162
const bgColor = secondaryButton?.backgroundColor || Colors.$backgroundDefault;
159-
160-
if (buttonLayout === FloatingButtonLayouts.HORIZONTAL) {
161-
return (
162-
<Button
163-
outline
164-
flex
165-
size={Button.sizes.large}
166-
testID={`${testID}.secondaryButton`}
167-
{...secondaryButton}
168-
style={[styles.shadow, styles.secondaryMargin, {backgroundColor: bgColor}]}
169-
enableShadow={false}
170-
/>
171-
);
172-
}
173-
163+
const isHorizontal = buttonLayout === FloatingButtonLayouts.HORIZONTAL;
164+
const buttonStyle = isHorizontal ?
165+
[styles.shadow, styles.secondaryMargin, {backgroundColor: bgColor}] : {marginBottom: bottomMargin || Spacings.s7};
166+
174167
return (
175168
<Button
176-
link
169+
outline={isHorizontal}
170+
flex={isHorizontal}
171+
link={!isHorizontal}
177172
size={Button.sizes.large}
178173
testID={`${testID}.secondaryButton`}
179174
{...secondaryButton}
180-
style={{marginBottom: bottomMargin || Spacings.s7}}
175+
style={buttonStyle}
181176
enableShadow={false}
182177
/>
183178
);
184179
}
185180

186181
render() {
187-
const {withoutAnimation, visible, testID} = this.props;
182+
const {withoutAnimation, visible, fullWidth, testID} = this.props;
188183
// NOTE: keep this.firstLoad as true as long as the visibility changed to true
189184
this.firstLoad && !visible ? (this.firstLoad = true) : (this.firstLoad = false);
190185

@@ -199,7 +194,8 @@ class FloatingButton extends PureComponent<FloatingButtonProps> {
199194
return (
200195
<View
201196
row={!!this.isSecondaryHorizontal}
202-
center={!!this.isSecondaryHorizontal}
197+
center={!!this.isSecondaryHorizontal || !fullWidth}
198+
paddingH-16={!this.isSecondaryHorizontal && fullWidth}
203199
pointerEvents="box-none"
204200
animated
205201
style={[styles.container, this.getAnimatedStyle()]}
@@ -218,7 +214,6 @@ const styles = StyleSheet.create({
218214
container: {
219215
...StyleSheet.absoluteFillObject,
220216
top: undefined,
221-
alignItems: 'center',
222217
zIndex: Constants.isAndroid ? 99 : undefined
223218
},
224219
image: {

0 commit comments

Comments
 (0)