dropdownButtonV2.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import {forwardRef} from 'react';
  2. import styled from '@emotion/styled';
  3. import Button, {ButtonLabel, ButtonProps} from 'sentry/components/button';
  4. import {IconChevron} from 'sentry/icons';
  5. import space from 'sentry/styles/space';
  6. export type DropdownButtonProps = {
  7. /**
  8. * Whether or not the button should render as open
  9. */
  10. isOpen?: boolean;
  11. /**
  12. * The fixed prefix text to show in the button eg: 'Sort By'
  13. */
  14. prefix?: React.ReactNode;
  15. /**
  16. * Should a chevron icon be shown?
  17. */
  18. showChevron?: boolean;
  19. } & Omit<ButtonProps, 'type' | 'prefix'>;
  20. const DropdownButton = forwardRef<
  21. React.RefObject<HTMLElement> | null,
  22. DropdownButtonProps
  23. >(
  24. (
  25. {
  26. children,
  27. prefix,
  28. isOpen = false,
  29. showChevron = true,
  30. disabled = false,
  31. priority = 'form',
  32. ...props
  33. }: DropdownButtonProps,
  34. ref
  35. ) => (
  36. <StyledButton
  37. {...props}
  38. type="button"
  39. hasPrefix={!!prefix}
  40. disabled={disabled}
  41. priority={priority}
  42. isOpen={isOpen}
  43. ref={ref}
  44. >
  45. {prefix && <LabelText>{prefix}</LabelText>}
  46. {children}
  47. {showChevron && (
  48. <StyledChevron size="xs" direction={isOpen ? 'up' : 'down'} aria-hidden="true" />
  49. )}
  50. </StyledButton>
  51. )
  52. );
  53. const StyledChevron = styled(IconChevron)`
  54. margin-left: ${space(0.75)};
  55. flex-shrink: 0;
  56. `;
  57. const StyledButton = styled(Button)<
  58. Required<Pick<DropdownButtonProps, 'isOpen' | 'disabled' | 'priority'>> & {
  59. hasPrefix: boolean;
  60. }
  61. >`
  62. position: relative;
  63. max-width: 100%;
  64. z-index: 2;
  65. ${p => (p.isOpen || p.disabled) && 'box-shadow: none;'}
  66. ${p => p.hasPrefix && `${ButtonLabel} {font-weight: 400;}`}
  67. `;
  68. const LabelText = styled('span')`
  69. &:after {
  70. content: ':';
  71. }
  72. font-weight: 600;
  73. padding-right: ${space(0.75)};
  74. `;
  75. export default DropdownButton;