searchBarAction.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import styled from '@emotion/styled';
  2. import type {SelectOption, SelectOptionOrSection} from 'sentry/components/compactSelect';
  3. import {CompactSelect} from 'sentry/components/compactSelect';
  4. import DropdownButton from 'sentry/components/dropdownButton';
  5. import SearchBar from 'sentry/components/searchBar';
  6. import {t, tn} from 'sentry/locale';
  7. type Props = {
  8. onChange: (value: string) => void;
  9. placeholder: string;
  10. query: string;
  11. className?: string;
  12. filterOptions?: SelectOptionOrSection<string>[];
  13. filterSelections?: SelectOption<string>[];
  14. onFilterChange?: (options: SelectOption<string>[]) => void;
  15. };
  16. function SearchBarAction({
  17. onChange,
  18. query,
  19. placeholder,
  20. filterOptions,
  21. filterSelections,
  22. onFilterChange,
  23. className,
  24. }: Props) {
  25. const trigger: React.ComponentProps<typeof CompactSelect>['trigger'] = (
  26. props,
  27. isOpen
  28. ) => (
  29. <StyledTrigger
  30. isOpen={isOpen}
  31. size="sm"
  32. priority={filterSelections && filterSelections.length > 0 ? 'primary' : 'default'}
  33. {...props}
  34. >
  35. {filterSelections?.length
  36. ? tn('%s Active Filter', '%s Active Filters', filterSelections.length)
  37. : t('Filter By')}
  38. </StyledTrigger>
  39. );
  40. return (
  41. <Wrapper className={className}>
  42. {filterOptions && (
  43. <CompactSelect
  44. size="sm"
  45. multiple
  46. maxMenuHeight={400}
  47. options={filterOptions}
  48. value={filterSelections?.map(f => f.value)}
  49. onChange={onFilterChange}
  50. trigger={trigger}
  51. />
  52. )}
  53. <StyledSearchBar
  54. size="sm"
  55. onChange={onChange}
  56. query={query}
  57. placeholder={placeholder}
  58. blendWithFilter={!!filterOptions}
  59. />
  60. </Wrapper>
  61. );
  62. }
  63. export default SearchBarAction;
  64. const Wrapper = styled('div')`
  65. display: flex;
  66. width: 100%;
  67. justify-content: flex-end;
  68. @media (min-width: ${p => p.theme.breakpoints.medium}) {
  69. width: 350px;
  70. }
  71. @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
  72. width: 500px;
  73. }
  74. `;
  75. const StyledSearchBar = styled(SearchBar)<{blendWithFilter?: boolean}>`
  76. width: 100%;
  77. ${p =>
  78. p.blendWithFilter &&
  79. `
  80. input {
  81. border-radius: ${p.theme.borderRadiusRight};
  82. border-left-width: 0;
  83. }
  84. `}
  85. `;
  86. const StyledTrigger = styled(DropdownButton)`
  87. border-radius: ${p => p.theme.borderRadiusLeft};
  88. `;