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 interface DropdownButtonProps extends Omit<ButtonProps, 'type' | 'prefix'> { /** * Forward a ref to the button's root */ forwardedRef?: React.ForwardedRef<HTMLElement>; /** * 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; } function DropdownButton({ children, prefix, isOpen = false, showChevron = true, disabled = false, priority = 'form', forwardedRef, ...props }: DropdownButtonProps) { return ( <StyledButton type="button" aria-haspopup="true" aria-expanded={isOpen} hasPrefix={!!prefix} disabled={disabled} priority={priority} isOpen={isOpen} ref={forwardedRef} {...props} > {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 forwardRef<HTMLElement, DropdownButtonProps>((props, ref) => ( <DropdownButton forwardedRef={ref} {...props} /> ));