<SearchTypeFacet /> -> <SearchType.Accordion />

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2021-12-28 11:34:03 +01:00
parent 8b532a6c02
commit 627b98ac07
11 changed files with 71 additions and 111 deletions
+2 -2
View File
@@ -2,6 +2,6 @@
'@backstage/plugin-search': patch
---
Introduces a `<SearchTypeFacet />` component, which operates on the same part of a search query as the `<SearchType />` component, but in a more opinionated way (as a single-select control surface suitable for faceted search UIs).
Introduces a `<SearchType.Accordion />` variant, which operates on the same part of a search query as the existing `<SearchType />`, but in a more opinionated way (as a single-select control surface suitable for faceted search UIs).
Check the [search plugin storybook](https://backstage.io/storybook/?path=/story/plugins-search-searchtypefacet--default) to see how it can be used.
Check the [search plugin storybook](https://backstage.io/storybook/?path=/story/plugins-search-searchtype--accordion) to see how it can be used.
@@ -29,7 +29,7 @@ import {
SearchFilter,
SearchResult,
SearchResultPager,
SearchTypeFacet,
SearchType,
} from '@backstage/plugin-search';
import { DocsResultListItem } from '@backstage/plugin-techdocs';
import { Grid, List, makeStyles, Paper, Theme } from '@material-ui/core';
@@ -63,7 +63,7 @@ const SearchPage = () => {
</Paper>
</Grid>
<Grid item xs={3}>
<SearchTypeFacet
<SearchType.Accordion
name="Result Type"
defaultValue="software-catalog"
types={[
+13 -11
View File
@@ -213,22 +213,16 @@ export const SearchResult: ({
// @public (undocumented)
export const SearchResultPager: () => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "SearchTypeProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SearchType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SearchType: ({
values,
className,
name,
defaultValue,
}: SearchTypeProps) => JSX.Element;
// @public
export const SearchTypeFacet: (props: SearchTypeFacetProps) => JSX.Element;
export const SearchType: {
(props: SearchTypeProps): JSX.Element;
Accordion(props: SearchTypeAccordionProps): JSX.Element;
};
// @public (undocumented)
export type SearchTypeFacetProps = {
export type SearchTypeAccordionProps = {
name: string;
types: Array<{
value: string;
@@ -238,6 +232,14 @@ export type SearchTypeFacetProps = {
defaultValue?: string;
};
// @public (undocumented)
export type SearchTypeProps = {
className?: string;
name: string;
values?: string[];
defaultValue?: string[] | string | null;
};
// Warning: (ae-missing-release-tag) "SidebarSearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -14,13 +14,7 @@
* limitations under the License.
*/
import React, {
ChangeEvent,
cloneElement,
Fragment,
useEffect,
useState,
} from 'react';
import React, { cloneElement, Fragment, useEffect, useState } from 'react';
import { useSearch } from '../SearchContext';
import {
Accordion,
@@ -79,8 +73,7 @@ const useStyles = makeStyles(theme => ({
/**
* @public
*/
export type SearchTypeFacetProps = {
/* what about this? */
export type SearchTypeAccordionProps = {
name: string;
types: Array<{
value: string;
@@ -90,23 +83,17 @@ export type SearchTypeFacetProps = {
defaultValue?: string;
};
/**
* A control surface for the search query's "types" property, displayed as a
* single-select collapsible accordion suitable for use in faceted search UIs.
* @public
*/
export const SearchTypeFacet = (props: SearchTypeFacetProps) => {
export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => {
const classes = useStyles();
const { setPageCursor, setTypes, types } = useSearch();
const [expanded, setExpanded] = useState(true);
const { defaultValue, name, types: givenTypes } = props;
const handleChange = (_event: ChangeEvent<{}>, newExpanded: boolean) =>
setExpanded(newExpanded);
const toggleExpanded = () => setExpanded(prevState => !prevState);
const handleClick = (type: string) => {
return () => {
setTypes(type !== '' ? [type] : []);
setPageCursor('0');
setPageCursor('');
setExpanded(false);
};
};
@@ -136,7 +123,7 @@ export const SearchTypeFacet = (props: SearchTypeFacetProps) => {
<Accordion
className={classes.accordion}
expanded={expanded}
onChange={handleChange}
onChange={toggleExpanded}
>
<AccordionSummary
classes={{
@@ -162,7 +149,10 @@ export const SearchTypeFacet = (props: SearchTypeFacetProps) => {
<Fragment key={type.value}>
<Divider />
<ListItem
selected={types.includes(type.value)}
selected={
types[0] === type.value ||
(types.length === 0 && type.value === '')
}
onClick={handleClick(type.value)}
button
>
@@ -14,6 +14,9 @@
* limitations under the License.
*/
import React, { useState } from 'react';
import CatalogIcon from '@material-ui/icons/MenuBook';
import DocsIcon from '@material-ui/icons/Description';
import UsersGroupsIcon from '@material-ui/icons/Person';
import { SearchType } from '../index';
import { SearchContext } from '../SearchContext';
@@ -34,3 +37,22 @@ export const Default = () => {
</SearchContext.Provider>
);
};
export const Accordion = () => {
const [types, setTypes] = useState<string[]>([]);
const setPageCursor = () => {};
return (
<SearchContext.Provider value={{ types, setTypes, setPageCursor } as any}>
<SearchType.Accordion
name="Result Types"
defaultValue="value-1"
types={[
{ value: 'value-1', name: 'Value One', icon: <CatalogIcon /> },
{ value: 'value-2', name: 'Value Two', icon: <DocsIcon /> },
{ value: 'value-3', name: 'Value Three', icon: <UsersGroupsIcon /> },
]}
/>
</SearchContext.Provider>
);
};
@@ -25,6 +25,10 @@ import {
} from '@material-ui/core';
import React, { ChangeEvent } from 'react';
import { useEffectOnce } from 'react-use';
import {
SearchTypeAccordion,
SearchTypeAccordionProps,
} from './SearchType.Accordion';
import { useSearch } from '../SearchContext';
const useStyles = makeStyles(theme => ({
@@ -41,6 +45,9 @@ const useStyles = makeStyles(theme => ({
},
}));
/**
* @public
*/
export type SearchTypeProps = {
className?: string;
name: string;
@@ -48,12 +55,8 @@ export type SearchTypeProps = {
defaultValue?: string[] | string | null;
};
const SearchType = ({
values = [],
className,
name,
defaultValue,
}: SearchTypeProps) => {
const SearchType = (props: SearchTypeProps) => {
const { className, defaultValue, name, values = [] } = props;
const classes = useStyles();
const { types, setTypes } = useSearch();
@@ -112,4 +115,14 @@ const SearchType = ({
);
};
/**
* A control surface for the search query's "types" property, displayed as a
* single-select collapsible accordion suitable for use in faceted search UIs.
* @public
*/
SearchType.Accordion = (props: SearchTypeAccordionProps) => {
return <SearchTypeAccordion {...props} />;
};
export { SearchType };
export type { SearchTypeAccordionProps };
@@ -15,3 +15,4 @@
*/
export { SearchType } from './SearchType';
export type { SearchTypeAccordionProps, SearchTypeProps } from './SearchType';
@@ -1,49 +0,0 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react';
import CatalogIcon from '@material-ui/icons/MenuBook';
import DocsIcon from '@material-ui/icons/Description';
import { SearchTypeFacet } from '../index';
import { SearchContext } from '../SearchContext';
export default {
title: 'Plugins/Search/SearchTypeFacet',
component: SearchTypeFacet,
};
export const Default = () => {
const [types, setTypes] = useState<string[]>([]);
return (
<SearchContext.Provider
value={{ types, setTypes, setPageCursor: () => {} } as any}
>
<SearchTypeFacet
name="Result Type"
defaultValue="software-catalog"
types={[
{
value: 'software-catalog',
name: 'Software Catalog',
icon: <CatalogIcon />,
},
{ value: 'techdocs', name: 'Documentation', icon: <DocsIcon /> },
]}
/>
</SearchContext.Provider>
);
};
@@ -1,18 +0,0 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { SearchTypeFacet } from './SearchTypeFacet';
export type { SearchTypeFacetProps } from './SearchTypeFacet';
-1
View File
@@ -24,7 +24,6 @@ export * from './SearchPage';
export * from './SearchResult';
export * from './SearchResultPager';
export * from './SearchType';
export * from './SearchTypeFacet';
export * from './SidebarSearch';
export * from './SidebarSearchModal';
export * from './HomePageComponent';
+2 -2
View File
@@ -34,7 +34,6 @@ export {
SearchPage as Router,
SearchResultPager,
SearchType,
SearchTypeFacet,
SidebarSearch,
useSearch,
} from './components';
@@ -46,7 +45,8 @@ export type {
FiltersState,
SearchBarProps,
SearchBarBaseProps,
SearchTypeFacetProps,
SearchTypeAccordionProps,
SearchTypeProps,
} from './components';
export {
DefaultResultListItem,