Skip to content

Commit bbbcac8

Browse files
[docs] Revert icon search virtualization (#43569)
Co-authored-by: Olivier Tassinari <[email protected]>
1 parent 1c76999 commit bbbcac8

File tree

1 file changed

+81
-79
lines changed

1 file changed

+81
-79
lines changed

docs/data/material/components/material-icons/SearchIcons.js

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as React from 'react';
2-
import { VirtuosoGrid } from 'react-virtuoso';
32
import { styled } from '@mui/material/styles';
43
import MuiPaper from '@mui/material/Paper';
54
import copy from 'clipboard-copy';
@@ -94,21 +93,20 @@ function selectNode(node) {
9493
selection.addRange(range);
9594
}
9695

96+
const iconWidth = 35;
97+
9798
const StyledIcon = styled('span')(({ theme }) => ({
9899
display: 'inline-flex',
99100
flexDirection: 'column',
100101
color: theme.palette.text.secondary,
101102
margin: '0 4px',
102103
'& > div': {
103-
display: 'flex',
104-
},
105-
'& > div > *': {
106104
flexGrow: 1,
107105
fontSize: '.6rem',
108106
overflow: 'hidden',
109107
textOverflow: 'ellipsis',
110108
textAlign: 'center',
111-
width: 0,
109+
width: `calc(${iconWidth}px + ${theme.spacing(2)} * 2 + 2px)`,
112110
},
113111
}));
114112

@@ -117,6 +115,7 @@ const StyledSvgIcon = styled(SvgIcon)(({ theme }) => ({
117115
cursor: 'pointer',
118116
color: theme.palette.text.primary,
119117
border: '1px solid transparent',
118+
fontSize: iconWidth,
120119
borderRadius: '12px',
121120
transition: theme.transitions.create(['background-color', 'box-shadow'], {
122121
duration: theme.transitions.duration.shortest,
@@ -129,56 +128,64 @@ const StyledSvgIcon = styled(SvgIcon)(({ theme }) => ({
129128
},
130129
}));
131130

132-
const ListWrapper = React.forwardRef(({ style, children, ...props }, ref) => {
131+
const handleIconClick = (event) => {
132+
const { iconName, iconTheme } = event.currentTarget.dataset;
133+
134+
if (Math.random() < 0.1) {
135+
window.gtag('event', 'material-icons', {
136+
eventAction: 'click',
137+
eventLabel: iconName,
138+
});
139+
window.gtag('event', 'material-icons-theme', {
140+
eventAction: 'click',
141+
eventLabel: iconTheme,
142+
});
143+
}
144+
};
145+
146+
function handleLabelClick(event) {
147+
selectNode(event.currentTarget);
148+
}
149+
150+
function Icon(props) {
151+
const { icon, onOpenClick } = props;
152+
/* eslint-disable jsx-a11y/click-events-have-key-events */
133153
return (
134-
<div
135-
ref={ref}
136-
{...props}
137-
style={{ display: 'flex', flexWrap: 'wrap', ...style }}
154+
<StyledIcon
155+
key={icon.importName}
156+
onClick={handleIconClick}
157+
data-icon-theme={icon.theme}
158+
data-icon-name={icon.name}
138159
>
139-
{children}
140-
</div>
160+
<StyledSvgIcon
161+
component={icon.Component}
162+
tabIndex={-1}
163+
onClick={onOpenClick}
164+
title={icon.importName}
165+
/>
166+
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO: a11y */}
167+
<div onClick={handleLabelClick}>{icon.importName}</div>
168+
{/* eslint-enable jsx-a11y/click-events-have-key-events */}
169+
</StyledIcon>
141170
);
142-
});
171+
}
143172

144-
function Icon(handleOpenClick) {
145-
return function itemContent(_, icon) {
146-
const handleIconClick = () => {
147-
if (Math.random() < 0.1) {
148-
window.gtag('event', 'material-icons', {
149-
eventAction: 'click',
150-
eventLabel: icon.name,
151-
});
152-
window.gtag('event', 'material-icons-theme', {
153-
eventAction: 'click',
154-
eventLabel: icon.theme,
155-
});
156-
}
157-
};
173+
const Icons = React.memo(function Icons(props) {
174+
const { icons, handleOpenClick } = props;
158175

159-
const handleLabelClick = (event) => {
160-
selectNode(event.currentTarget);
161-
};
176+
return (
177+
<div>
178+
{icons.map((icon) => (
179+
<Icon key={icon.importName} icon={icon} onOpenClick={handleOpenClick} />
180+
))}
181+
</div>
182+
);
183+
});
162184

163-
return (
164-
/* eslint-disable jsx-a11y/click-events-have-key-events */
165-
<StyledIcon key={icon.importName} onClick={handleIconClick}>
166-
<StyledSvgIcon
167-
component={icon.Component}
168-
fontSize="large"
169-
tabIndex={-1}
170-
onClick={handleOpenClick}
171-
title={icon.importName}
172-
/>
173-
<div>
174-
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO: a11y */}
175-
<div onClick={handleLabelClick}>{icon.importName}</div>
176-
</div>
177-
{/* eslint-enable jsx-a11y/click-events-have-key-events */}
178-
</StyledIcon>
179-
);
180-
};
181-
}
185+
Icons.propTypes = {
186+
handleOpenClick: PropTypes.func.isRequired,
187+
icons: PropTypes.array.isRequired,
188+
};
182189

183190
const ImportLink = styled(Link)(({ theme }) => ({
184191
textAlign: 'right',
@@ -439,7 +446,14 @@ DialogDetails.propTypes = {
439446
selectedIcon: PropTypes.object,
440447
};
441448

449+
const Form = styled('form')({
450+
position: 'sticky',
451+
top: 80,
452+
});
453+
442454
const Paper = styled(MuiPaper)(({ theme }) => ({
455+
position: 'sticky',
456+
top: 80,
443457
display: 'flex',
444458
alignItems: 'center',
445459
marginBottom: theme.spacing(2),
@@ -525,30 +539,26 @@ export default function SearchIcons() {
525539
setSelectedIcon('');
526540
}, [setSelectedIcon]);
527541

528-
const deferredQuery = React.useDeferredValue(query);
529-
const deferredTheme = React.useDeferredValue(theme);
530-
531-
const isPending = query !== deferredQuery || theme !== deferredTheme;
532-
533542
const icons = React.useMemo(() => {
534-
const keys =
535-
deferredQuery === ''
536-
? null
537-
: searchIndex.search(deferredQuery, { limit: 3000 });
543+
const keys = query === '' ? null : searchIndex.search(query, { limit: 3000 });
538544
return (keys === null ? allIcons : keys.map((key) => allIconsMap[key])).filter(
539-
(icon) => deferredTheme === icon.theme,
545+
(icon) => theme === icon.theme,
540546
);
541-
}, [deferredQuery, deferredTheme]);
547+
}, [query, theme]);
548+
549+
const deferredIcons = React.useDeferredValue(icons);
550+
551+
const isPending = deferredIcons !== icons;
542552

543553
React.useEffect(() => {
544554
// Keep track of the no results so we can add synonyms in the future.
545-
if (deferredQuery.length >= 4 && icons.length === 0) {
555+
if (query.length >= 4 && icons.length === 0) {
546556
window.gtag('event', 'material-icons', {
547557
eventAction: 'no-results',
548-
eventLabel: deferredQuery,
558+
eventLabel: query,
549559
});
550560
}
551-
}, [deferredQuery, icons.length]);
561+
}, [query, icons.length]);
552562

553563
const dialogSelectedIcon = useLatest(
554564
selectedIcon ? allIconsMap[selectedIcon] : null,
@@ -557,7 +567,7 @@ export default function SearchIcons() {
557567
return (
558568
<Grid container sx={{ minHeight: 500 }}>
559569
<Grid item xs={12} sm={3}>
560-
<form>
570+
<Form>
561571
<Typography fontWeight={500} sx={{ mb: 1 }}>
562572
Filter the style
563573
</Typography>
@@ -578,7 +588,7 @@ export default function SearchIcons() {
578588
},
579589
)}
580590
</RadioGroup>
581-
</form>
591+
</Form>
582592
</Grid>
583593
<Grid item xs={12} sm={9}>
584594
<Paper>
@@ -603,21 +613,13 @@ export default function SearchIcons() {
603613
<Typography sx={{ mb: 1 }}>{`${formatNumber(
604614
icons.length,
605615
)} matching results`}</Typography>
606-
<VirtuosoGrid
607-
style={{ height: 500 }}
608-
data={icons}
609-
components={{ List: ListWrapper }}
610-
itemContent={Icon(handleOpenClick)}
611-
/>
616+
<Icons icons={deferredIcons} handleOpenClick={handleOpenClick} />
612617
</Grid>
613-
{/* 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. */}
614-
{selectedIcon ? (
615-
<DialogDetails
616-
open={!!selectedIcon}
617-
selectedIcon={dialogSelectedIcon}
618-
handleClose={handleClose}
619-
/>
620-
) : null}
618+
<DialogDetails
619+
open={!!selectedIcon}
620+
selectedIcon={dialogSelectedIcon}
621+
handleClose={handleClose}
622+
/>
621623
</Grid>
622624
);
623625
}

0 commit comments

Comments
 (0)