| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| import React, { CSSProperties } from 'react'; |
| import { kebabCase } from 'lodash'; |
| import { mix } from 'polished'; |
| import cx from 'classnames'; |
| import { Button as AntdButton } from 'src/common/components'; |
| import { useTheme } from '@superset-ui/core'; |
| import { Tooltip } from 'src/common/components/Tooltip'; |
| |
| export type OnClickHandler = React.MouseEventHandler<HTMLElement>; |
| |
| export interface ButtonProps { |
| id?: string; |
| className?: string; |
| tooltip?: string; |
| placement?: |
| | 'bottom' |
| | 'left' |
| | 'right' |
| | 'top' |
| | 'topLeft' |
| | 'topRight' |
| | 'bottomLeft' |
| | 'bottomRight' |
| | 'leftTop' |
| | 'leftBottom' |
| | 'rightTop' |
| | 'rightBottom'; |
| onClick?: OnClickHandler; |
| disabled?: boolean; |
| buttonStyle?: |
| | 'primary' |
| | 'secondary' |
| | 'tertiary' |
| | 'success' |
| | 'warning' |
| | 'danger' |
| | 'default' |
| | 'link' |
| | 'dashed'; |
| buttonSize?: 'default' | 'small' | 'xsmall'; |
| style?: CSSProperties; |
| children?: React.ReactNode; |
| href?: string; |
| htmlType?: 'button' | 'submit' | 'reset'; |
| cta?: boolean; |
| } |
| |
| export default function Button(props: ButtonProps) { |
| const { |
| tooltip, |
| placement, |
| disabled = false, |
| buttonSize, |
| buttonStyle, |
| className, |
| cta, |
| children, |
| href, |
| ...restProps |
| } = props; |
| |
| const theme = useTheme(); |
| const { colors, transitionTiming, borderRadius, typography } = theme; |
| const { primary, grayscale, success, warning, error } = colors; |
| |
| let height = 32; |
| let padding = 18; |
| if (buttonSize === 'xsmall') { |
| height = 22; |
| padding = 5; |
| } else if (buttonSize === 'small') { |
| height = 30; |
| padding = 10; |
| } |
| |
| let backgroundColor = primary.light4; |
| let backgroundColorHover = mix(0.1, primary.base, primary.light4); |
| let backgroundColorActive = mix(0.25, primary.base, primary.light4); |
| let backgroundColorDisabled = grayscale.light2; |
| let color = primary.dark1; |
| let colorHover = color; |
| let borderWidth = 0; |
| let borderStyle = 'none'; |
| let borderColor = 'transparent'; |
| let borderColorHover = 'transparent'; |
| let borderColorDisabled = 'transparent'; |
| |
| if (buttonStyle === 'primary') { |
| backgroundColor = primary.dark1; |
| backgroundColorHover = mix(0.1, grayscale.light5, primary.dark1); |
| backgroundColorActive = mix(0.2, grayscale.dark2, primary.dark1); |
| color = grayscale.light5; |
| colorHover = color; |
| } else if (buttonStyle === 'tertiary' || buttonStyle === 'dashed') { |
| backgroundColor = grayscale.light5; |
| backgroundColorHover = grayscale.light5; |
| backgroundColorActive = grayscale.light5; |
| backgroundColorDisabled = grayscale.light5; |
| borderWidth = 1; |
| borderStyle = buttonStyle === 'dashed' ? 'dashed' : 'solid'; |
| borderColor = primary.dark1; |
| borderColorHover = primary.light1; |
| borderColorDisabled = grayscale.light2; |
| } else if (buttonStyle === 'danger') { |
| backgroundColor = error.base; |
| backgroundColorHover = mix(0.1, grayscale.light5, error.base); |
| backgroundColorActive = mix(0.2, grayscale.dark2, error.base); |
| color = grayscale.light5; |
| colorHover = color; |
| } else if (buttonStyle === 'warning') { |
| backgroundColor = warning.base; |
| backgroundColorHover = mix(0.1, grayscale.dark2, warning.base); |
| backgroundColorActive = mix(0.2, grayscale.dark2, warning.base); |
| color = grayscale.light5; |
| colorHover = color; |
| } else if (buttonStyle === 'success') { |
| backgroundColor = success.base; |
| backgroundColorHover = mix(0.1, grayscale.light5, success.base); |
| backgroundColorActive = mix(0.2, grayscale.dark2, success.base); |
| color = grayscale.light5; |
| colorHover = color; |
| } else if (buttonStyle === 'link') { |
| backgroundColor = 'transparent'; |
| backgroundColorHover = 'transparent'; |
| backgroundColorActive = 'transparent'; |
| colorHover = primary.base; |
| } |
| |
| const button = ( |
| <AntdButton |
| href={disabled ? undefined : href} |
| disabled={disabled} |
| className={cx(className, { cta: !!cta })} |
| css={{ |
| display: 'inline-flex', |
| alignItems: 'center', |
| justifyContent: 'center', |
| lineHeight: 1.5715, |
| fontSize: typography.sizes.s, |
| fontWeight: typography.weights.bold, |
| height, |
| textTransform: 'uppercase', |
| padding: `0px ${padding}px`, |
| transition: `all ${transitionTiming}s`, |
| minWidth: cta ? theme.gridUnit * 36 : undefined, |
| minHeight: cta ? theme.gridUnit * 8 : undefined, |
| boxShadow: 'none', |
| borderWidth, |
| borderStyle, |
| borderColor, |
| borderRadius, |
| color, |
| backgroundColor, |
| '&:hover': { |
| color: colorHover, |
| backgroundColor: backgroundColorHover, |
| borderColor: borderColorHover, |
| }, |
| '&:active': { |
| color, |
| backgroundColor: backgroundColorActive, |
| }, |
| '&:focus': { |
| color, |
| backgroundColor, |
| borderColor, |
| }, |
| '&[disabled], &[disabled]:hover': { |
| color: grayscale.base, |
| backgroundColor: backgroundColorDisabled, |
| borderColor: borderColorDisabled, |
| }, |
| 'i:first-of-type, svg:first-of-type': { |
| marginRight: theme.gridUnit * 2, |
| padding: `0 ${theme.gridUnit * 2} 0 0`, |
| }, |
| marginLeft: theme.gridUnit * 2, |
| '&:first-of-type': { |
| marginLeft: 0, |
| }, |
| }} |
| {...restProps} |
| > |
| {children} |
| </AntdButton> |
| ); |
| |
| if (tooltip) { |
| return ( |
| <Tooltip |
| placement={placement} |
| id={`${kebabCase(tooltip)}-tooltip`} |
| title={tooltip} |
| > |
| {button} |
| </Tooltip> |
| ); |
| } |
| |
| return button; |
| } |