UNPKG

13 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/esm/extends";
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import withStyles from '../styles/withStyles';
7import { alpha } from '../styles/colorManipulator';
8import ButtonBase from '../ButtonBase';
9import capitalize from '../utils/capitalize';
10export const styles = theme => ({
11 /* Styles applied to the root element. */
12 root: _extends({}, theme.typography.button, {
13 boxSizing: 'border-box',
14 minWidth: 64,
15 padding: '6px 16px',
16 borderRadius: theme.shape.borderRadius,
17 color: theme.palette.text.primary,
18 transition: theme.transitions.create(['background-color', 'box-shadow', 'border'], {
19 duration: theme.transitions.duration.short
20 }),
21 '&:hover': {
22 textDecoration: 'none',
23 backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
24 // Reset on touch devices, it doesn't add specificity
25 '@media (hover: none)': {
26 backgroundColor: 'transparent'
27 },
28 '&$disabled': {
29 backgroundColor: 'transparent'
30 }
31 },
32 '&$disabled': {
33 color: theme.palette.action.disabled
34 }
35 }),
36
37 /* Styles applied to the span element that wraps the children. */
38 label: {
39 width: '100%',
40 // Ensure the correct width for iOS Safari
41 display: 'inherit',
42 alignItems: 'inherit',
43 justifyContent: 'inherit'
44 },
45
46 /* Styles applied to the root element if `variant="text"`. */
47 text: {
48 padding: '6px 8px'
49 },
50
51 /* Styles applied to the root element if `variant="text"` and `color="primary"`. */
52 textPrimary: {
53 color: theme.palette.primary.main,
54 '&:hover': {
55 backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
56 // Reset on touch devices, it doesn't add specificity
57 '@media (hover: none)': {
58 backgroundColor: 'transparent'
59 }
60 }
61 },
62
63 /* Styles applied to the root element if `variant="text"` and `color="secondary"`. */
64 textSecondary: {
65 color: theme.palette.secondary.main,
66 '&:hover': {
67 backgroundColor: alpha(theme.palette.secondary.main, theme.palette.action.hoverOpacity),
68 // Reset on touch devices, it doesn't add specificity
69 '@media (hover: none)': {
70 backgroundColor: 'transparent'
71 }
72 }
73 },
74
75 /* Styles applied to the root element if `variant="outlined"`. */
76 outlined: {
77 padding: '5px 15px',
78 border: `1px solid ${theme.palette.type === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)'}`,
79 '&$disabled': {
80 border: `1px solid ${theme.palette.action.disabledBackground}`
81 }
82 },
83
84 /* Styles applied to the root element if `variant="outlined"` and `color="primary"`. */
85 outlinedPrimary: {
86 color: theme.palette.primary.main,
87 border: `1px solid ${alpha(theme.palette.primary.main, 0.5)}`,
88 '&:hover': {
89 border: `1px solid ${theme.palette.primary.main}`,
90 backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
91 // Reset on touch devices, it doesn't add specificity
92 '@media (hover: none)': {
93 backgroundColor: 'transparent'
94 }
95 }
96 },
97
98 /* Styles applied to the root element if `variant="outlined"` and `color="secondary"`. */
99 outlinedSecondary: {
100 color: theme.palette.secondary.main,
101 border: `1px solid ${alpha(theme.palette.secondary.main, 0.5)}`,
102 '&:hover': {
103 border: `1px solid ${theme.palette.secondary.main}`,
104 backgroundColor: alpha(theme.palette.secondary.main, theme.palette.action.hoverOpacity),
105 // Reset on touch devices, it doesn't add specificity
106 '@media (hover: none)': {
107 backgroundColor: 'transparent'
108 }
109 },
110 '&$disabled': {
111 border: `1px solid ${theme.palette.action.disabled}`
112 }
113 },
114
115 /* Styles applied to the root element if `variant="contained"`. */
116 contained: {
117 color: theme.palette.getContrastText(theme.palette.grey[300]),
118 backgroundColor: theme.palette.grey[300],
119 boxShadow: theme.shadows[2],
120 '&:hover': {
121 backgroundColor: theme.palette.grey.A100,
122 boxShadow: theme.shadows[4],
123 // Reset on touch devices, it doesn't add specificity
124 '@media (hover: none)': {
125 boxShadow: theme.shadows[2],
126 backgroundColor: theme.palette.grey[300]
127 },
128 '&$disabled': {
129 backgroundColor: theme.palette.action.disabledBackground
130 }
131 },
132 '&$focusVisible': {
133 boxShadow: theme.shadows[6]
134 },
135 '&:active': {
136 boxShadow: theme.shadows[8]
137 },
138 '&$disabled': {
139 color: theme.palette.action.disabled,
140 boxShadow: theme.shadows[0],
141 backgroundColor: theme.palette.action.disabledBackground
142 }
143 },
144
145 /* Styles applied to the root element if `variant="contained"` and `color="primary"`. */
146 containedPrimary: {
147 color: theme.palette.primary.contrastText,
148 backgroundColor: theme.palette.primary.main,
149 '&:hover': {
150 backgroundColor: theme.palette.primary.dark,
151 // Reset on touch devices, it doesn't add specificity
152 '@media (hover: none)': {
153 backgroundColor: theme.palette.primary.main
154 }
155 }
156 },
157
158 /* Styles applied to the root element if `variant="contained"` and `color="secondary"`. */
159 containedSecondary: {
160 color: theme.palette.secondary.contrastText,
161 backgroundColor: theme.palette.secondary.main,
162 '&:hover': {
163 backgroundColor: theme.palette.secondary.dark,
164 // Reset on touch devices, it doesn't add specificity
165 '@media (hover: none)': {
166 backgroundColor: theme.palette.secondary.main
167 }
168 }
169 },
170
171 /* Styles applied to the root element if `disableElevation={true}`. */
172 disableElevation: {
173 boxShadow: 'none',
174 '&:hover': {
175 boxShadow: 'none'
176 },
177 '&$focusVisible': {
178 boxShadow: 'none'
179 },
180 '&:active': {
181 boxShadow: 'none'
182 },
183 '&$disabled': {
184 boxShadow: 'none'
185 }
186 },
187
188 /* Pseudo-class applied to the ButtonBase root element if the button is keyboard focused. */
189 focusVisible: {},
190
191 /* Pseudo-class applied to the root element if `disabled={true}`. */
192 disabled: {},
193
194 /* Styles applied to the root element if `color="inherit"`. */
195 colorInherit: {
196 color: 'inherit',
197 borderColor: 'currentColor'
198 },
199
200 /* Styles applied to the root element if `size="small"` and `variant="text"`. */
201 textSizeSmall: {
202 padding: '4px 5px',
203 fontSize: theme.typography.pxToRem(13)
204 },
205
206 /* Styles applied to the root element if `size="large"` and `variant="text"`. */
207 textSizeLarge: {
208 padding: '8px 11px',
209 fontSize: theme.typography.pxToRem(15)
210 },
211
212 /* Styles applied to the root element if `size="small"` and `variant="outlined"`. */
213 outlinedSizeSmall: {
214 padding: '3px 9px',
215 fontSize: theme.typography.pxToRem(13)
216 },
217
218 /* Styles applied to the root element if `size="large"` and `variant="outlined"`. */
219 outlinedSizeLarge: {
220 padding: '7px 21px',
221 fontSize: theme.typography.pxToRem(15)
222 },
223
224 /* Styles applied to the root element if `size="small"` and `variant="contained"`. */
225 containedSizeSmall: {
226 padding: '4px 10px',
227 fontSize: theme.typography.pxToRem(13)
228 },
229
230 /* Styles applied to the root element if `size="large"` and `variant="contained"`. */
231 containedSizeLarge: {
232 padding: '8px 22px',
233 fontSize: theme.typography.pxToRem(15)
234 },
235
236 /* Styles applied to the root element if `size="small"`. */
237 sizeSmall: {},
238
239 /* Styles applied to the root element if `size="large"`. */
240 sizeLarge: {},
241
242 /* Styles applied to the root element if `fullWidth={true}`. */
243 fullWidth: {
244 width: '100%'
245 },
246
247 /* Styles applied to the startIcon element if supplied. */
248 startIcon: {
249 display: 'inherit',
250 marginRight: 8,
251 marginLeft: -4,
252 '&$iconSizeSmall': {
253 marginLeft: -2
254 }
255 },
256
257 /* Styles applied to the endIcon element if supplied. */
258 endIcon: {
259 display: 'inherit',
260 marginRight: -4,
261 marginLeft: 8,
262 '&$iconSizeSmall': {
263 marginRight: -2
264 }
265 },
266
267 /* Styles applied to the icon element if supplied and `size="small"`. */
268 iconSizeSmall: {
269 '& > *:first-child': {
270 fontSize: 18
271 }
272 },
273
274 /* Styles applied to the icon element if supplied and `size="medium"`. */
275 iconSizeMedium: {
276 '& > *:first-child': {
277 fontSize: 20
278 }
279 },
280
281 /* Styles applied to the icon element if supplied and `size="large"`. */
282 iconSizeLarge: {
283 '& > *:first-child': {
284 fontSize: 22
285 }
286 }
287});
288const Button = /*#__PURE__*/React.forwardRef(function Button(props, ref) {
289 const {
290 children,
291 classes,
292 className,
293 color = 'default',
294 component = 'button',
295 disabled = false,
296 disableElevation = false,
297 disableFocusRipple = false,
298 endIcon: endIconProp,
299 focusVisibleClassName,
300 fullWidth = false,
301 size = 'medium',
302 startIcon: startIconProp,
303 type = 'button',
304 variant = 'text'
305 } = props,
306 other = _objectWithoutPropertiesLoose(props, ["children", "classes", "className", "color", "component", "disabled", "disableElevation", "disableFocusRipple", "endIcon", "focusVisibleClassName", "fullWidth", "size", "startIcon", "type", "variant"]);
307
308 const startIcon = startIconProp && /*#__PURE__*/React.createElement("span", {
309 className: clsx(classes.startIcon, classes[`iconSize${capitalize(size)}`])
310 }, startIconProp);
311 const endIcon = endIconProp && /*#__PURE__*/React.createElement("span", {
312 className: clsx(classes.endIcon, classes[`iconSize${capitalize(size)}`])
313 }, endIconProp);
314 return /*#__PURE__*/React.createElement(ButtonBase, _extends({
315 className: clsx(classes.root, classes[variant], className, color === 'inherit' ? classes.colorInherit : color !== 'default' && classes[`${variant}${capitalize(color)}`], size !== 'medium' && [classes[`${variant}Size${capitalize(size)}`], classes[`size${capitalize(size)}`]], disableElevation && classes.disableElevation, disabled && classes.disabled, fullWidth && classes.fullWidth),
316 component: component,
317 disabled: disabled,
318 focusRipple: !disableFocusRipple,
319 focusVisibleClassName: clsx(classes.focusVisible, focusVisibleClassName),
320 ref: ref,
321 type: type
322 }, other), /*#__PURE__*/React.createElement("span", {
323 className: classes.label
324 }, startIcon, children, endIcon));
325});
326process.env.NODE_ENV !== "production" ? Button.propTypes = {
327 // ----------------------------- Warning --------------------------------
328 // | These PropTypes are generated from the TypeScript type definitions |
329 // | To update them edit the d.ts file and run "yarn proptypes" |
330 // ----------------------------------------------------------------------
331
332 /**
333 * The content of the button.
334 */
335 children: PropTypes.node,
336
337 /**
338 * Override or extend the styles applied to the component.
339 * See [CSS API](#css) below for more details.
340 */
341 classes: PropTypes.object,
342
343 /**
344 * @ignore
345 */
346 className: PropTypes.string,
347
348 /**
349 * The color of the component. It supports those theme colors that make sense for this component.
350 */
351 color: PropTypes.oneOf(['default', 'inherit', 'primary', 'secondary']),
352
353 /**
354 * The component used for the root node.
355 * Either a string to use a HTML element or a component.
356 */
357 component: PropTypes
358 /* @typescript-to-proptypes-ignore */
359 .elementType,
360
361 /**
362 * If `true`, the button will be disabled.
363 */
364 disabled: PropTypes.bool,
365
366 /**
367 * If `true`, no elevation is used.
368 */
369 disableElevation: PropTypes.bool,
370
371 /**
372 * If `true`, the keyboard focus ripple will be disabled.
373 */
374 disableFocusRipple: PropTypes.bool,
375
376 /**
377 * If `true`, the ripple effect will be disabled.
378 *
379 * ⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure
380 * to highlight the element by applying separate styles with the `focusVisibleClassName`.
381 */
382 disableRipple: PropTypes.bool,
383
384 /**
385 * Element placed after the children.
386 */
387 endIcon: PropTypes.node,
388
389 /**
390 * @ignore
391 */
392 focusVisibleClassName: PropTypes.string,
393
394 /**
395 * If `true`, the button will take up the full width of its container.
396 */
397 fullWidth: PropTypes.bool,
398
399 /**
400 * The URL to link to when the button is clicked.
401 * If defined, an `a` element will be used as the root node.
402 */
403 href: PropTypes.string,
404
405 /**
406 * The size of the button.
407 * `small` is equivalent to the dense button styling.
408 */
409 size: PropTypes.oneOf(['large', 'medium', 'small']),
410
411 /**
412 * Element placed before the children.
413 */
414 startIcon: PropTypes.node,
415
416 /**
417 * @ignore
418 */
419 type: PropTypes.oneOfType([PropTypes.oneOf(['button', 'reset', 'submit']), PropTypes.string]),
420
421 /**
422 * The variant to use.
423 */
424 variant: PropTypes.oneOf(['contained', 'outlined', 'text'])
425} : void 0;
426export default withStyles(styles, {
427 name: 'MuiButton'
428})(Button);
\No newline at end of file