Browse Source

ref(button): improve tsc compile time (#31699)

* ref(button): use interface for props

* ref(button): adopt the new conditional aria type

* ref(button): export both props

* ref(button): fix styled prop

* ref(button): modify imports

* fix(button): revert old changes

* fix(button): relax children type

* fix(button): aria label casing

* Update static/app/components/confirm.tsx

Co-authored-by: Priscila Oliveira <priscila.oliveira@sentry.io>

* Update static/app/components/confirm.tsx

Co-authored-by: Priscila Oliveira <priscila.oliveira@sentry.io>

* style(lint): Auto commit lint changes

* style(lint): Auto commit lint changes

* ref(components): use withoutaria props

* fix(button): omit prop at the right place

* fix(addintegrationbutton): remove child

Co-authored-by: Priscila Oliveira <priscila.oliveira@sentry.io>
Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
Jonas 3 years ago
parent
commit
9b344aaa7e

+ 4 - 4
static/app/components/actions/button.tsx

@@ -1,9 +1,9 @@
 import * as React from 'react';
 
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 
-const ActionButton = (props: React.ComponentProps<typeof Button>) => (
-  <Button size="xsmall" {...props} />
-);
+function ActionButton(props: ButtonProps): React.ReactElement {
+  return <Button size="xsmall" {...props} />;
+}
 
 export default ActionButton;

+ 3 - 3
static/app/components/activity/note/input.tsx

@@ -3,7 +3,7 @@ import {Mention, MentionsInput, MentionsInputProps} from 'react-mentions';
 import {withTheme} from '@emotion/react';
 import styled from '@emotion/styled';
 
-import Button from 'sentry/components/button';
+import Button, {ButtonPropsWithoutAriaLabel} from 'sentry/components/button';
 import NavTabs from 'sentry/components/navTabs';
 import {IconMarkdown} from 'sentry/icons';
 import {t} from 'sentry/locale';
@@ -363,9 +363,9 @@ const Footer = styled('div')`
   padding-left: ${space(1.5)};
 `;
 
-type FooterButtonProps = {
+interface FooterButtonProps extends ButtonPropsWithoutAriaLabel {
   error?: string | null;
-} & React.ComponentProps<typeof Button>;
+}
 
 const FooterButton = styled(Button)<FooterButtonProps>`
   font-size: 13px;

+ 21 - 19
static/app/components/button.tsx

@@ -17,23 +17,18 @@ import {Theme} from 'sentry/utils/theme';
  */
 type ButtonElement = HTMLButtonElement & HTMLAnchorElement & any;
 
-type ConditionalAriaLabel =
-  | {
-      children: Omit<React.ReactNode, 'null' | 'undefined' | 'boolean'>;
-      'aria-label'?: string;
-    }
-  | {
-      'aria-label': string;
-      children?: null | boolean;
-    };
-
-type Props = {
+interface BaseButtonProps
+  extends Omit<
+    React.ButtonHTMLAttributes<ButtonElement>,
+    'ref' | 'label' | 'size' | 'title'
+  > {
   align?: 'center' | 'left' | 'right';
   // This is only used with `<ButtonBar>`
   barId?: string;
   borderless?: boolean;
   busy?: boolean;
   disabled?: boolean;
+  download?: HTMLAnchorElement['download'];
   external?: boolean;
   forwardRef?: React.Ref<ButtonElement>;
   href?: string;
@@ -41,16 +36,24 @@ type Props = {
   name?: string;
   onClick?: (e: React.MouseEvent) => void;
   priority?: 'default' | 'primary' | 'danger' | 'link' | 'success' | 'form';
+  rel?: HTMLAnchorElement['rel'];
   size?: 'zero' | 'xsmall' | 'small';
+  target?: HTMLAnchorElement['target'];
   title?: React.ComponentProps<typeof Tooltip>['title'];
   to?: string | object;
   tooltipProps?: Omit<Tooltip['props'], 'children' | 'title' | 'skipWrapper'>;
-
   translucentBorder?: boolean;
-} & ConditionalAriaLabel;
+}
 
-type ButtonProps = Omit<React.HTMLProps<ButtonElement>, keyof Props | 'ref' | 'label'> &
-  Props;
+export interface ButtonPropsWithoutAriaLabel extends BaseButtonProps {
+  children: React.ReactNode;
+}
+export interface ButtonPropsWithAriaLabel extends BaseButtonProps {
+  'aria-label': string;
+  children?: never;
+}
+
+export type ButtonProps = ButtonPropsWithoutAriaLabel | ButtonPropsWithAriaLabel;
 
 type Url = ButtonProps['to'] | ButtonProps['href'];
 
@@ -71,7 +74,7 @@ function BaseButton({
   tooltipProps,
   onClick,
   ...buttonProps
-}: Props) {
+}: ButtonProps) {
   // Intercept onClick and propagate
   function handleClick(e: React.MouseEvent) {
     // Don't allow clicks when disabled or busy
@@ -147,7 +150,6 @@ const Button = reactForwardRef<ButtonElement, ButtonProps>((props, ref) => (
 ));
 
 Button.displayName = 'Button';
-
 export default Button;
 
 type StyledButtonProps = ButtonProps & {theme: Theme};
@@ -272,7 +274,7 @@ const getSizeStyles = ({size, translucentBorder, theme}: StyledButtonProps) => {
 const StyledButton = styled(
   reactForwardRef<any, ButtonProps>(
     (
-      {forwardRef, size: _size, external, to, href, disabled, ...otherProps}: Props,
+      {forwardRef, size: _size, external, to, href, disabled, ...otherProps}: ButtonProps,
       forwardRefAlt
     ) => {
       // XXX: There may be two forwarded refs here, one potentially passed from a
@@ -309,7 +311,7 @@ const StyledButton = styled(
       prop === 'external' ||
       (typeof prop === 'string' && isPropValid(prop)),
   }
-)<Props>`
+)<ButtonProps>`
   display: inline-block;
   border-radius: ${p => p.theme.button.borderRadius};
   text-transform: none;

+ 2 - 2
static/app/components/buttonBar.tsx

@@ -3,12 +3,12 @@ import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 import classNames from 'classnames';
 
-import Button, {StyledButton} from 'sentry/components/button';
+import {ButtonProps, StyledButton} from 'sentry/components/button';
 import space, {ValidSize} from 'sentry/styles/space';
 
 type ButtonBarProps = {
   children: React.ReactNode;
-  active?: React.ComponentProps<typeof Button>['barId'];
+  active?: ButtonProps['barId'];
   className?: string;
   gap?: ValidSize;
   merged?: boolean;

+ 4 - 4
static/app/components/confirm.tsx

@@ -1,7 +1,7 @@
 import * as React from 'react';
 
 import {ModalRenderProps, openModal} from 'sentry/actionCreators/modal';
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 import ButtonBar from 'sentry/components/buttonBar';
 import {t} from 'sentry/locale';
 
@@ -93,7 +93,7 @@ export type OpenConfirmOptions = {
   /**
    * Button priority
    */
-  priority?: React.ComponentProps<typeof Button>['priority'];
+  priority?: ButtonProps['priority'];
   /**
    * Custom function to render the cancel button
    */
@@ -305,7 +305,7 @@ class ConfirmModal extends React.Component<ModalProps, ModalState> {
                 onClick={this.handleClose}
                 aria-label={typeof cancelText === 'string' ? cancelText : t('Cancel')}
               >
-                {cancelText}
+                {cancelText ?? t('Cancel')}
               </Button>
             )}
             {renderConfirmButton ? (
@@ -322,7 +322,7 @@ class ConfirmModal extends React.Component<ModalProps, ModalState> {
                 autoFocus
                 aria-label={typeof confirmText === 'string' ? confirmText : t('Confirm')}
               >
-                {confirmText}
+                {confirmText ?? t('Confirm')}
               </Button>
             )}
           </ButtonBar>

+ 5 - 7
static/app/components/createAlertButton.tsx

@@ -11,9 +11,10 @@ import {navigateTo} from 'sentry/actionCreators/navigation';
 import Access from 'sentry/components/acl/access';
 import Alert from 'sentry/components/alert';
 import GuideAnchor from 'sentry/components/assistant/guideAnchor';
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 import Link from 'sentry/components/links/link';
 import {IconClose, IconInfo, IconSiren} from 'sentry/icons';
+import {SVGIconProps} from 'sentry/icons/svgIcon';
 import {t, tct} from 'sentry/locale';
 import {Organization, Project} from 'sentry/types';
 import EventView from 'sentry/utils/discover/eventView';
@@ -182,10 +183,7 @@ function IncompatibleQueryAlert({
   );
 }
 
-type CreateAlertFromViewButtonProps = Omit<
-  React.ComponentProps<typeof Button>,
-  'aria-label'
-> & {
+type CreateAlertFromViewButtonProps = ButtonProps & {
   /**
    * Discover query used to create the alert
    */
@@ -327,12 +325,12 @@ function CreateAlertFromViewButton({
 type Props = {
   organization: Organization;
   hideIcon?: boolean;
-  iconProps?: React.ComponentProps<typeof IconSiren>;
+  iconProps?: SVGIconProps;
   projectSlug?: string;
   referrer?: string;
   showPermissionGuide?: boolean;
 } & WithRouterProps &
-  React.ComponentProps<typeof Button>;
+  ButtonProps;
 
 const CreateAlertButton = withRouter(
   ({

+ 4 - 4
static/app/components/demoSandboxButton.tsx

@@ -1,9 +1,9 @@
-import Button from 'sentry/components/button';
+import Button, {ButtonPropsWithoutAriaLabel} from 'sentry/components/button';
 import {Organization, SandboxData} from 'sentry/types';
 import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
 import useOrganization from 'sentry/utils/useOrganization';
 
-type Props = {
+interface DemoSandboxButtonProps extends ButtonPropsWithoutAriaLabel {
   /**
    * The deep link scenario
    */
@@ -32,7 +32,7 @@ type Props = {
    * Which project we should link to in the sandbox
    */
   projectSlug?: 'react' | 'python' | 'ios' | 'android' | 'react-native';
-} & React.ComponentProps<typeof Button>;
+}
 
 /**
  * Renders a button that will kick off the sandbox around children
@@ -45,7 +45,7 @@ function DemoSandboxButton({
   errorType,
   clientData,
   ...buttonProps
-}: Props) {
+}: DemoSandboxButtonProps): React.ReactElement {
   const organization: Organization = useOrganization();
   const url = new URL('https://try.sentry-demo.com/demo/start/');
 

+ 3 - 3
static/app/components/discoverButton.tsx

@@ -1,16 +1,16 @@
 import * as React from 'react';
 
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 import DiscoverFeature from 'sentry/components/discover/discoverFeature';
 import {t} from 'sentry/locale';
 
-type Props = Omit<React.ComponentProps<typeof Button>, 'aria-label'>;
+type DiscoverButtonProps = Omit<ButtonProps, 'aria-label'>;
 
 /**
  * Provide a button that turns itself off if the current organization
  * doesn't have access to discover results.
  */
-function DiscoverButton({children, ...buttonProps}: Props) {
+function DiscoverButton({children, ...buttonProps}: DiscoverButtonProps) {
   return (
     <DiscoverFeature>
       {({hasFeature}) => (

+ 8 - 6
static/app/components/dropdownButton.tsx

@@ -1,11 +1,11 @@
 import * as React from 'react';
 import styled from '@emotion/styled';
 
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 import {IconChevron} from 'sentry/icons';
 import space from 'sentry/styles/space';
 
-type Props = Omit<React.ComponentProps<typeof Button>, 'type' | 'priority'> & {
+interface DropdownButtonProps extends Omit<ButtonProps, 'prefix'> {
   /**
    * Forward a ref to the button's root
    */
@@ -30,7 +30,7 @@ type Props = Omit<React.ComponentProps<typeof Button>, 'type' | 'priority'> & {
    * Should a chevron icon be shown?
    */
   showChevron?: boolean;
-};
+}
 
 const DropdownButton = ({
   children,
@@ -42,7 +42,7 @@ const DropdownButton = ({
   disabled = false,
   priority = 'form',
   ...props
-}: Props) => {
+}: DropdownButtonProps) => {
   return (
     <StyledButton
       {...props}
@@ -69,7 +69,9 @@ const StyledChevron = styled(IconChevron)`
 `;
 
 const StyledButton = styled(Button)<
-  Required<Pick<Props, 'isOpen' | 'disabled' | 'hideBottomBorder' | 'priority'>>
+  Required<
+    Pick<DropdownButtonProps, 'isOpen' | 'disabled' | 'hideBottomBorder' | 'priority'>
+  >
 >`
   border-bottom-right-radius: ${p => (p.isOpen ? 0 : p.theme.borderRadius)};
   border-bottom-left-radius: ${p => (p.isOpen ? 0 : p.theme.borderRadius)};
