123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- 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 = {
-
- alwaysRenderMenu: boolean;
-
- 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>;
-
- alignRight?: boolean;
-
- blendWithActor?: boolean;
-
- button?: (args: ButtonArgs) => React.ReactNode;
-
- buttonProps?: React.ComponentProps<typeof DropdownButton>;
-
- buttonTooltipTitle?: string | null;
- className?: string;
- detached?: boolean;
- fullWidth?: boolean;
-
- label?: NonNullable<React.ReactNode>;
- priority?: ButtonPriority;
- };
- 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};
|