Merge pull request #15873 from backstage/search/improve-accessibility

[Search] improve accessibility
This commit is contained in:
Emma Indal
2023-02-02 10:00:32 +01:00
committed by GitHub
24 changed files with 226 additions and 209 deletions
+10
View File
@@ -0,0 +1,10 @@
---
'@backstage/plugin-techdocs': patch
'@backstage/plugin-catalog': patch
'@backstage/plugin-explore': patch
'@backstage/plugin-search-react': patch
---
`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements.
Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `<li>` elements.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Navigation items in mobile sidebar now have aria label.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search': patch
---
Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator.
+14
View File
@@ -235,6 +235,20 @@ export const YourSearchResultListItemExtension = plugin.provide(
);
```
If your list item accept props, you can extend the `SearchResultListItemExtensionProps` with your component specific props:
```tsx
export const YourSearchResultListItemExtension: (
props: SearchResultListItemExtensionProps<YourSearchResultListItemProps>,
) => JSX.Element | null = plugin.provide(
createSearchResultListItemExtension({
name: 'YourSearchResultListItem',
component: () =>
import('./components').then(m => m.YourSearchResultListItem),
}),
);
```
Additionally, you can define a predicate function that receives a result and returns whether your extension should be used to render it or not:
```tsx
@@ -23,17 +23,11 @@ import {
Grid,
makeStyles,
Paper,
useTheme,
} from '@material-ui/core';
import Typography from '@material-ui/core/Typography';
import BuildIcon from '@material-ui/icons/Build';
import LaunchIcon from '@material-ui/icons/Launch';
import {
CatalogIcon,
DocsIcon,
Link,
useContent,
} from '@backstage/core-components';
import { CatalogIcon, DocsIcon, Link } from '@backstage/core-components';
import { useApi, useRouteRef } from '@backstage/core-plugin-api';
import { CatalogSearchResultListItem } from '@internal/plugin-catalog-customized';
import {
@@ -78,9 +72,6 @@ const rootRouteRef = searchPlugin.routes.root;
export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => {
const classes = useStyles();
const navigate = useNavigate();
const { transitions } = useTheme();
const { focusContent } = useContent();
const catalogApi = useApi(catalogApiRef);
const { term, types } = useSearch();
@@ -91,19 +82,14 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => {
searchBarRef?.current?.focus();
});
const handleSearchResultClick = useCallback(() => {
toggleModal();
setTimeout(focusContent, transitions.duration.leavingScreen);
}, [toggleModal, focusContent, transitions]);
const handleSearchBarKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
if (e.key === 'Enter') {
handleSearchResultClick();
toggleModal();
navigate(searchPagePath);
}
},
[navigate, searchPagePath, handleSearchResultClick],
[navigate, searchPagePath, toggleModal],
);
return (
@@ -187,7 +173,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => {
alignItems="center"
>
<Grid item>
<Link to={searchPagePath} onClick={handleSearchResultClick}>
<Link to={searchPagePath} onClick={toggleModal}>
<Typography
component="span"
className={classes.viewResultsLink}
@@ -200,10 +186,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => {
</Grid>
</Grid>
<Grid item xs>
<SearchResult
onClick={handleSearchResultClick}
onKeyDown={handleSearchResultClick}
>
<SearchResult onClick={toggleModal}>
<CatalogSearchResultListItem icon={<CatalogIcon />} />
<TechDocsSearchResultListItem icon={<DocsIcon />} />
<ToolSearchResultListItem icon={<BuildIcon />} />
@@ -100,6 +100,7 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => {
return (
// Material UI issue: https://github.com/mui-org/material-ui/issues/27820
<BottomNavigationAction
aria-label={label}
label={label}
icon={icon}
component={Link as any}
+2 -1
View File
@@ -19,6 +19,7 @@ import { default as React_2 } from 'react';
import { ReactNode } from 'react';
import { ResultHighlight } from '@backstage/plugin-search-common';
import { RouteRef } from '@backstage/core-plugin-api';
import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react';
import { StarredEntitiesApi } from '@backstage/plugin-catalog-react';
import { StorageApi } from '@backstage/core-plugin-api';
import { StyleRules } from '@material-ui/core/styles/withStyles';
@@ -108,7 +109,7 @@ export const catalogPlugin: BackstagePlugin<
// @public (undocumented)
export const CatalogSearchResultListItem: (
props: CatalogSearchResultListItemProps,
props: SearchResultListItemExtensionProps<CatalogSearchResultListItemProps>,
) => JSX.Element | null;
// @public
@@ -18,8 +18,6 @@ import React, { ReactNode } from 'react';
import {
Box,
Chip,
Divider,
ListItem,
ListItemIcon,
ListItemText,
makeStyles,
@@ -67,48 +65,43 @@ export function CatalogSearchResultListItem(
return (
<>
<ListItem alignItems="flex-start">
{props.icon && <ListItemIcon>{props.icon}</ListItemIcon>}
<div className={classes.flexContainer}>
<ListItemText
className={classes.itemText}
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{highlight?.fields.title ? (
<HighlightedSearchResultText
text={highlight.fields.title}
preTag={highlight.preTag}
postTag={highlight.postTag}
/>
) : (
result.title
)}
</Link>
}
secondary={
highlight?.fields.text ? (
{props.icon && <ListItemIcon>{props.icon}</ListItemIcon>}
<div className={classes.flexContainer}>
<ListItemText
className={classes.itemText}
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{highlight?.fields.title ? (
<HighlightedSearchResultText
text={highlight.fields.text}
text={highlight.fields.title}
preTag={highlight.preTag}
postTag={highlight.postTag}
/>
) : (
result.text
)
}
/>
<Box>
{result.kind && (
<Chip label={`Kind: ${result.kind}`} size="small" />
)}
{result.lifecycle && (
<Chip label={`Lifecycle: ${result.lifecycle}`} size="small" />
)}
</Box>
</div>
</ListItem>
<Divider component="li" />
result.title
)}
</Link>
}
secondary={
highlight?.fields.text ? (
<HighlightedSearchResultText
text={highlight.fields.text}
preTag={highlight.preTag}
postTag={highlight.postTag}
/>
) : (
result.text
)
}
/>
<Box>
{result.kind && <Chip label={`Kind: ${result.kind}`} size="small" />}
{result.lifecycle && (
<Chip label={`Lifecycle: ${result.lifecycle}`} size="small" />
)}
</Box>
</div>
</>
);
}
+5 -2
View File
@@ -31,7 +31,10 @@ import {
fetchApiRef,
storageApiRef,
} from '@backstage/core-plugin-api';
import { createSearchResultListItemExtension } from '@backstage/plugin-search-react';
import {
createSearchResultListItemExtension,
SearchResultListItemExtensionProps,
} from '@backstage/plugin-search-react';
import { DefaultStarredEntitiesApi } from './apis';
import { AboutCardProps } from './components/AboutCard';
import { DefaultCatalogPageProps } from './components/CatalogPage';
@@ -254,7 +257,7 @@ export const RelatedEntitiesCard: <T extends Entity>(
/** @public */
export const CatalogSearchResultListItem: (
props: CatalogSearchResultListItemProps,
props: SearchResultListItemExtensionProps<CatalogSearchResultListItemProps>,
) => JSX.Element | null = catalogPlugin.provide(
createSearchResultListItemExtension({
name: 'CatalogSearchResultListItem',
+2 -1
View File
@@ -19,6 +19,7 @@ import { IndexableDocument } from '@backstage/plugin-search-common';
import { ReactNode } from 'react';
import { ResultHighlight } from '@backstage/plugin-search-common';
import { RouteRef } from '@backstage/core-plugin-api';
import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react';
import { TabProps } from '@material-ui/core';
// @public @deprecated (undocumented)
@@ -126,7 +127,7 @@ export const ToolExplorerContent: (props: {
// @public (undocumented)
export const ToolSearchResultListItem: (
props: ToolSearchResultListItemProps,
props: SearchResultListItemExtensionProps<ToolSearchResultListItemProps>,
) => JSX.Element | null;
// @public
@@ -18,8 +18,6 @@ import React, { ReactNode } from 'react';
import {
Box,
Chip,
Divider,
ListItem,
ListItemIcon,
ListItemText,
makeStyles,
@@ -64,46 +62,42 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) {
return (
<>
<ListItem alignItems="flex-start">
{props.icon && <ListItemIcon>{props.icon}</ListItemIcon>}
<div className={classes.flexContainer}>
<ListItemText
className={classes.itemText}
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{props.highlight?.fields.title ? (
<HighlightedSearchResultText
text={props.highlight.fields.title}
preTag={props.highlight.preTag}
postTag={props.highlight.postTag}
/>
) : (
result.title
)}
</Link>
}
secondary={
props.highlight?.fields.text ? (
{props.icon && <ListItemIcon>{props.icon}</ListItemIcon>}
<div className={classes.flexContainer}>
<ListItemText
className={classes.itemText}
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{props.highlight?.fields.title ? (
<HighlightedSearchResultText
text={props.highlight.fields.text}
text={props.highlight.fields.title}
preTag={props.highlight.preTag}
postTag={props.highlight.postTag}
/>
) : (
result.text
)
}
/>
<Box>
{result.tags &&
result.tags.map((tag: string) => (
<Chip label={tag} size="small" />
))}
</Box>
</div>
</ListItem>
<Divider component="li" />
result.title
)}
</Link>
}
secondary={
props.highlight?.fields.text ? (
<HighlightedSearchResultText
text={props.highlight.fields.text}
preTag={props.highlight.preTag}
postTag={props.highlight.postTag}
/>
) : (
result.text
)
}
/>
<Box>
{result.tags?.map((tag: string) => (
<Chip label={tag} size="small" />
))}
</Box>
</div>
</>
);
}
+5 -2
View File
@@ -22,7 +22,10 @@ import {
discoveryApiRef,
fetchApiRef,
} from '@backstage/core-plugin-api';
import { createSearchResultListItemExtension } from '@backstage/plugin-search-react';
import {
createSearchResultListItemExtension,
SearchResultListItemExtensionProps,
} from '@backstage/plugin-search-react';
import { ExploreClient, exploreApiRef } from './api';
import { ToolSearchResultListItemProps } from './components/ToolSearchResultListItem';
// import { exampleTools } from './util/examples';
@@ -70,7 +73,7 @@ export const explorePlugin = createPlugin({
/** @public */
export const ToolSearchResultListItem: (
props: ToolSearchResultListItemProps,
props: SearchResultListItemExtensionProps<ToolSearchResultListItemProps>,
) => JSX.Element | null = explorePlugin.provide(
createSearchResultListItemExtension({
name: 'ToolSearchResultListItem',
+12
View File
@@ -14,6 +14,7 @@ import { InputBaseProps } from '@material-ui/core';
import { JsonObject } from '@backstage/types';
import { JsonValue } from '@backstage/types';
import { LinkProps } from '@backstage/core-components';
import { ListItemProps } from '@material-ui/core';
import { ListItemTextProps } from '@material-ui/core';
import { ListProps } from '@material-ui/core';
import { PropsWithChildren } from 'react';
@@ -55,6 +56,7 @@ export type DefaultResultListItemProps = {
highlight?: ResultHighlight;
rank?: number;
lineClamp?: number;
toggleModal?: () => void;
};
// @public (undocumented)
@@ -391,6 +393,16 @@ export type SearchResultListItemExtensionOptions<
predicate?: (result: SearchResult_2) => boolean;
};
// @public
export type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &
PropsWithChildren<
{
rank?: number;
result?: SearchDocument;
noTrack?: boolean;
} & Omit<ListItemProps, 'button'>
>;
// @public
export const SearchResultListItemExtensions: (
props: SearchResultListItemExtensionsProps,
@@ -35,9 +35,10 @@ describe('DefaultResultListItem', () => {
it('Includes primary/secondary text (title / text)', async () => {
await renderInTestApp(<DefaultResultListItem result={result} />);
expect(screen.getByRole('listitem')).toHaveTextContent(
result.title + result.text,
);
expect(
screen.getByRole('link', { name: result.title }),
).toBeInTheDocument();
expect(screen.getByText(result.text)).toBeInTheDocument();
});
it('should render icon if prop is specified', async () => {
@@ -21,13 +21,7 @@ import {
SearchDocument,
} from '@backstage/plugin-search-common';
import { HighlightedSearchResultText } from '../HighlightedSearchResultText';
import {
ListItem,
ListItemIcon,
ListItemText,
Box,
Divider,
} from '@material-ui/core';
import { ListItemIcon, ListItemText, Box } from '@material-ui/core';
import Typography from '@material-ui/core/Typography';
import { Link } from '@backstage/core-components';
@@ -43,6 +37,7 @@ export type DefaultResultListItemProps = {
highlight?: ResultHighlight;
rank?: number;
lineClamp?: number;
toggleModal?: () => void;
};
/**
@@ -61,48 +56,45 @@ export const DefaultResultListItemComponent = ({
return (
<>
<ListItem alignItems="center">
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{highlight?.fields.title ? (
<HighlightedSearchResultText
text={highlight?.fields.title || ''}
preTag={highlight?.preTag || ''}
postTag={highlight?.postTag || ''}
/>
) : (
result.title
)}
</Link>
}
secondary={
<Typography
component="span"
style={{
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: lineClamp,
overflow: 'hidden',
}}
>
{highlight?.fields.text ? (
<HighlightedSearchResultText
text={highlight.fields.text}
preTag={highlight.preTag}
postTag={highlight.postTag}
/>
) : (
result.text
)}
</Typography>
}
/>
{secondaryAction && <Box alignItems="flex-end">{secondaryAction}</Box>}
</ListItem>
<Divider />
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primaryTypographyProps={{ variant: 'h6' }}
primary={
<Link noTrack to={result.location}>
{highlight?.fields.title ? (
<HighlightedSearchResultText
text={highlight?.fields.title || ''}
preTag={highlight?.preTag || ''}
postTag={highlight?.postTag || ''}
/>
) : (
result.title
)}
</Link>
}
secondary={
<Typography
component="span"
style={{
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: lineClamp,
overflow: 'hidden',
}}
>
{highlight?.fields.text ? (
<HighlightedSearchResultText
text={highlight.fields.text}
preTag={highlight.preTag}
postTag={highlight.postTag}
/>
) : (
result.text
)}
</Typography>
}
/>
{secondaryAction && <Box alignItems="flex-end">{secondaryAction}</Box>}
</>
);
};
@@ -16,8 +16,6 @@
import React from 'react';
import { waitFor } from '@testing-library/react';
import { ListItem } from '@material-ui/core';
import {
wrapInTestApp,
renderInTestApp,
@@ -217,8 +215,7 @@ describe('SearchResult', () => {
}).provide(
createSearchResultListItemExtension({
name: 'SearchResultExtension',
component: async () => props =>
<ListItem>Result: {props.result?.title}</ListItem>,
component: async () => props => <>Result: {props.result?.title}</>,
}),
);
@@ -18,7 +18,7 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ListItem, MenuItem } from '@material-ui/core';
import { MenuItem } from '@material-ui/core';
import DocsIcon from '@material-ui/icons/InsertDriveFile';
import {
@@ -143,8 +143,7 @@ describe('SearchResultGroup', () => {
}).provide(
createSearchResultListItemExtension({
name: 'SearchResultGroupItemExtension',
component: async () => props =>
<ListItem>Result: {props.result?.title}</ListItem>,
component: async () => props => <>Result: {props.result?.title}</>,
}),
);
@@ -17,7 +17,6 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { ListItem } from '@material-ui/core';
import {
TestApiProvider,
renderWithEffects,
@@ -226,8 +225,7 @@ describe('SearchResultList', () => {
}).provide(
createSearchResultListItemExtension({
name: 'SearchResultListItemExtension',
component: async () => props =>
<ListItem>Result: {props.result?.title}</ListItem>,
component: async () => props => <>Result: {props.result?.title}</>,
}),
);
+7 -9
View File
@@ -18,7 +18,7 @@ import React from 'react';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ListItem, ListItemText } from '@material-ui/core';
import { ListItemText } from '@material-ui/core';
import {
wrapInTestApp,
@@ -75,9 +75,9 @@ const createExtension = (
predicate,
component = async () => (props: { result?: SearchDocument }) =>
(
<ListItem>
<>
<ListItemText primary="Default" secondary={props.result?.title} />
</ListItem>
</>
),
} = options;
return plugin.provide(
@@ -120,7 +120,7 @@ describe('extensions', () => {
);
await userEvent.click(
screen.getByRole('button', { name: /Search Result 1/ }),
screen.getByRole('link', { name: /Search Result 1/ }),
);
expect(analyticsApiMock.getEvents()[0]).toMatchObject({
@@ -146,9 +146,7 @@ describe('extensions', () => {
expect(screen.getByText('Default')).toBeInTheDocument();
expect(screen.getByText('Search Result 1')).toBeInTheDocument();
await userEvent.click(
screen.getByRole('button', { name: /Search Result 1/ }),
);
await userEvent.click(screen.getByRole('listitem'));
expect(analyticsApiMock.getEvents()[0]).toMatchObject({
action: 'discover',
@@ -184,9 +182,9 @@ describe('extensions', () => {
predicate: (result: SearchResult) => result.type === 'explore',
component: async () => (props: { result?: SearchDocument }) =>
(
<ListItem>
<>
<ListItemText primary="Explore" secondary={props.result?.title} />
</ListItem>
</>
),
});
+29 -16
View File
@@ -33,7 +33,7 @@ import {
} from '@backstage/core-plugin-api';
import { SearchDocument, SearchResult } from '@backstage/plugin-search-common';
import { Box, List, ListProps } from '@material-ui/core';
import { ListItem, List, ListProps, ListItemProps } from '@material-ui/core';
import { DefaultResultListItem } from './components';
@@ -73,26 +73,34 @@ const findSearchResultListItemExtensionElement = (
};
/**
* @internal
* Props for {@link SearchResultListItemExtension}.
* @public
* Extends props for any search result list item extension
*/
type SearchResultListItemExtensionProps = PropsWithChildren<{
rank?: number;
result?: SearchDocument;
noTrack?: boolean;
}>;
export type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &
PropsWithChildren<
{
rank?: number;
result?: SearchDocument;
noTrack?: boolean;
} & Omit<ListItemProps, 'button'>
>;
/**
* @internal
* Extends children with extension capabilities.
* @param props - see {@link SearchResultListItemExtensionProps}.
*/
const SearchResultListItemExtension = ({
rank,
result,
noTrack,
children,
}: SearchResultListItemExtensionProps) => {
const SearchResultListItemExtension = (
props: SearchResultListItemExtensionProps,
) => {
const {
rank,
result,
noTrack,
children,
alignItems = 'flex-start',
...rest
} = props;
const analytics = useAnalytics();
const handleClickCapture = useCallback(() => {
@@ -105,9 +113,14 @@ const SearchResultListItemExtension = ({
}, [rank, result, noTrack, analytics]);
return (
<Box role="button" tabIndex={0} onClickCapture={handleClickCapture}>
<ListItem
divider
alignItems={alignItems}
onClickCapture={handleClickCapture}
{...rest}
>
{children}
</Box>
</ListItem>
);
};
@@ -22,13 +22,12 @@ import { makeStyles, Tab, Tabs } from '@material-ui/core';
const useStyles = makeStyles((theme: BackstageTheme) => ({
tabs: {
borderBottom: `1px solid ${theme.palette.textVerySubtle}`,
padding: theme.spacing(0, 4),
},
tab: {
height: '50px',
fontWeight: theme.typography.fontWeightBold,
fontSize: theme.typography.pxToRem(13),
color: theme.palette.textSubtle,
color: theme.palette.text.primary,
minWidth: '130px',
},
}));
@@ -72,6 +71,7 @@ export const SearchTypeTabs = (props: SearchTypeTabsProps) => {
return (
<Tabs
aria-label="List of search types tabs"
className={classes.tabs}
indicatorColor="primary"
value={types.length === 0 ? '' : types[0]}
@@ -81,7 +81,6 @@ export const SearchTypeTabs = (props: SearchTypeTabsProps) => {
<Tab
key={idx}
className={classes.tab}
disableRipple
label={type.name}
value={type.value}
/>
+2 -1
View File
@@ -19,6 +19,7 @@ import { default as React_2 } from 'react';
import { ReactNode } from 'react';
import { ResultHighlight } from '@backstage/plugin-search-common';
import { RouteRef } from '@backstage/core-plugin-api';
import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react';
import { TableColumn } from '@backstage/core-components';
import { TableOptions } from '@backstage/core-components';
import { TableProps } from '@backstage/core-components';
@@ -400,7 +401,7 @@ export type TechDocsSearchProps = {
// @public
export const TechDocsSearchResultListItem: (
props: TechDocsSearchResultListItemProps,
props: SearchResultListItemExtensionProps<TechDocsSearchResultListItemProps>,
) => JSX.Element | null;
// @public
+5 -2
View File
@@ -33,7 +33,10 @@ import {
fetchApiRef,
identityApiRef,
} from '@backstage/core-plugin-api';
import { createSearchResultListItemExtension } from '@backstage/plugin-search-react';
import {
createSearchResultListItemExtension,
SearchResultListItemExtensionProps,
} from '@backstage/plugin-search-react';
import { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem';
/**
@@ -162,7 +165,7 @@ export const TechDocsReaderPage = techdocsPlugin.provide(
* @public
*/
export const TechDocsSearchResultListItem: (
props: TechDocsSearchResultListItemProps,
props: SearchResultListItemExtensionProps<TechDocsSearchResultListItemProps>,
) => JSX.Element | null = techdocsPlugin.provide(
createSearchResultListItemExtension({
name: 'TechDocsSearchResultListItem',
@@ -15,13 +15,7 @@
*/
import React, { PropsWithChildren, ReactNode } from 'react';
import {
Divider,
ListItem,
ListItemIcon,
ListItemText,
makeStyles,
} from '@material-ui/core';
import { ListItemIcon, ListItemText, makeStyles } from '@material-ui/core';
import Typography from '@material-ui/core/Typography';
import { Link } from '@backstage/core-components';
import { ResultHighlight } from '@backstage/plugin-search-common';
@@ -157,11 +151,8 @@ export const TechDocsSearchResultListItem = (
const ListItemWrapper = ({ children }: PropsWithChildren<{}>) =>
asListItem ? (
<>
<ListItem alignItems="flex-start">
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<div className={classes.flexContainer}>{children}</div>
</ListItem>
<Divider component="li" />
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<div className={classes.flexContainer}>{children}</div>
</>
) : (
<>{children}</>