Browse Source

ref(dropdownControl): Remove V1 (#37310)

* ref(replay): Use CompactSelect for ChooseLayout dropdown

* ref(dropdownControl): Remove V1

* ref(storybook): Remove DropdownControl story

* fix(dropdownButton): Default to aria-haspopup="true"

* fix(tests): Fix Dashboards acceptance tests

* ref(DropdownMenuControl): Remove V2 from import names
Vu Luong 2 years ago
parent
commit
3215809f40

+ 0 - 122
docs-ui/stories/components/dropdownControl.stories.js

@@ -1,122 +0,0 @@
-import DropdownControl, {DropdownItem} from 'sentry/components/dropdownControl';
-import MenuItem from 'sentry/components/menuItem';
-
-export default {
-  title: 'Components/Buttons/Dropdowns/Dropdown Control',
-};
-
-export const BasicLabelKnobs = ({
-  menuWidth,
-  alwaysRenderMenu,
-  alignRight,
-  blendWithActor,
-}) => {
-  return (
-    <div className="clearfix">
-      <DropdownControl
-        label="Open Me"
-        menuWidth={menuWidth}
-        alwaysRenderMenu={alwaysRenderMenu}
-        alignRight={alignRight}
-        blendWithActor={blendWithActor}
-      >
-        <DropdownItem href="">Href Item</DropdownItem>
-        <DropdownItem to="">Router Item</DropdownItem>
-        <DropdownItem disabled>Disabled Item</DropdownItem>
-        <DropdownItem divider />
-        <DropdownItem isActive href="">
-          Active Item
-        </DropdownItem>
-      </DropdownControl>
-    </div>
-  );
-};
-
-BasicLabelKnobs.storyName = 'Basic Label + Knobs';
-BasicLabelKnobs.args = {
-  menuWidth: '',
-  alwaysRenderMenu: true,
-  alignRight: false,
-  blendWithActor: false,
-};
-BasicLabelKnobs.parameters = {
-  docs: {
-    description: {
-      story: 'Using a string value for the button label',
-    },
-  },
-};
-
-export const BasicMenuItem = () => (
-  <div className="clearfix">
-    <DropdownControl label={<em>Slanty</em>}>
-      <MenuItem href="">Item</MenuItem>
-      <MenuItem href="">Item</MenuItem>
-    </DropdownControl>
-  </div>
-);
-
-BasicMenuItem.storyName = 'Basic Menu Item';
-BasicMenuItem.parameters = {
-  docs: {
-    description: {
-      story: 'Element labels replace the button contents',
-    },
-  },
-};
-
-export const ElementLabel = () => (
-  <div className="clearfix">
-    <DropdownControl label="Created Date">
-      <MenuItem href="">Item</MenuItem>
-      <MenuItem href="">Item</MenuItem>
-    </DropdownControl>
-  </div>
-);
-
-ElementLabel.storyName = 'Element Label';
-ElementLabel.parameters = {
-  docs: {
-    description: {
-      story: 'Element labels replace the button contents',
-    },
-  },
-};
-
-export const PrefixedLabel = () => (
-  <div className="clearfix">
-    <DropdownControl buttonProps={{prefix: 'Sort By'}} label="Created Date">
-      <MenuItem href="">Item</MenuItem>
-      <MenuItem href="">Item</MenuItem>
-    </DropdownControl>
-  </div>
-);
-
-PrefixedLabel.storyName = 'Prefixed Label';
-PrefixedLabel.parameters = {
-  docs: {
-    description: {
-      story: 'Element labels replace the button contents',
-    },
-  },
-};
-
-export const CustomButton = () => (
-  <div className="clearfix">
-    <DropdownControl
-      button={({getActorProps}) => <button {...getActorProps()}>click me</button>}
-    >
-      <MenuItem href="">Item</MenuItem>
-      <MenuItem href="">Item</MenuItem>
-    </DropdownControl>
-  </div>
-);
-
-CustomButton.storyName = 'Custom Button';
-CustomButton.parameters = {
-  docs: {
-    description: {
-      story: 'button prop lets you replace the entire button.',
-    },
-  },
-};

+ 2 - 2
static/app/components/actions/ignore.tsx

@@ -6,7 +6,7 @@ import ButtonBar from 'sentry/components/buttonBar';
 import {openConfirmModal} from 'sentry/components/confirm';
 import CustomIgnoreCountModal from 'sentry/components/customIgnoreCountModal';
 import CustomIgnoreDurationModal from 'sentry/components/customIgnoreDurationModal';
-import DropdownMenuControlV2 from 'sentry/components/dropdownMenuControlV2';
+import DropdownMenuControl from 'sentry/components/dropdownMenuControl';
 import Duration from 'sentry/components/duration';
 import Tooltip from 'sentry/components/tooltip';
 import {IconChevron, IconMute} from 'sentry/icons';
@@ -214,7 +214,7 @@ const IgnoreActions = ({
       >
         {t('Ignore')}
       </IgnoreButton>
-      <DropdownMenuControlV2
+      <DropdownMenuControl
         trigger={({props: triggerProps, ref: triggerRef}) => (
           <DropdownTrigger
             ref={triggerRef}

+ 2 - 2
static/app/components/actions/resolve.tsx

@@ -7,7 +7,7 @@ import ButtonBar from 'sentry/components/buttonBar';
 import {openConfirmModal} from 'sentry/components/confirm';
 import CustomCommitsResolutionModal from 'sentry/components/customCommitsResolutionModal';
 import CustomResolutionModal from 'sentry/components/customResolutionModal';
-import DropdownMenuControlV2 from 'sentry/components/dropdownMenuControlV2';
+import DropdownMenuControl from 'sentry/components/dropdownMenuControl';
 import Tooltip from 'sentry/components/tooltip';
 import {IconCheckmark, IconChevron} from 'sentry/icons';
 import {t} from 'sentry/locale';
@@ -182,7 +182,7 @@ class ResolveActions extends Component<Props> {
     const isDisabled = !projectSlug ? disabled : disableDropdown;
 
     return (
-      <DropdownMenuControlV2
+      <DropdownMenuControl
         items={items}
         trigger={({props: triggerProps, ref: triggerRef}) => (
           <DropdownTrigger

+ 21 - 75
static/app/components/dropdownButton.tsx

@@ -5,19 +5,11 @@ import Button, {ButtonLabel, ButtonProps} from 'sentry/components/button';
 import {IconChevron} from 'sentry/icons';
 import space from 'sentry/styles/space';
 
-interface DropdownButtonProps extends Omit<ButtonProps, 'prefix'> {
-  /**
-   * Whether the menu associated with this button is visually detached.
-   */
-  detached?: boolean;
+export interface DropdownButtonProps extends Omit<ButtonProps, 'type' | 'prefix'> {
   /**
    * Forward a ref to the button's root
    */
-  forwardedRef?: React.Ref<typeof Button>;
-  /**
-   * Should the bottom border become transparent when open?
-   */
-  hideBottomBorder?: boolean;
+  forwardedRef?: React.ForwardedRef<HTMLElement>;
   /**
    * Whether or not the button should render as open
    */
@@ -26,116 +18,70 @@ interface DropdownButtonProps extends Omit<ButtonProps, 'prefix'> {
    * The fixed prefix text to show in the button eg: 'Sort By'
    */
   prefix?: React.ReactNode;
-  /**
-   * Button color
-   */
-  priority?: 'default' | 'primary' | 'form';
-  /**
-   * Align chevron to the right of dropdown button
-   */
-  rightAlignChevron?: boolean;
   /**
    * Should a chevron icon be shown?
    */
   showChevron?: boolean;
 }
 
-const DropdownButton = ({
+function DropdownButton({
   children,
-  forwardedRef,
   prefix,
   isOpen = false,
-  showChevron = false,
-  hideBottomBorder = true,
-  detached = false,
+  showChevron = true,
   disabled = false,
   priority = 'form',
-  rightAlignChevron = false,
+  forwardedRef,
   ...props
-}: DropdownButtonProps) => {
+}: DropdownButtonProps) {
   return (
     <StyledButton
-      {...props}
       type="button"
-      aria-haspopup="listbox"
-      aria-expanded={detached ? isOpen : undefined}
+      aria-haspopup="true"
+      aria-expanded={isOpen}
       hasPrefix={!!prefix}
       disabled={disabled}
       priority={priority}
       isOpen={isOpen}
-      hideBottomBorder={hideBottomBorder}
-      detached={detached}
       ref={forwardedRef}
+      {...props}
     >
       {prefix && <LabelText>{prefix}</LabelText>}
       {children}
       {showChevron && (
-        <StyledChevron
-          rightAlignChevron={rightAlignChevron}
-          size="xs"
-          direction={isOpen ? 'up' : 'down'}
-        />
+        <StyledChevron size="xs" direction={isOpen ? 'up' : 'down'} aria-hidden="true" />
       )}
     </StyledButton>
   );
-};
-
-DropdownButton.defaultProps = {
-  showChevron: true,
-};
-
-const StyledChevron = styled(IconChevron, {
-  shouldForwardProp: prop => prop !== 'rightAlignChevron',
-})<{
-  rightAlignChevron: boolean;
-}>`
-  margin-left: 0.33em;
+}
 
-  @media (max-width: ${p => p.theme.breakpoints.small}) {
-    position: ${p => p.rightAlignChevron && 'absolute'};
-    right: ${p => p.rightAlignChevron && `${space(2)}`};
-  }
+const StyledChevron = styled(IconChevron)`
+  margin-left: ${space(0.75)};
+  flex-shrink: 0;
 `;
 
 const StyledButton = styled(Button)<
-  Required<
-    Pick<
-      DropdownButtonProps,
-      'isOpen' | 'disabled' | 'hideBottomBorder' | 'detached' | 'priority'
-    >
-  > & {
+  Required<Pick<DropdownButtonProps, 'isOpen' | 'disabled' | 'priority'>> & {
     hasPrefix: boolean;
   }
 >`
-  border-bottom-right-radius: ${p =>
-    p.isOpen && !p.detached ? 0 : p.theme.borderRadius};
-  border-bottom-left-radius: ${p => (p.isOpen && !p.detached ? 0 : p.theme.borderRadius)};
   position: relative;
+  max-width: 100%;
   z-index: 2;
 
-  ${p => (p.isOpen || p.disabled) && 'box-shadow: none'};
+  ${p => (p.isOpen || p.disabled) && 'box-shadow: none;'}
   ${p => p.hasPrefix && `${ButtonLabel} {font-weight: 400;}`}
-
-  &,
-  &:active,
-  &:focus,
-  &:hover {
-    ${p =>
-      p.isOpen &&
-      p.hideBottomBorder &&
-      !p.detached &&
-      `border-bottom-color: transparent;`}
-  }
 `;
 
 const LabelText = styled('span')`
-  font-weight: 600;
-  padding-right: ${space(0.75)};
   &:after {
     content: ':';
   }
+
+  font-weight: 600;
+  padding-right: ${space(0.75)};
 `;
 
-export default forwardRef<typeof Button, DropdownButtonProps>((props, ref) => (
+export default forwardRef<HTMLElement, DropdownButtonProps>((props, ref) => (
   <DropdownButton forwardedRef={ref} {...props} />
 ));

+ 0 - 81
static/app/components/dropdownButtonV2.tsx

@@ -1,81 +0,0 @@
-import {forwardRef} from 'react';
-import styled from '@emotion/styled';
-
-import Button, {ButtonLabel, ButtonProps} from 'sentry/components/button';
-import {IconChevron} from 'sentry/icons';
-import space from 'sentry/styles/space';
-
-export type DropdownButtonProps = {
-  /**
-   * Whether or not the button should render as open
-   */
-  isOpen?: boolean;
-  /**
-   * The fixed prefix text to show in the button eg: 'Sort By'
-   */
-  prefix?: React.ReactNode;
-  /**
-   * Should a chevron icon be shown?
-   */
-  showChevron?: boolean;
-} & Omit<ButtonProps, 'type' | 'prefix'>;
-
-const DropdownButton = forwardRef<HTMLElement, DropdownButtonProps>(
-  (
-    {
-      children,
-      prefix,
-      isOpen = false,
-      showChevron = true,
-      disabled = false,
-      priority = 'form',
-      ...props
-    }: DropdownButtonProps,
-    ref
-  ) => (
-    <StyledButton
-      {...props}
-      type="button"
-      hasPrefix={!!prefix}
-      disabled={disabled}
-      priority={priority}
-      isOpen={isOpen}
-      ref={ref}
-    >
-      {prefix && <LabelText>{prefix}</LabelText>}
-      {children}
-      {showChevron && (
-        <StyledChevron size="xs" direction={isOpen ? 'up' : 'down'} aria-hidden="true" />
-      )}
-    </StyledButton>
-  )
-);
-
-const StyledChevron = styled(IconChevron)`
-  margin-left: ${space(0.75)};
-  flex-shrink: 0;
-`;
-
-const StyledButton = styled(Button)<
-  Required<Pick<DropdownButtonProps, 'isOpen' | 'disabled' | 'priority'>> & {
-    hasPrefix: boolean;
-  }
->`
-  position: relative;
-  max-width: 100%;
-  z-index: 2;
-
-  ${p => (p.isOpen || p.disabled) && 'box-shadow: none;'}
-  ${p => p.hasPrefix && `${ButtonLabel} {font-weight: 400;}`}
-`;
-
-const LabelText = styled('span')`
-  &:after {
-    content: ':';
-  }
-
-  font-weight: 600;
-  padding-right: ${space(0.75)};
-`;
-
-export default DropdownButton;

+ 0 - 204
static/app/components/dropdownControl.tsx

@@ -1,204 +0,0 @@
-import {Component, Fragment} from 'react';
-import styled from '@emotion/styled';
-
-import DropdownBubble from 'sentry/components/dropdownBubble';
-import DropdownButton from 'sentry/components/dropdownButton';
-import DropdownMenu, {
-  GetActorPropsFn,
-  GetMenuPropsFn,
-} from 'sentry/components/dropdownMenu';
-import MenuItem from 'sentry/components/menuItem';
-import Tooltip from 'sentry/components/tooltip';
-
-type ButtonPriority = React.ComponentProps<typeof DropdownButton>['priority'];
-
-type DefaultProps = {
-  /**
-   * Should the menu contents always be rendered?  Defaults to true.
-   * Set to false to have menu contents removed from the DOM on close.
-   */
-  alwaysRenderMenu: boolean;
-  /**
-   * Width of the menu. Defaults to 100% of the button width.
-   */
-  menuWidth: string;
-};
-
-type ChildrenArgs = {
-  getMenuProps: GetMenuPropsFn;
-  isOpen: boolean;
-};
-
-type ButtonArgs = {
-  getActorProps: GetActorPropsFn;
-  isOpen: boolean;
-};
-
-type Props = DefaultProps & {
-  children:
-    | ((args: ChildrenArgs) => React.ReactElement)
-    | React.ReactElement
-    | Array<React.ReactElement>;
-  /**
-   * Align the dropdown menu to the right. (Default aligns to left)
-   */
-  alignRight?: boolean;
-  /**
-   * This makes the dropdown menu blend (e.g. corners are not rounded) with its
-   * actor (opener) component
-   */
-  blendWithActor?: boolean;
-  /**
-   * A closure that returns a styled button. Function will get {isOpen, getActorProps}
-   * as arguments. Use this if you need to style/replace the dropdown button.
-   */
-  button?: (args: ButtonArgs) => React.ReactNode;
-  /**
-   * Props to pass to DropdownButton
-   */
-  buttonProps?: React.ComponentProps<typeof DropdownButton>;
-  /**
-   * Tooltip to show on button when dropdown isn't open
-   */
-  buttonTooltipTitle?: string | null;
-  className?: string;
-  detached?: boolean;
-  fullWidth?: boolean;
-
-  /**
-   * String or element for the button contents.
-   */
-  label?: NonNullable<React.ReactNode>;
-
-  priority?: ButtonPriority;
-};
-
-/*
- * A higher level dropdown component that helps with building complete dropdowns
- * including the button + menu options. Use the `button` or `label` prop to set
- * the button content and `children` to provide menu options.
- */
-class DropdownControl extends Component<Props> {
-  static defaultProps: DefaultProps = {
-    alwaysRenderMenu: true,
-    menuWidth: '100%',
-  };
-
-  renderButton(isOpen: boolean, getActorProps: GetActorPropsFn) {
-    const {
-      label,
-      button,
-      buttonProps,
-      buttonTooltipTitle,
-      priority,
-      detached,
-      fullWidth,
-    } = this.props;
-
-    if (button) {
-      return button({isOpen, getActorProps});
-    }
-
-    if (buttonTooltipTitle && !isOpen) {
-      return (
-        <Tooltip skipWrapper position="top" title={buttonTooltipTitle}>
-          <StyledDropdownButton
-            priority={priority}
-            {...getActorProps(buttonProps)}
-            isOpen={isOpen}
-            data-test-id="dropdown-control-button"
-            detached={detached}
-            hideBottomBorder={!detached}
-            rightAlignChevron={fullWidth ?? false}
-          >
-            {label}
-          </StyledDropdownButton>
-        </Tooltip>
-      );
-    }
-
-    return (
-      <StyledDropdownButton
-        priority={priority}
-        {...getActorProps(buttonProps)}
-        isOpen={isOpen}
-        data-test-id="dropdown-control-button"
-        detached={detached}
-        hideBottomBorder={!detached}
-        rightAlignChevron={fullWidth ?? false}
-      >
-        {label}
-      </StyledDropdownButton>
-    );
-  }
-
-  renderChildren(isOpen: boolean, getMenuProps: GetMenuPropsFn) {
-    const {children, alignRight, menuWidth, blendWithActor, priority, detached} =
-      this.props;
-
-    if (typeof children === 'function') {
-      return children({isOpen, getMenuProps});
-    }
-
-    const alignMenu = alignRight ? 'right' : 'left';
-
-    return (
-      <Content
-        {...getMenuProps()}
-        priority={priority}
-        alignMenu={alignMenu}
-        width={menuWidth}
-        isOpen={isOpen}
-        blendWithActor={blendWithActor}
-        detached={detached}
-        blendCorner
-        data-test-id="dropdown-control"
-      >
-        {children}
-      </Content>
-    );
-  }
-
-  render() {
-    const {alwaysRenderMenu, className, fullWidth} = this.props;
-
-    return (
-      <Container className={className} fullWidth={fullWidth ?? false}>
-        <DropdownMenu alwaysRenderMenu={alwaysRenderMenu}>
-          {({isOpen, getMenuProps, getActorProps}) => (
-            <Fragment>
-              {this.renderButton(isOpen, getActorProps)}
-              {this.renderChildren(isOpen, getMenuProps)}
-            </Fragment>
-          )}
-        </DropdownMenu>
-      </Container>
-    );
-  }
-}
-
-const Container = styled('div')<{fullWidth: boolean}>`
-  display: inline-block;
-  position: relative;
-
-  @media (max-width: ${p => p.theme.breakpoints.small}) {
-    width: ${p => p.fullWidth && '100%'};
-  }
-`;
-
-const StyledDropdownButton = styled(DropdownButton)`
-  z-index: ${p => p.theme.zIndex.dropdownAutocomplete.actor};
-  white-space: nowrap;
-`;
-
-const Content = styled(DropdownBubble)<{isOpen: boolean; priority?: ButtonPriority}>`
-  display: ${p => (p.isOpen ? 'block' : 'none')};
-  border-color: ${p => p.theme.button[p.priority || 'form'].border};
-`;
-
-const DropdownItem = styled(MenuItem)`
-  font-size: ${p => p.theme.fontSizeMedium};
-`;
-
-export default DropdownControl;
-export {DropdownItem, Content};

+ 2 - 2
static/app/components/dropdownMenuControlV2.tsx → static/app/components/dropdownMenuControl.tsx

@@ -8,8 +8,8 @@ import {Item, Section} from '@react-stately/collections';
 import {useMenuTriggerState} from '@react-stately/menu';
 import {MenuTriggerProps} from '@react-types/menu';
 
-import DropdownButton, {DropdownButtonProps} from 'sentry/components/dropdownButtonV2';
-import {MenuItemProps} from 'sentry/components/dropdownMenuItemV2';
+import DropdownButton, {DropdownButtonProps} from 'sentry/components/dropdownButton';
+import {MenuItemProps} from 'sentry/components/dropdownMenuItem';
 import Menu from 'sentry/components/dropdownMenuV2';
 
 type TriggerProps = {

+ 0 - 0
static/app/components/dropdownMenuItemV2.tsx → static/app/components/dropdownMenuItem.tsx


+ 1 - 1
static/app/components/dropdownMenuSectionV2.tsx → static/app/components/dropdownMenuSection.tsx

@@ -2,7 +2,7 @@ import styled from '@emotion/styled';
 import {useMenuSection} from '@react-aria/menu';
 import {Node} from '@react-types/shared';
 
-import {MenuItemProps} from 'sentry/components/dropdownMenuItemV2';
+import {MenuItemProps} from 'sentry/components/dropdownMenuItem';
 import space from 'sentry/styles/space';
 
 type Props = {

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

@@ -15,9 +15,9 @@ import {mergeProps} from '@react-aria/utils';
 import {useTreeState} from '@react-stately/tree';
 import {Node} from '@react-types/shared';
 
-import MenuControl from 'sentry/components/dropdownMenuControlV2';
-import MenuItem, {MenuItemProps} from 'sentry/components/dropdownMenuItemV2';
-import MenuSection from 'sentry/components/dropdownMenuSectionV2';
+import MenuControl from 'sentry/components/dropdownMenuControl';
+import MenuItem, {MenuItemProps} from 'sentry/components/dropdownMenuItem';
+import MenuSection from 'sentry/components/dropdownMenuSection';
 import space from 'sentry/styles/space';
 
 type Props = {

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