settingsPageHeader.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React from 'react';
  2. import styled from '@emotion/styled';
  3. import {HeaderTitle} from 'app/styles/organization';
  4. import space from 'app/styles/space';
  5. type Props = {
  6. // Icon left of title
  7. icon?: React.ReactNode;
  8. // The title
  9. title: React.ReactNode;
  10. subtitle?: React.ReactNode;
  11. // Disables font styles in the title. Allows for more custom titles.
  12. noTitleStyles?: boolean;
  13. className?: string;
  14. // CTA button
  15. action?: React.ReactNode;
  16. body?: React.ReactNode;
  17. tabs?: React.ReactNode;
  18. };
  19. class UnstyledSettingsPageHeader extends React.Component<Props> {
  20. static defaultProps = {
  21. noTitleStyles: false,
  22. };
  23. render() {
  24. const {
  25. icon,
  26. title,
  27. subtitle,
  28. action,
  29. tabs,
  30. noTitleStyles,
  31. body,
  32. ...props
  33. } = this.props;
  34. // If Header is narrow, use align-items to center <Action>.
  35. // Otherwise, use a fixed margin to prevent an odd alignment.
  36. // This is needed as Actions could be a button or a dropdown.
  37. const isNarrow = !subtitle;
  38. return (
  39. <div {...props}>
  40. <TitleAndActions isNarrow={isNarrow}>
  41. <TitleWrapper>
  42. {icon && <Icon>{icon}</Icon>}
  43. {title && (
  44. <Title tabs={tabs} styled={noTitleStyles}>
  45. <HeaderTitle>{title}</HeaderTitle>
  46. {subtitle && <Subtitle>{subtitle}</Subtitle>}
  47. </Title>
  48. )}
  49. </TitleWrapper>
  50. {action && <Action isNarrow={isNarrow}>{action}</Action>}
  51. </TitleAndActions>
  52. {body && <BodyWrapper>{body}</BodyWrapper>}
  53. {tabs && <TabsWrapper>{tabs}</TabsWrapper>}
  54. </div>
  55. );
  56. }
  57. }
  58. type TitleProps = {
  59. styled?: boolean;
  60. tabs?: React.ReactNode;
  61. };
  62. const TitleAndActions = styled('div')<{isNarrow?: boolean}>`
  63. display: flex;
  64. align-items: ${p => (p.isNarrow ? 'center' : 'flex-start')};
  65. `;
  66. const TitleWrapper = styled('div')`
  67. flex: 1;
  68. `;
  69. const Title = styled('div')<TitleProps & React.HTMLProps<HTMLDivElement>>`
  70. ${p => !p.styled && `font-size: 20px; font-weight: 600;`};
  71. margin: ${space(4)} ${space(2)} ${space(3)} 0;
  72. `;
  73. const Subtitle = styled('div')`
  74. color: ${p => p.theme.gray400};
  75. font-weight: 400;
  76. font-size: ${p => p.theme.fontSizeLarge};
  77. padding: ${space(1.5)} 0 0;
  78. `;
  79. const Icon = styled('div')`
  80. margin-right: ${space(1)};
  81. `;
  82. const Action = styled('div')<{isNarrow?: boolean}>`
  83. margin-top: ${p => (p.isNarrow ? '0' : space(4))};
  84. `;
  85. const SettingsPageHeader = styled(UnstyledSettingsPageHeader)<
  86. Omit<React.HTMLProps<HTMLDivElement>, keyof Props> & Props
  87. >`
  88. font-size: 14px;
  89. margin-top: -${space(4)};
  90. `;
  91. const BodyWrapper = styled('div')`
  92. flex: 1;
  93. margin: 0 0 ${space(3)};
  94. `;
  95. const TabsWrapper = styled('div')`
  96. flex: 1;
  97. margin: 0; /* sentry/components/navTabs has added margin */
  98. `;
  99. export default SettingsPageHeader;