UNPKG

3.94 kBTypeScriptView Raw
1import * as React from 'react';
2import {
3 StyleSheet,
4 StyleProp,
5 ViewStyle,
6 GestureResponderEvent,
7} from 'react-native';
8import { withTheme } from '../../core/theming';
9import color from 'color';
10import IconButton from '../IconButton';
11import { ToggleButtonGroupContext } from './ToggleButtonGroup';
12import { black, white } from '../../styles/colors';
13import type { IconSource } from '../Icon';
14
15type Props = {
16 /**
17 * Icon to display for the `ToggleButton`.
18 */
19 icon: IconSource;
20 /**
21 * Size of the icon.
22 */
23 size?: number;
24 /**
25 * Custom text color for button.
26 */
27 color?: string;
28 /**
29 * Whether the button is disabled.
30 */
31 disabled?: boolean;
32 /**
33 * Accessibility label for the `ToggleButton`. This is read by the screen reader when the user taps the button.
34 */
35 accessibilityLabel?: string;
36 /**
37 * Function to execute on press.
38 */
39 onPress?: (value?: GestureResponderEvent | string) => void;
40 /**
41 * Value of button.
42 */
43 value?: string;
44 /**
45 * Status of button.
46 */
47 status?: 'checked' | 'unchecked';
48 style?: StyleProp<ViewStyle>;
49 /**
50 * @optional
51 */
52 theme: ReactNativePaper.Theme;
53};
54
55/**
56 * Toggle buttons can be used to group related options. To emphasize groups of related toggle buttons,
57 * a group should share a common container.
58 *
59 * <div class="screenshots">
60 * <img class="medium" src="screenshots/toggle-button.png" />
61 * </div>
62 *
63 * ## Usage
64 * ```js
65 * import * as React from 'react';
66 * import { ToggleButton } from 'react-native-paper';
67 *
68 * const ToggleButtonExample = () => {
69 * const [status, setStatus] = React.useState('checked');
70 *
71 * const onButtonToggle = value => {
72 * setStatus(status === 'checked' ? 'unchecked' : 'checked');
73 * };
74 *
75 * return (
76 * <ToggleButton
77 * icon="bluetooth"
78 * value="bluetooth"
79 * status={status}
80 * onPress={onButtonToggle}
81 * />
82 * );
83 * };
84 *
85 * export default ToggleButtonExample;
86 *
87 * ```
88 */
89const ToggleButton = ({
90 icon,
91 size,
92 theme,
93 accessibilityLabel,
94 disabled,
95 style,
96 value,
97 status,
98 onPress,
99 ...rest
100}: Props) => {
101 const borderRadius = theme.roundness;
102
103 return (
104 <ToggleButtonGroupContext.Consumer>
105 {(context: { value: string | null; onValueChange: Function } | null) => {
106 let backgroundColor;
107
108 const checked: boolean | null =
109 (context && context.value === value) || status === 'checked';
110
111 if (checked) {
112 backgroundColor = theme.dark
113 ? 'rgba(255, 255, 255, .12)'
114 : 'rgba(0, 0, 0, .08)';
115 } else {
116 backgroundColor = 'transparent';
117 }
118
119 return (
120 <IconButton
121 borderless={false}
122 icon={icon}
123 onPress={(e?: GestureResponderEvent | string) => {
124 if (onPress) {
125 onPress(e);
126 }
127
128 if (context) {
129 context.onValueChange(!checked ? value : null);
130 }
131 }}
132 size={size}
133 accessibilityLabel={accessibilityLabel}
134 accessibilityState={{ disabled, selected: checked }}
135 disabled={disabled}
136 style={[
137 styles.content,
138 {
139 backgroundColor,
140 borderRadius,
141 borderColor: color(theme.dark ? white : black)
142 .alpha(0.29)
143 .rgb()
144 .string(),
145 },
146 style,
147 ]}
148 {...rest}
149 />
150 );
151 }}
152 </ToggleButtonGroupContext.Consumer>
153 );
154};
155
156const styles = StyleSheet.create({
157 content: {
158 width: 42,
159 height: 42,
160 margin: 0,
161 },
162});
163
164export default withTheme(ToggleButton);
165
166// @component-docs ignore-next-line
167const ToggleButtonWithTheme = withTheme(ToggleButton);
168// @component-docs ignore-next-line
169export { ToggleButtonWithTheme as ToggleButton };