/** ******************************************************************************************************************* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed 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, { useMemo, ReactNode, MouseEventHandler, FunctionComponent } from 'react'; import MaterialButton, { ButtonProps as MaterialButtonProps } from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/core/styles'; import IconButton from '@material-ui/core/IconButton'; import CircularProgress from '@material-ui/core/CircularProgress'; import ButtonIcon, { ButtonIconType as _ButtonIconType } from './components/ButtonIcon'; import Box from '../../layouts/Box'; const useStyles = makeStyles({ iconButton: { padding: '4px 12px', }, loadingIcon: { paddingRight: '2px', }, }); export interface ButtonProps { children?: ReactNode | string; /** * Determines the general styling of the button. * Use primary for primary buttons, normal for secondary buttons, link for tertiary buttons, icon to only display the icon without text. */ variant?: 'primary' | 'normal' | 'link' | 'icon'; /** * Renders a link with button styling. * Use this property if you need a link styled as a button (variant=link), * for example when you have a 'help' button that links to the documentation. * */ href?: string; /** * Fired when the user clicks on the button, and the button is not disabled or in loading state. */ onClick?: MouseEventHandler; /** * Renders the button as disabled and prevents clicks. * */ disabled?: boolean; /** * Displays an icon next to the text. Check the iconAlign property for positioning.
* Available options are 'add_plus' | 'copy' | 'external' | 'folder' | 'refresh' | 'settings'
* or Material UI Icon Component Type can be provided. * */ icon?: ButtonIconType; /** * Defines where icon should be * */ iconAlign?: 'left' | 'right'; /** * Renders the button as being in a loading state. * It takes precedence over the disabled if both are set to true. It prevents clicks. * */ loading?: boolean; /** * This property will be used as aria-label. * It should be used in buttons that don't have text in order to make them accessible. * */ label?: string; /** * The type of button. */ type?: 'button' | 'submit' | 'reset'; /** * The size of the button. * `small` is equivalent to the dense button styling. */ size?: 'small' | 'medium' | 'large'; } const OffsetCircularProgress = () => ( ); const muiButtonProps = ({ loading, disabled, onClick, variant, href, icon, iconAlign, label, type = 'button', size = 'medium', }: Partial): MaterialButtonProps => { const getVariantProps = () => { switch (variant) { case 'link': return { href }; case 'primary': return { variant: 'contained' as const, color: 'primary' as const }; case 'normal': return { variant: 'text' as const }; } return {}; }; return { disabled, onClick, type, size, 'aria-label': label, ...(icon && { [iconAlign === 'right' ? 'endIcon' : 'startIcon']: }), ...(loading && { startIcon: }), ...getVariantProps(), }; }; /** * A button allows users to trigger actions on the interface. */ const Button: FunctionComponent = ({ variant = 'normal', href = '', iconAlign = 'left', onClick, icon, loading, label, disabled, children, type = 'button', size = 'medium', ...props }) => { const styles = useStyles({}); const isDisabled = useMemo(() => disabled || loading, [disabled, loading]); switch (variant) { case 'icon': return ( {loading ? ( ) : ( )} ); default: return ( {children} ); } }; export default Button; export type ButtonIconType = _ButtonIconType; export { ButtonIcon };