diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js
index fc2d1f34e158a5..602f6718a81ee7 100644
--- a/docs/data/material/components/material-icons/SearchIcons.js
+++ b/docs/data/material/components/material-icons/SearchIcons.js
@@ -5,7 +5,6 @@ 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';
@@ -14,6 +13,7 @@ import DialogTitle from '@mui/material/DialogTitle';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import Button from '@mui/material/Button';
+import Stack from '@mui/material/Stack';
import * as flexsearch from 'flexsearch';
import SearchIcon from '@mui/icons-material/Search';
import FormControlLabel from '@mui/material/FormControlLabel';
@@ -50,8 +50,6 @@ import synonyms from './synonyms';
const FlexSearchIndex = flexsearch.default.Index;
-const UPDATE_SEARCH_INDEX_WAIT_MS = 220;
-
// const mui = {
// ExitToApp,
// ExitToAppOutlined,
@@ -129,50 +127,54 @@ 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 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 handleLabelClick = (event) => {
+ selectNode(event.currentTarget);
+ };
- 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 */}
-
- );
- })}
-
- );
-});
+ 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 */}
+
+ );
+ })}
+
+ );
+ },
+ (prev, next) =>
+ prev.data.total === next.data.total && prev.data.length === next.data.length,
+);
Icons.propTypes = {
handleOpenClick: PropTypes.func.isRequired,
@@ -480,9 +482,12 @@ function useLatest(value) {
export default function SearchIcons() {
const [keys, setKeys] = React.useState(null);
- const [theme, setTheme] = useQueryParameterState('theme', 'Filled');
+ const lazyKeys = React.useDeferredValue(keys);
+ const [theme, setTheme] = useQueryParameterState('theme', 'All');
const [selectedIcon, setSelectedIcon] = useQueryParameterState('selected', '');
- const [query, setQuery] = useQueryParameterState('query', '');
+ const [query, setQuery] = useQueryParameterState('query', '', 0);
+ const lazyQuery = React.useDeferredValue(query);
+ const [minIcons, setMinIcons] = React.useState(49);
const handleOpenClick = React.useCallback(
(event) => {
@@ -495,41 +500,32 @@ 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),
- [],
- );
-
React.useEffect(() => {
- updateSearchResults(query);
- return () => {
- updateSearchResults.clear();
- };
- }, [query, updateSearchResults]);
+ if (lazyQuery === '') {
+ setMinIcons(49);
+ setKeys(null);
+ return;
+ }
+
+ searchIndex.searchAsync(lazyQuery, { limit: 3000 }).then((res) => {
+ setKeys(res);
+
+ if (lazyQuery.length >= 4 && res.length === 0) {
+ window.gtag('event', 'material-icons', {
+ eventAction: 'no-results',
+ eventLabel: lazyQuery,
+ });
+ }
+ });
+ }, [lazyQuery]);
const icons = React.useMemo(
() =>
- (keys === null ? allIcons : keys.map((key) => allIconsMap[key])).filter(
- (icon) => theme === icon.theme,
- ),
- [theme, keys],
+ (lazyKeys === null
+ ? allIcons
+ : lazyKeys.map((key) => allIconsMap[key])
+ ).filter((icon) => theme === 'All' || theme === icon.theme),
+ [theme, lazyKeys],
);
const dialogSelectedIcon = useLatest(
@@ -544,7 +540,7 @@ export default function SearchIcons() {
Filter the style
- {['Filled', 'Outlined', 'Rounded', 'Two tone', 'Sharp'].map(
+ {['All', 'Filled', 'Outlined', 'Rounded', 'Two tone', 'Sharp'].map(
(currentTheme) => {
return (
setQuery(event.target.value)}
- placeholder="Search icons…"
+ placeholder={`Search icons...`}
inputProps={{ 'aria-label': 'search icons' }}
/>
- {`${formatNumber(
- icons.length,
- )} matching results`}
-
+
+ {`${formatNumber(icons.length)} matching results`}
+
+
+
+ {icons.length > minIcons && (
+
+ )}
+
void] {
const initialValueRef = React.useRef(initialValue);
@@ -50,7 +49,7 @@ export default function useQueryParameterState(
},
);
}
- }, QUERY_UPDATE_WAIT_MS),
+ }, waitMs),
[name, router],
);