searchBarAction.tsx 2.3 KB

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