Skip to content

Commit 4722ad3

Browse files
committed
feat(Button): add customBackground prop for custom background elements (#3799)
* feat(Button): add customBackground prop for custom background elements * feat(ButtonScreen): add custom gradient and image background buttons examples * fix(Button): update customBackground handling and improve button styles
1 parent 0b30f47 commit 4722ad3

File tree

6 files changed

+375
-3
lines changed

6 files changed

+375
-3
lines changed

demo/src/screens/componentScreens/ButtonsScreen.tsx

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import React, {Component} from 'react';
2-
import {ScrollView, StyleSheet, Alert, Image} from 'react-native';
3-
import {Text, View, Assets, Constants, Button, Colors, Typography, ButtonProps} from 'react-native-ui-lib';
2+
import {ScrollView, StyleSheet, Alert} from 'react-native';
3+
import {
4+
Text,
5+
View,
6+
Assets,
7+
Constants,
8+
Button,
9+
Colors,
10+
Typography,
11+
ButtonProps,
12+
Incubator,
13+
Image
14+
} from 'react-native-ui-lib';
415

516
const ButtonSpace = 20;
617
const plusIcon = Assets.getAssetByPath('icons.demo.plus');
@@ -267,6 +278,34 @@ export default class ButtonsScreen extends Component {
267278
<Button label="hyperlink button" hyperlink style={{marginBottom: ButtonSpace}}/>
268279

269280
<Button label="Icon on right" iconSource={plusIcon} iconOnRight/>
281+
282+
<Text style={styles.header}>Custom Backgrounds</Text>
283+
<Button
284+
label="Gradient Background"
285+
customBackground={
286+
<Incubator.Gradient
287+
colors={[Colors.$backgroundPrimaryHeavy, Colors.$backgroundPrimaryMedium]}
288+
type="rectangle"
289+
width={200}
290+
height={50}
291+
/>
292+
}
293+
style={{marginBottom: ButtonSpace}}
294+
/>
295+
<Button
296+
label="Image Background"
297+
customBackground={
298+
<Image
299+
source={{
300+
uri: 'https://images.pexels.com/photos/748837/pexels-photo-748837.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260'
301+
}}
302+
style={{width: 200, height: 50}}
303+
resizeMode="cover"
304+
/>
305+
}
306+
style={{marginBottom: ButtonSpace}}
307+
$textNeutralHeavy
308+
/>
270309
</View>
271310

272311
<View marginT-20>

src/components/button/__tests__/__snapshots__/index.spec.js.snap

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,296 @@ exports[`Button container size should return style for xSmall button 2`] = `
22922292
</View>
22932293
`;
22942294

2295+
exports[`Button customBackground should render button with custom background element 1`] = `
2296+
<View
2297+
accessibilityRole="button"
2298+
accessibilityState={
2299+
{
2300+
"busy": undefined,
2301+
"checked": undefined,
2302+
"disabled": undefined,
2303+
"expanded": undefined,
2304+
"selected": undefined,
2305+
}
2306+
}
2307+
accessibilityValue={
2308+
{
2309+
"max": undefined,
2310+
"min": undefined,
2311+
"now": undefined,
2312+
"text": undefined,
2313+
}
2314+
}
2315+
accessible={true}
2316+
collapsable={false}
2317+
focusable={true}
2318+
hitSlop={
2319+
{
2320+
"bottom": 7.5,
2321+
"left": 0,
2322+
"right": 0,
2323+
"top": 7.5,
2324+
}
2325+
}
2326+
onClick={[Function]}
2327+
onLayout={[Function]}
2328+
onResponderGrant={[Function]}
2329+
onResponderMove={[Function]}
2330+
onResponderRelease={[Function]}
2331+
onResponderTerminate={[Function]}
2332+
onResponderTerminationRequest={[Function]}
2333+
onStartShouldSetResponder={[Function]}
2334+
style={
2335+
{
2336+
"alignItems": "center",
2337+
"backgroundColor": undefined,
2338+
"borderRadius": 999,
2339+
"flexDirection": "row",
2340+
"justifyContent": "center",
2341+
"minWidth": 90,
2342+
"opacity": 1,
2343+
"paddingHorizontal": 20,
2344+
"paddingVertical": 9.5,
2345+
}
2346+
}
2347+
>
2348+
<View
2349+
absF={true}
2350+
style={
2351+
[
2352+
undefined,
2353+
undefined,
2354+
undefined,
2355+
undefined,
2356+
{
2357+
"bottom": 0,
2358+
"left": 0,
2359+
"position": "absolute",
2360+
"right": 0,
2361+
"top": 0,
2362+
},
2363+
{},
2364+
{},
2365+
{},
2366+
[
2367+
{
2368+
"overflow": "hidden",
2369+
},
2370+
{
2371+
"borderRadius": 999,
2372+
},
2373+
],
2374+
]
2375+
}
2376+
>
2377+
<View
2378+
style={
2379+
[
2380+
undefined,
2381+
undefined,
2382+
undefined,
2383+
{
2384+
"flex": 1,
2385+
},
2386+
undefined,
2387+
{},
2388+
{},
2389+
{},
2390+
{
2391+
"backgroundColor": "red",
2392+
},
2393+
]
2394+
}
2395+
/>
2396+
</View>
2397+
<Text
2398+
fsTagName="unmask"
2399+
numberOfLines={1}
2400+
style={
2401+
[
2402+
{
2403+
"backgroundColor": "transparent",
2404+
"color": "#20303C",
2405+
"writingDirection": "ltr",
2406+
},
2407+
undefined,
2408+
undefined,
2409+
undefined,
2410+
undefined,
2411+
undefined,
2412+
undefined,
2413+
undefined,
2414+
undefined,
2415+
[
2416+
{
2417+
"backgroundColor": "transparent",
2418+
"flexDirection": "row",
2419+
"fontFamily": "System",
2420+
"fontSize": 16,
2421+
"fontWeight": "400",
2422+
"lineHeight": 24,
2423+
},
2424+
{
2425+
"color": "#FFFFFF",
2426+
},
2427+
undefined,
2428+
undefined,
2429+
undefined,
2430+
],
2431+
]
2432+
}
2433+
testID="undefined.label"
2434+
>
2435+
Button
2436+
</Text>
2437+
</View>
2438+
`;
2439+
2440+
exports[`Button customBackground should render custom background element with transparent backgroundColor when provided 1`] = `
2441+
<View
2442+
accessibilityRole="button"
2443+
accessibilityState={
2444+
{
2445+
"busy": undefined,
2446+
"checked": undefined,
2447+
"disabled": undefined,
2448+
"expanded": undefined,
2449+
"selected": undefined,
2450+
}
2451+
}
2452+
accessibilityValue={
2453+
{
2454+
"max": undefined,
2455+
"min": undefined,
2456+
"now": undefined,
2457+
"text": undefined,
2458+
}
2459+
}
2460+
accessible={true}
2461+
collapsable={false}
2462+
focusable={true}
2463+
hitSlop={
2464+
{
2465+
"bottom": 7.5,
2466+
"left": 0,
2467+
"right": 0,
2468+
"top": 7.5,
2469+
}
2470+
}
2471+
onClick={[Function]}
2472+
onLayout={[Function]}
2473+
onResponderGrant={[Function]}
2474+
onResponderMove={[Function]}
2475+
onResponderRelease={[Function]}
2476+
onResponderTerminate={[Function]}
2477+
onResponderTerminationRequest={[Function]}
2478+
onStartShouldSetResponder={[Function]}
2479+
style={
2480+
{
2481+
"alignItems": "center",
2482+
"backgroundColor": undefined,
2483+
"borderRadius": 999,
2484+
"flexDirection": "row",
2485+
"justifyContent": "center",
2486+
"minWidth": 90,
2487+
"opacity": 1,
2488+
"paddingHorizontal": 20,
2489+
"paddingVertical": 9.5,
2490+
}
2491+
}
2492+
>
2493+
<View
2494+
absF={true}
2495+
style={
2496+
[
2497+
undefined,
2498+
undefined,
2499+
undefined,
2500+
undefined,
2501+
{
2502+
"bottom": 0,
2503+
"left": 0,
2504+
"position": "absolute",
2505+
"right": 0,
2506+
"top": 0,
2507+
},
2508+
{},
2509+
{},
2510+
{},
2511+
[
2512+
{
2513+
"overflow": "hidden",
2514+
},
2515+
{
2516+
"borderRadius": 999,
2517+
},
2518+
],
2519+
]
2520+
}
2521+
>
2522+
<View
2523+
style={
2524+
[
2525+
undefined,
2526+
undefined,
2527+
undefined,
2528+
{
2529+
"flex": 1,
2530+
},
2531+
undefined,
2532+
{},
2533+
{},
2534+
{},
2535+
{
2536+
"backgroundColor": "blue",
2537+
},
2538+
]
2539+
}
2540+
/>
2541+
</View>
2542+
<Text
2543+
fsTagName="unmask"
2544+
numberOfLines={1}
2545+
style={
2546+
[
2547+
{
2548+
"backgroundColor": "transparent",
2549+
"color": "#20303C",
2550+
"writingDirection": "ltr",
2551+
},
2552+
undefined,
2553+
undefined,
2554+
undefined,
2555+
undefined,
2556+
undefined,
2557+
undefined,
2558+
undefined,
2559+
undefined,
2560+
[
2561+
{
2562+
"backgroundColor": "transparent",
2563+
"flexDirection": "row",
2564+
"fontFamily": "System",
2565+
"fontSize": 16,
2566+
"fontWeight": "400",
2567+
"lineHeight": 24,
2568+
},
2569+
{
2570+
"color": "#FFFFFF",
2571+
},
2572+
undefined,
2573+
undefined,
2574+
undefined,
2575+
],
2576+
]
2577+
}
2578+
testID="undefined.label"
2579+
>
2580+
Button
2581+
</Text>
2582+
</View>
2583+
`;
2584+
22952585
exports[`Button hyperlink should render button as a hyperlink 1`] = `
22962586
<View
22972587
accessibilityRole="button"

src/components/button/__tests__/index.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import renderer from 'react-test-renderer';
33
import Button from '../index';
4+
import View from '../../view';
45
import {Colors, ThemeManager} from '../../../style';
56
import {Constants} from '../../../commons';
67

@@ -231,6 +232,20 @@ describe('Button', () => {
231232
});
232233
});
233234

235+
describe('customBackground', () => {
236+
it('should render button with custom background element', () => {
237+
const CustomBackground = () => <View flex style={{backgroundColor: 'red'}}/>;
238+
const tree = renderer.create(<Button label="Button" customBackground={<CustomBackground/>}/>).toJSON();
239+
expect(tree).toMatchSnapshot();
240+
});
241+
242+
it('should render custom background element with transparent backgroundColor when provided', () => {
243+
const CustomBackground = () => <View flex style={{backgroundColor: 'blue'}}/>;
244+
const tree = renderer.create(<Button label="Button" backgroundColor="green" customBackground={<CustomBackground/>}/>).toJSON();
245+
expect(tree).toMatchSnapshot();
246+
});
247+
});
248+
234249
describe('icon', () => {
235250
it('should return the right spacing according to button size when label exists and icon on the right', () => {
236251
expect(renderer.create(<Button label="Button" size="large" iconOnRight/>).toJSON()).toMatchSnapshot();

src/components/button/button.api.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@
161161
"name": "animateTo",
162162
"type": "ButtonAnimationDirection",
163163
"description": "the direction of the animation ('left' and 'right' will effect the button's own alignment)"
164+
},
165+
{
166+
"name": "customBackground",
167+
"type": "React.ReactElement",
168+
"description": "Custom element to render as button background (takes precedence over backgroundColor)"
164169
}
165170
],
166171
"snippet": [

0 commit comments

Comments
 (0)