components.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import * as React from 'react';
  2. import styled from '@emotion/styled';
  3. import Button from 'sentry/components/button';
  4. import {IconClose} from 'sentry/icons/iconClose';
  5. import {t} from 'sentry/locale';
  6. import space from 'sentry/styles/space';
  7. const ModalHeader = styled('header')`
  8. position: relative;
  9. border-bottom: 1px solid ${p => p.theme.border};
  10. padding: ${space(3)} ${space(4)};
  11. margin: -${space(4)} -${space(4)} ${space(3)} -${space(4)};
  12. h1,
  13. h2,
  14. h3,
  15. h4,
  16. h5,
  17. h6 {
  18. font-size: 20px;
  19. font-weight: 600;
  20. margin-bottom: 0;
  21. line-height: 1.1;
  22. }
  23. `;
  24. const CloseButton = styled(
  25. (p: Omit<React.ComponentProps<typeof Button>, 'aria-label'>) => (
  26. <Button
  27. size="zero"
  28. icon={<IconClose size="10px" />}
  29. aria-label={t('Close Modal')}
  30. {...p}
  31. />
  32. )
  33. )`
  34. position: absolute;
  35. top: 0;
  36. right: 0;
  37. transform: translate(50%, -50%);
  38. border-radius: 50%;
  39. border: none;
  40. box-shadow: 0 0 0 1px ${p => p.theme.translucentBorder};
  41. background: ${p => p.theme.background};
  42. height: 24px;
  43. width: 24px;
  44. `;
  45. const ModalBody = styled('section')`
  46. font-size: ${p => p.theme.fontSizeMedium};
  47. p:last-child {
  48. margin-bottom: 0;
  49. }
  50. img {
  51. max-width: 100%;
  52. }
  53. `;
  54. const ModalFooter = styled('footer')`
  55. border-top: 1px solid ${p => p.theme.border};
  56. display: flex;
  57. justify-content: flex-end;
  58. padding: ${space(3)} ${space(4)};
  59. margin: ${space(3)} -${space(4)} -${space(4)};
  60. `;
  61. type HeaderProps = {
  62. /**
  63. * Show a close button in the header
  64. */
  65. closeButton?: boolean;
  66. };
  67. /**
  68. * Creates a ModalHeader that includes props to enable the close button
  69. */
  70. const makeClosableHeader = (closeModal: () => void) => {
  71. const ClosableHeader: React.FC<React.ComponentProps<typeof ModalHeader> & HeaderProps> =
  72. ({closeButton, children, ...props}) => (
  73. <ModalHeader {...props}>
  74. {children}
  75. {closeButton && <CloseButton onClick={closeModal} />}
  76. </ModalHeader>
  77. );
  78. ClosableHeader.displayName = 'Header';
  79. return ClosableHeader;
  80. };
  81. /**
  82. * Creates a CloseButton component that is connected to the provided closeModal trigger
  83. */
  84. const makeCloseButton =
  85. (closeModal: () => void): React.FC<React.ComponentProps<typeof CloseButton>> =>
  86. props =>
  87. <CloseButton {...props} onClick={closeModal} />;
  88. export {makeClosableHeader, makeCloseButton, ModalBody, ModalFooter};