settingsNavItem.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {Fragment, ReactElement} from 'react';
  2. import {Link as RouterLink} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import Badge from 'sentry/components/badge';
  5. import FeatureBadge from 'sentry/components/featureBadge';
  6. import HookOrDefault from 'sentry/components/hookOrDefault';
  7. import {Tooltip} from 'sentry/components/tooltip';
  8. import {t} from 'sentry/locale';
  9. import {space} from 'sentry/styles/space';
  10. type Props = {
  11. label: React.ReactNode;
  12. to: React.ComponentProps<RouterLink>['to'];
  13. badge?: string | number | null | ReactElement;
  14. id?: string;
  15. index?: boolean;
  16. onClick?: (e: React.MouseEvent) => void;
  17. };
  18. const SettingsNavItem = ({badge, label, index, id, ...props}: Props) => {
  19. const LabelHook = HookOrDefault({
  20. hookName: 'sidebar:item-label',
  21. defaultComponent: ({children}) => <Fragment>{children}</Fragment>,
  22. });
  23. let renderedBadge: React.ReactNode;
  24. if (badge === 'new') {
  25. renderedBadge = <FeatureBadge type="new" />;
  26. } else if (badge === 'beta') {
  27. renderedBadge = <FeatureBadge type="beta" />;
  28. } else if (badge === 'warning') {
  29. renderedBadge = (
  30. <Tooltip title={t('This setting needs review')} position="right">
  31. <StyledBadge text={badge} type="warning" />
  32. </Tooltip>
  33. );
  34. } else if (typeof badge === 'string' || typeof badge === 'number') {
  35. renderedBadge = <StyledBadge text={badge} />;
  36. } else {
  37. renderedBadge = badge;
  38. }
  39. return (
  40. <StyledNavItem onlyActiveOnIndex={index} activeClassName="active" {...props}>
  41. <LabelHook id={id}>{label}</LabelHook>
  42. {badge ? renderedBadge : null}
  43. </StyledNavItem>
  44. );
  45. };
  46. const StyledNavItem = styled(RouterLink)`
  47. display: block;
  48. color: ${p => p.theme.gray300};
  49. font-size: 14px;
  50. line-height: 30px;
  51. position: relative;
  52. &.active {
  53. color: ${p => p.theme.textColor};
  54. &:before {
  55. background: ${p => p.theme.active};
  56. }
  57. }
  58. &:hover,
  59. &:focus,
  60. &:active {
  61. color: ${p => p.theme.textColor};
  62. outline: none;
  63. }
  64. &.focus-visible {
  65. outline: none;
  66. background: ${p => p.theme.backgroundSecondary};
  67. padding-left: 15px;
  68. margin-left: -15px;
  69. border-radius: 3px;
  70. &:before {
  71. left: -15px;
  72. }
  73. }
  74. &:before {
  75. position: absolute;
  76. content: '';
  77. display: block;
  78. top: 4px;
  79. left: -30px;
  80. height: 20px;
  81. width: 4px;
  82. background: transparent;
  83. border-radius: 0 2px 2px 0;
  84. }
  85. `;
  86. const StyledBadge = styled(Badge)`
  87. font-weight: 400;
  88. height: auto;
  89. line-height: 1;
  90. font-size: ${p => p.theme.fontSizeExtraSmall};
  91. padding: 3px ${space(0.75)};
  92. vertical-align: middle;
  93. `;
  94. export default SettingsNavItem;