savedSearchTab.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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 isActive={isActive} className="saved-search-tab">
  56. <StyledDropdownLink
  57. alwaysRenderMenu={false}
  58. anchorMiddle
  59. caret
  60. title={title}
  61. isActive={isActive}
  62. >
  63. <SavedSearchMenu
  64. organization={organization}
  65. savedSearchList={savedSearchList}
  66. onSavedSearchSelect={onSavedSearchSelect}
  67. onSavedSearchDelete={onSavedSearchDelete}
  68. query={query}
  69. sort={sort}
  70. />
  71. </StyledDropdownLink>
  72. </TabWrapper>
  73. );
  74. }
  75. export default SavedSearchTab;
  76. const TabWrapper = styled('li')<{isActive?: boolean}>`
  77. /* Color matches nav-tabs - overwritten using dark mode class saved-search-tab */
  78. border-bottom: ${p => (p.isActive ? `4px solid #6c5fc7` : 0)};
  79. /* Reposition menu under caret */
  80. & > span {
  81. display: block;
  82. }
  83. & > span > .dropdown-menu {
  84. padding: 0;
  85. margin-top: ${space(1)};
  86. min-width: 20vw;
  87. max-width: 25vw;
  88. z-index: ${p => p.theme.zIndex.globalSelectionHeader};
  89. :after {
  90. border-bottom-color: ${p => p.theme.backgroundSecondary};
  91. }
  92. }
  93. @media (max-width: ${p => p.theme.breakpoints[4]}) {
  94. & > span > .dropdown-menu {
  95. max-width: 30vw;
  96. }
  97. }
  98. @media (max-width: ${p => p.theme.breakpoints[1]}) {
  99. & > span > .dropdown-menu {
  100. max-width: 50vw;
  101. }
  102. }
  103. `;
  104. const TitleWrapper = styled('span')`
  105. margin-right: ${space(0.5)};
  106. user-select: none;
  107. display: flex;
  108. align-items: center;
  109. `;
  110. const TitleTextOverflow = styled('span')`
  111. margin-right: ${space(0.5)};
  112. max-width: 150px;
  113. ${overflowEllipsis};
  114. `;
  115. const StyledDropdownLink = styled(DropdownLink)<{isActive?: boolean}>`
  116. position: relative;
  117. display: block;
  118. padding: ${space(1)} 0;
  119. /* Important to override a media query from .nav-tabs */
  120. font-size: ${p => p.theme.fontSizeLarge} !important;
  121. text-align: center;
  122. text-transform: capitalize;
  123. /* TODO(scttcper): Replace hex color when nav-tabs is replaced */
  124. color: ${p => (p.isActive ? p.theme.textColor : '#7c6a8e')};
  125. :hover {
  126. color: #2f2936;
  127. }
  128. `;