@@ -95,6 +97,6 @@ const LabelText = styled('span')`
   }
 `;
 
-export default React.forwardRef<typeof Button, Props>((props, ref) => (
+export default React.forwardRef<typeof Button, DropdownButtonProps>((props, ref) => (
   <DropdownButton forwardedRef={ref} {...props} />
 ));

+ 3 - 4
static/app/components/dropdownButtonV2.tsx

@@ -1,12 +1,11 @@
 import {forwardRef} from 'react';
 import styled from '@emotion/styled';
 
-import Button from 'sentry/components/button';
+import Button, {ButtonProps} from 'sentry/components/button';
 import {IconChevron} from 'sentry/icons';
 import space from 'sentry/styles/space';
 
-export type DropdownButtonProps = Omit<React.ComponentProps<typeof Button>, 'type'> & {
-  children?: React.ReactNode;
+export type DropdownButtonProps = {
   /**
    * Whether or not the button should render as open
    */
@@ -19,7 +18,7 @@ export type DropdownButtonProps = Omit<React.ComponentProps<typeof Button>, 'typ
    * Should a chevron icon be shown?
    */
   showChevron?: boolean;
-};
+} & Omit<ButtonProps, 'type' | 'prefix'>;
 
 const DropdownButton = forwardRef<
   React.RefObject<HTMLElement> | null,

Some files were not shown because too many files changed in this diff