savedSearchTab.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import Badge from 'sentry/components/badge';
  4. import DropdownLink from 'sentry/components/dropdownLink';
  5. import QueryCount from 'sentry/components/queryCount';
  6. import {t} from 'sentry/locale';
  7. import overflowEllipsis from 'sentry/styles/overflowEllipsis';
  8. import space from 'sentry/styles/space';
  9. import {Organization, SavedSearch} from 'sentry/types';
  10. import SavedSearchMenu from './savedSearchMenu';
  11. type Props = {
  12. onSavedSearchDelete: (savedSearch: SavedSearch) => void;
  13. onSavedSearchSelect: (savedSearch: SavedSearch) => void;
  14. organization: Organization;
  15. savedSearchList: SavedSearch[];
  16. sort: string;
  17. isActive?: boolean;
  18. query?: string;
  19. queryCount?: number;
  20. };
  21. function SavedSearchTab({
  22. isActive,
  23. organization,
  24. savedSearchList,
  25. onSavedSearchSelect,
  26. onSavedSearchDelete,
  27. query,
  28. queryCount,
  29. sort,
  30. }: Props) {
  31. const savedSearch = savedSearchList.find(
  32. search => search.query === query && search.sort === sort
  33. );
  34. const title = (
  35. <TitleWrapper>
  36. {isActive ? (
  37. <Fragment>
  38. <TitleTextOverflow>
  39. {savedSearch ? savedSearch.name : t('Custom Search')}{' '}
  40. </TitleTextOverflow>
  41. {queryCount !== undefined && queryCount > 0 && (
  42. <div>
  43. <Badge>
  44. <QueryCount hideParens count={queryCount} max={1000} />
  45. </Badge>
  46. </div>
  47. )}
  48. </Fragment>
  49. ) : (
  50. t('Saved Searches')
  51. )}
  52. </TitleWrapper>
  53. );
  54. return (
  55. <TabWrapper
  56. isActive={isActive}
  57. className="saved-search-tab"
  58. data-test-id="saved-search-tab"
  59. >
  60. <StyledDropdownLink
  61. alwaysRenderMenu={false}
  62. anchorMiddle
  63. caret
  64. title={title}
  65. isActive={isActive}
  66. >
  67. <SavedSearchMenu
  68. organization={organization}
  69. savedSearchList={savedSearchList}
  70. onSavedSearchSelect={onSavedSearchSelect}
  71. onSavedSearchDelete={onSavedSearchDelete}
  72. query={query}
  73. sort={sort}
  74. />
  75. </StyledDropdownLink>
  76. </TabWrapper>
  77. );
  78. }
  79. export default SavedSearchTab;
  80. const TabWrapper = styled('li')<{isActive?: boolean}>`
  81. /* Color matches nav-tabs - overwritten using dark mode class saved-search-tab */
  82. border-bottom: ${p => (p.isActive ? `4px solid #6c5fc7` : 0)};
  83. /* Reposition menu under caret */
  84. & > span {
  85. display: block;
  86. }
  87. & > span > .dropdown-menu {
  88. padding: 0;
  89. margin-top: ${space(1)};
  90. min-width: 20vw;
  91. max-width: 25vw;
  92. z-index: ${p => p.theme.zIndex.globalSelectionHeader};
  93. :after {
  94. border-bottom-color: ${p => p.theme.backgroundSecondary};
  95. }
  96. }
  97. @media (max-width: ${p => p.theme.breakpoints[4]}) {
  98. & > span > .dropdown-menu {
  99. max-width: 30vw;
  100. }
  101. }
  102. @media (max-width: ${p => p.theme.breakpoints[1]}) {
  103. & > span > .dropdown-menu {
  104. max-width: 50vw;
  105. }
  106. }
  107. `;
  108. const TitleWrapper = styled('span')`
  109. margin-right: ${space(0.5)};
  110. user-select: none;
  111. display: flex;
  112. align-items: center;
  113. `;
  114. const TitleTextOverflow = styled('span')`
  115. margin-right: ${space(0.5)};
  116. max-width: 150px;
  117. ${overflowEllipsis};
  118. `;
  119. const StyledDropdownLink = styled(DropdownLink)<{isActive?: boolean}>`
  120. position: relative;
  121. display: block;
  122. padding: ${space(1)} 0;
  123. /* Important to override a media query from .nav-tabs */
  124. font-size: ${p => p.theme.fontSizeLarge} !important;
  125. text-align: center;
  126. text-transform: capitalize;
  127. /* TODO(scttcper): Replace hex color when nav-tabs is replaced */
  128. color: ${p => (p.isActive ? p.theme.textColor : '#7c6a8e')};
  129. :hover {
  130. color: #2f2936;
  131. }
  132. `;