From 2ea4a859cfb815fa0e9633e35cc557985bc61d35 Mon Sep 17 00:00:00 2001 From: anle9650 Date: Fri, 1 Mar 2024 20:33:22 -0700 Subject: [PATCH 1/8] Update SearchIcons.js --- docs/data/material/components/material-icons/SearchIcons.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index fc2d1f34e158a5..cd26b2b4ac3e21 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -480,6 +480,7 @@ function useLatest(value) { export default function SearchIcons() { const [keys, setKeys] = React.useState(null); + const [, startTransition] = React.useTransition(); const [theme, setTheme] = useQueryParameterState('theme', 'Filled'); const [selectedIcon, setSelectedIcon] = useQueryParameterState('selected', ''); const [query, setQuery] = useQueryParameterState('query', ''); @@ -573,7 +574,7 @@ export default function SearchIcons() { setQuery(event.target.value)} + onChange={(event) => startTransition(() => setQuery(event.target.value))} placeholder="Search icons…" inputProps={{ 'aria-label': 'search icons' }} /> From ca833fe497e915ca6b6450be4fd2d820cc806d52 Mon Sep 17 00:00:00 2001 From: anle9650 Date: Wed, 6 Mar 2024 20:39:13 -0700 Subject: [PATCH 2/8] Revert "Update SearchIcons.js" This reverts commit 2ea4a859cfb815fa0e9633e35cc557985bc61d35. --- docs/data/material/components/material-icons/SearchIcons.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index cd26b2b4ac3e21..fc2d1f34e158a5 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -480,7 +480,6 @@ function useLatest(value) { export default function SearchIcons() { const [keys, setKeys] = React.useState(null); - const [, startTransition] = React.useTransition(); const [theme, setTheme] = useQueryParameterState('theme', 'Filled'); const [selectedIcon, setSelectedIcon] = useQueryParameterState('selected', ''); const [query, setQuery] = useQueryParameterState('query', ''); @@ -574,7 +573,7 @@ export default function SearchIcons() { startTransition(() => setQuery(event.target.value))} + onChange={(event) => setQuery(event.target.value)} placeholder="Search icons…" inputProps={{ 'aria-label': 'search icons' }} /> From 99f856625cbf3bb18fcc34a54d02cc61152faedd Mon Sep 17 00:00:00 2001 From: anle9650 Date: Wed, 6 Mar 2024 20:45:59 -0700 Subject: [PATCH 3/8] Update useQueryParameterState.ts --- docs/src/modules/utils/useQueryParameterState.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/modules/utils/useQueryParameterState.ts b/docs/src/modules/utils/useQueryParameterState.ts index 4af5e339ce418e..159a5b6fe45898 100644 --- a/docs/src/modules/utils/useQueryParameterState.ts +++ b/docs/src/modules/utils/useQueryParameterState.ts @@ -61,10 +61,11 @@ export default function useQueryParameterState( [setUrlValue], ); + const [, startTransition] = React.useTransition(); const setUserState = React.useCallback( (newValue: string) => { - setUrlValue(newValue); setState(newValue); + startTransition(() => setUrlValue(newValue)); }, [setUrlValue], ); From e2e608bea9419d1d732bb3d235827ec9f4aeb9a6 Mon Sep 17 00:00:00 2001 From: MUI bot <2109932+Janpot@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:38:31 +0100 Subject: [PATCH 4/8] Update --- .../components/material-icons/SearchIcons.js | 88 ++++++++----------- .../modules/utils/useQueryParameterState.ts | 3 +- 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index fc2d1f34e158a5..ab37121e506c63 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -5,16 +5,17 @@ import copy from 'clipboard-copy'; import InputBase from '@mui/material/InputBase'; import Typography from '@mui/material/Typography'; import PropTypes from 'prop-types'; -import { debounce } from '@mui/material/utils'; import Grid from '@mui/material/Grid'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogTitle from '@mui/material/DialogTitle'; +import CircularProgress from '@mui/material/CircularProgress'; +import InputAdornment from '@mui/material/InputAdornment'; import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; import Button from '@mui/material/Button'; -import * as flexsearch from 'flexsearch'; +import flexsearch from 'flexsearch'; import SearchIcon from '@mui/icons-material/Search'; import FormControlLabel from '@mui/material/FormControlLabel'; import RadioGroup from '@mui/material/RadioGroup'; @@ -48,9 +49,7 @@ import useQueryParameterState from 'docs/src/modules/utils/useQueryParameterStat import HighlightedCode from 'docs/src/modules/components/HighlightedCode'; import synonyms from './synonyms'; -const FlexSearchIndex = flexsearch.default.Index; - -const UPDATE_SEARCH_INDEX_WAIT_MS = 220; +const FlexSearchIndex = flexsearch.Index; // const mui = { // ExitToApp, @@ -479,7 +478,6 @@ function useLatest(value) { } export default function SearchIcons() { - const [keys, setKeys] = React.useState(null); const [theme, setTheme] = useQueryParameterState('theme', 'Filled'); const [selectedIcon, setSelectedIcon] = useQueryParameterState('selected', ''); const [query, setQuery] = useQueryParameterState('query', ''); @@ -495,42 +493,30 @@ export default function SearchIcons() { setSelectedIcon(''); }, [setSelectedIcon]); - const updateSearchResults = React.useMemo( - () => - debounce((value) => { - if (value === '') { - setKeys(null); - } else { - searchIndex.searchAsync(value, { limit: 3000 }).then((results) => { - setKeys(results); - - // Keep track of the no results so we can add synonyms in the future. - if (value.length >= 4 && results.length === 0) { - window.gtag('event', 'material-icons', { - eventAction: 'no-results', - eventLabel: value, - }); - } - }); - } - }, UPDATE_SEARCH_INDEX_WAIT_MS), - [], - ); + const deferredQuery = React.useDeferredValue(query); + const deferredTheme = React.useDeferredValue(theme); + + const isPending = query !== deferredQuery || theme !== deferredTheme; + + const icons = React.useMemo(() => { + const keys = + deferredQuery === '' + ? null + : searchIndex.search(deferredQuery, { limit: 3000 }); + return (keys === null ? allIcons : keys.map((key) => allIconsMap[key])).filter( + (icon) => deferredTheme === icon.theme, + ); + }, [deferredQuery, deferredTheme]); React.useEffect(() => { - updateSearchResults(query); - return () => { - updateSearchResults.clear(); - }; - }, [query, updateSearchResults]); - - const icons = React.useMemo( - () => - (keys === null ? allIcons : keys.map((key) => allIconsMap[key])).filter( - (icon) => theme === icon.theme, - ), - [theme, keys], - ); + // Keep track of the no results so we can add synonyms in the future. + if (deferredQuery.length >= 4 && icons.length === 0) { + window.gtag('event', 'material-icons', { + eventAction: 'no-results', + eventLabel: deferredQuery, + }); + } + }, [deferredQuery, icons]); const dialogSelectedIcon = useLatest( selectedIcon ? allIconsMap[selectedIcon] : null, @@ -543,20 +529,17 @@ export default function SearchIcons() { Filter the style - + setTheme(event.target.value)} + > {['Filled', 'Outlined', 'Rounded', 'Two tone', 'Sharp'].map( (currentTheme) => { return ( setTheme(currentTheme)} - value={currentTheme} - /> - } + value={currentTheme} + control={} label={currentTheme} /> ); @@ -576,6 +559,13 @@ export default function SearchIcons() { onChange={(event) => setQuery(event.target.value)} placeholder="Search icons…" inputProps={{ 'aria-label': 'search icons' }} + endAdornment={ + isPending ? ( + + + + ) : null + } /> {`${formatNumber( diff --git a/docs/src/modules/utils/useQueryParameterState.ts b/docs/src/modules/utils/useQueryParameterState.ts index 159a5b6fe45898..4af5e339ce418e 100644 --- a/docs/src/modules/utils/useQueryParameterState.ts +++ b/docs/src/modules/utils/useQueryParameterState.ts @@ -61,11 +61,10 @@ export default function useQueryParameterState( [setUrlValue], ); - const [, startTransition] = React.useTransition(); const setUserState = React.useCallback( (newValue: string) => { + setUrlValue(newValue); setState(newValue); - startTransition(() => setUrlValue(newValue)); }, [setUrlValue], ); From ba196bfc024891e204bb836f3f1c74eda562e51a Mon Sep 17 00:00:00 2001 From: ZeeshanTamboli Date: Wed, 7 Aug 2024 20:54:37 +0530 Subject: [PATCH 5/8] run effect only when icons length changes --- docs/data/material/components/material-icons/SearchIcons.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index 0f57087d811735..05be58b87e9f02 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -553,7 +553,7 @@ export default function SearchIcons() { eventLabel: deferredQuery, }); } - }, [deferredQuery, icons]); + }, [deferredQuery, icons.length]); const dialogSelectedIcon = useLatest( selectedIcon ? allIconsMap[selectedIcon] : null, From f772c5d2ae6e5408d6331069ebd876bf6979fc31 Mon Sep 17 00:00:00 2001 From: ZeeshanTamboli Date: Thu, 8 Aug 2024 12:35:44 +0530 Subject: [PATCH 6/8] virtualize icons using react-virtuoso --- .../components/material-icons/SearchIcons.js | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index 05be58b87e9f02..498b37f51277e5 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import { VirtuosoGrid } from 'react-virtuoso'; import { styled } from '@mui/material/styles'; import MuiPaper from '@mui/material/Paper'; import copy from 'clipboard-copy'; @@ -128,55 +129,56 @@ const StyledSvgIcon = styled(SvgIcon)(({ theme }) => ({ }, })); -const Icons = React.memo(function Icons(props) { - const { icons, handleOpenClick } = props; - - const handleIconClick = (icon) => () => { - if (Math.random() < 0.1) { - window.gtag('event', 'material-icons', { - eventAction: 'click', - eventLabel: icon.name, - }); - window.gtag('event', 'material-icons-theme', { - eventAction: 'click', - eventLabel: icon.theme, - }); - } - }; - - const handleLabelClick = (event) => { - selectNode(event.currentTarget); - }; - +const ListWrapper = React.forwardRef(({ style, children, ...props }, ref) => { return ( -
- {icons.map((icon) => { - /* eslint-disable jsx-a11y/click-events-have-key-events */ - return ( - - -
- {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO: a11y */} -
{icon.importName}
-
- {/* eslint-enable jsx-a11y/click-events-have-key-events */} -
- ); - })} +
+ {children}
); }); -Icons.propTypes = { - handleOpenClick: PropTypes.func.isRequired, - icons: PropTypes.array.isRequired, -}; +function Icon(handleOpenClick) { + return function itemContent(_, icon) { + const handleIconClick = () => { + if (Math.random() < 0.1) { + window.gtag('event', 'material-icons', { + eventAction: 'click', + eventLabel: icon.name, + }); + window.gtag('event', 'material-icons-theme', { + eventAction: 'click', + eventLabel: icon.theme, + }); + } + }; + + const handleLabelClick = (event) => { + selectNode(event.currentTarget); + }; + + return ( + /* eslint-disable jsx-a11y/click-events-have-key-events */ + + +
+ {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO: a11y */} +
{icon.importName}
+
+ {/* eslint-enable jsx-a11y/click-events-have-key-events */} +
+ ); + }; +} const ImportLink = styled(Link)(({ theme }) => ({ textAlign: 'right', @@ -437,14 +439,7 @@ DialogDetails.propTypes = { selectedIcon: PropTypes.object, }; -const Form = styled('form')({ - position: 'sticky', - top: 80, -}); - const Paper = styled(MuiPaper)(({ theme }) => ({ - position: 'sticky', - top: 80, display: 'flex', alignItems: 'center', marginBottom: theme.spacing(2), @@ -562,7 +557,7 @@ export default function SearchIcons() { return ( -
+ Filter the style @@ -583,7 +578,7 @@ export default function SearchIcons() { }, )} -
+
@@ -608,7 +603,12 @@ export default function SearchIcons() { {`${formatNumber( icons.length, )} matching results`} - + Date: Thu, 8 Aug 2024 16:20:42 +0530 Subject: [PATCH 7/8] Fix intermittent issue of Dialog not closing sometimes --- .../components/material-icons/SearchIcons.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index 498b37f51277e5..f367f510466eef 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -610,11 +610,14 @@ export default function SearchIcons() { itemContent={Icon(handleOpenClick)} />
- + {/* Temporary fix for Dialog not closing sometimes and Backdrop stuck at opacity 0 (see issue https://github.com/mui/material-ui/issues/32286). */} + {selectedIcon ? ( + + ) : null} ); } From e083e6008db10a556a52def51c9064dc6bc86bf8 Mon Sep 17 00:00:00 2001 From: ZeeshanTamboli Date: Thu, 8 Aug 2024 18:44:26 +0530 Subject: [PATCH 8/8] add comment that closing animation is not applied --- docs/data/material/components/material-icons/SearchIcons.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index f367f510466eef..d8378f881feda8 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -610,7 +610,7 @@ export default function SearchIcons() { itemContent={Icon(handleOpenClick)} /> - {/* Temporary fix for Dialog not closing sometimes and Backdrop stuck at opacity 0 (see issue https://github.com/mui/material-ui/issues/32286). */} + {/* Temporary fix for Dialog not closing sometimes and Backdrop stuck at opacity 0 (see issue https://github.com/mui/material-ui/issues/32286). One disadvantage is that the closing animation is not applied. */} {selectedIcon ? (