github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/ui/Button.tsx (about) 1 import React, { ReactNode } from 'react'; 2 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 3 import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; 4 import cx from 'classnames'; 5 import styles from './Button.module.scss'; 6 7 export interface ButtonProps { 8 kind?: 'default' | 'primary' | 'secondary' | 'danger' | 'outline' | 'float'; 9 // kind?: 'default' | 'primary' | 'secondary' | 'danger' | 'float' | 'outline'; 10 /** Whether the button is disabled or not */ 11 disabled?: boolean; 12 icon?: IconDefinition; 13 iconNode?: ReactNode; 14 15 children?: React.ReactNode; 16 17 /** Buttons are grouped so that only the first and last have clear limits */ 18 grouped?: boolean; 19 20 onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; 21 22 // TODO 23 // for the full list use refer to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input 24 type?: 'button' | 'submit'; 25 ['data-testid']?: string; 26 27 ['aria-label']?: string; 28 29 className?: string; 30 31 id?: string; 32 form?: React.ButtonHTMLAttributes<HTMLButtonElement>['form']; 33 34 /** disable a box around it */ 35 noBox?: boolean; 36 37 /** ONLY use this if within a modal (https://stackoverflow.com/a/71848275 and https://citizensadvice.github.io/react-dialogs/modal/auto_focus/index.html) */ 38 autoFocus?: React.ButtonHTMLAttributes<HTMLButtonElement>['autoFocus']; 39 } 40 41 const Button = React.forwardRef(function Button( 42 { 43 disabled = false, 44 kind = 'default', 45 type = 'button', 46 icon, 47 iconNode, 48 children, 49 grouped, 50 onClick, 51 id, 52 className, 53 form, 54 noBox, 55 autoFocus, 56 ...props 57 }: ButtonProps, 58 ref: React.LegacyRef<HTMLButtonElement> 59 ) { 60 return ( 61 <button 62 // needed for tooltip 63 // eslint-disable-next-line react/jsx-props-no-spreading 64 {...props} 65 id={id} 66 ref={ref} 67 type={type} 68 data-testid={props['data-testid']} 69 disabled={disabled} 70 onClick={onClick} 71 form={form} 72 autoFocus={autoFocus} // eslint-disable-line jsx-a11y/no-autofocus 73 aria-label={props['aria-label']} 74 className={cx( 75 styles.button, 76 grouped ? styles.grouped : '', 77 getKindStyles(kind), 78 className, 79 noBox && styles.noBox, 80 iconNode && styles.customIcon, 81 !icon && !iconNode && styles.noIcon 82 )} 83 > 84 {icon ? ( 85 <FontAwesomeIcon 86 icon={icon} 87 className={children ? styles.iconWithText : ''} 88 /> 89 ) : null} 90 {iconNode} 91 {children} 92 </button> 93 ); 94 }); 95 96 function getKindStyles(kind: ButtonProps['kind']) { 97 switch (kind) { 98 case 'default': { 99 return styles.default; 100 } 101 102 case 'primary': { 103 return styles.primary; 104 } 105 106 case 'secondary': { 107 return styles.secondary; 108 } 109 110 case 'danger': { 111 return styles.danger; 112 } 113 114 case 'outline': { 115 return styles.outline; 116 } 117 118 case 'float': { 119 return styles.float; 120 } 121 122 default: { 123 throw Error(`Unsupported kind ${kind}`); 124 } 125 } 126 } 127 128 export default Button;