diff --git a/.changeset/search-lucky-roses-wash.md b/.changeset/search-lucky-roses-wash.md new file mode 100644 index 0000000000..f2445ddc8d --- /dev/null +++ b/.changeset/search-lucky-roses-wash.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-search': patch +--- + +Change `` design to follow Figma and be similar to existing multi +selects in Backstage. diff --git a/plugins/search/src/components/SearchType/SearchType.test.tsx b/plugins/search/src/components/SearchType/SearchType.test.tsx index 1ca032e41d..b8bf59d13e 100644 --- a/plugins/search/src/components/SearchType/SearchType.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.test.tsx @@ -14,13 +14,12 @@ * limitations under the License. */ -import React from 'react'; -import { screen, render, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { SearchType } from './SearchType'; - -import { SearchContextProvider } from '../SearchContext'; import { useApi } from '@backstage/core-plugin-api'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { SearchContextProvider } from '../SearchContext'; +import { SearchType } from './SearchType'; jest.mock('@backstage/core-plugin-api', () => ({ ...jest.requireActual('@backstage/core-plugin-api'), @@ -101,9 +100,6 @@ describe('SearchType', () => { expect( screen.getByRole('option', { name: values[1] }), ).not.toHaveAttribute('aria-selected'); - expect(screen.getByRole('option', { name: 'All' })).not.toHaveAttribute( - 'aria-selected', - ); }); it('Renders correctly based on type filter defaultValue', async () => { @@ -130,9 +126,6 @@ describe('SearchType', () => { expect( screen.getByRole('option', { name: values[1] }), ).not.toHaveAttribute('aria-selected'); - expect(screen.getByRole('option', { name: 'All' })).not.toHaveAttribute( - 'aria-selected', - ); }); it('Selecting a value sets type filter state', async () => { @@ -169,19 +162,9 @@ describe('SearchType', () => { await waitFor(() => { expect(screen.getByRole('listbox')).toBeInTheDocument(); }); - - userEvent.click(screen.getByRole('option', { name: 'All' })); - - await waitFor(() => { - expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ - types: [], - }), - ); - }); }); - it('Selecting a value maintains unrelated filter state, selecting All defaults to default empty state', async () => { + it('Selecting none defaults to empty state', async () => { render( { expect(screen.getByRole('listbox')).toBeInTheDocument(); }); - userEvent.click(screen.getByRole('option', { name: 'All' })); + userEvent.click(screen.getByRole('option', { name: values[0] })); await waitFor(() => { expect(query).toHaveBeenLastCalledWith(expect.objectContaining([])); diff --git a/plugins/search/src/components/SearchType/SearchType.tsx b/plugins/search/src/components/SearchType/SearchType.tsx index 6e57879064..5290caa0b7 100644 --- a/plugins/search/src/components/SearchType/SearchType.tsx +++ b/plugins/search/src/components/SearchType/SearchType.tsx @@ -13,30 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { useSearch } from '../SearchContext'; -import { useEffectOnce } from 'react-use'; -import React, { ChangeEvent } from 'react'; import { + Checkbox, Chip, FormControl, InputLabel, + ListItemText, makeStyles, MenuItem, Select, } from '@material-ui/core'; +import React, { ChangeEvent } from 'react'; +import { useEffectOnce } from 'react-use'; +import { useSearch } from '../SearchContext'; -const useStyles = makeStyles({ +const useStyles = makeStyles(theme => ({ label: { textTransform: 'capitalize', }, chips: { display: 'flex', flexWrap: 'wrap', + marginTop: theme.spacing(1), }, chip: { margin: 2, }, -}); +})); export type SearchTypeProps = { className?: string; @@ -55,20 +58,18 @@ const SearchType = ({ const { types, setTypes } = useSearch(); useEffectOnce(() => { - if (defaultValue && Array.isArray(defaultValue)) { - setTypes(defaultValue); - } else if (defaultValue) { - setTypes([defaultValue]); + if (!types.length) { + if (defaultValue && Array.isArray(defaultValue)) { + setTypes(defaultValue); + } else if (defaultValue) { + setTypes([defaultValue]); + } } }); const handleChange = (e: ChangeEvent<{ value: unknown }>) => { const value = e.target.value as string[]; - if (!value || value.includes('*')) { - setTypes([]); - } else { - setTypes(value.filter(it => it !== 'All')); - } + setTypes(value as string[]); }; return ( @@ -84,22 +85,26 @@ const SearchType = ({