Skip to content

Commit

Permalink
[docs] Make it easier to find material icons
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Aug 9, 2019
1 parent c5b518b commit 36c9319
Show file tree
Hide file tree
Showing 6 changed files with 444 additions and 52 deletions.
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"emotion-theming": "^10.0.14",
"fg-loadcss": "^2.0.1",
"final-form": "^4.18.2",
"flexsearch": "^0.6.30",
"isomorphic-fetch": "^2.2.1",
"json2mq": "^0.2.0",
"jss-plugin-template": "^10.0.0-alpha.23",
Expand Down
22 changes: 22 additions & 0 deletions docs/pages/components/material-icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import Markdown from 'docs/src/pages/components/material-icons/material-icons.md';
import Search from 'docs/src/pages/components/material-icons/Search';

const req = name => {
const map = {
'material-icons.md': Markdown,
'Search.js': {
default: Search,
},
};
return map[name];
};
req.keys = () => ['material-icons.md', 'Search.js'];
const reqPrefix = 'pages/components/material-icons';

function Page() {
return <MarkdownDocs disableToc req={req} reqSource={() => {}} reqPrefix={reqPrefix} />;
}

export default Page;
1 change: 1 addition & 0 deletions docs/src/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const pages = [
{ pathname: '/components/chips' },
{ pathname: '/components/dividers' },
{ pathname: '/components/icons' },
{ pathname: '/components/material-icons' },
{ pathname: '/components/lists' },
{ pathname: '/components/tables' },
{ pathname: '/components/tooltips' },
Expand Down
203 changes: 203 additions & 0 deletions docs/src/pages/components/material-icons/Search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import InputBase from '@material-ui/core/InputBase';
import Typography from '@material-ui/core/Typography';
import debounce from '@material-ui/core/utils/debounce';
import Grid from '@material-ui/core/Grid';
import FormGroup from '@material-ui/core/FormGroup';
import IconButton from '@material-ui/core/IconButton';
import FlexSearch from 'flexsearch';
import SearchIcon from '@material-ui/icons/Search';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
// import DirectionsIcon from '@material-ui/icons/Directions';
// import DeleteIcon from '@material-ui/icons/Delete';
// import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined';
// import DeleteRoundedIcon from '@material-ui/icons/DeleteRounded';
// import DeleteTwoToneIcon from '@material-ui/icons/DeleteTwoTone';
// import DeleteSharpIcon from '@material-ui/icons/DeleteSharp';
// import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
// import DeleteForeverOutlinedIcon from '@material-ui/icons/DeleteForeverOutlined';
// import DeleteForeverRoundedIcon from '@material-ui/icons/DeleteForeverRounded';
// import DeleteForeverTwoToneIcon from '@material-ui/icons/DeleteForeverTwoTone';
// import DeleteForeverSharpIcon from '@material-ui/icons/DeleteForeverSharp';
import * as mui from '@material-ui/icons';

// const mui = {
// DeleteIcon,
// DeleteOutlinedIcon,
// DeleteRoundedIcon,
// DeleteTwoToneIcon,
// DeleteSharpIcon,
// DeleteForeverIcon,
// DeleteForeverOutlinedIcon,
// DeleteForeverRoundedIcon,
// DeleteForeverTwoToneIcon,
// DeleteForeverSharpIcon,
// };

const useStyles = makeStyles(theme => ({
paper: {
padding: '2px 4px',
display: 'flex',
alignItems: 'center',
marginBottom: theme.spacing(2),
width: '100%',
},
input: {
marginLeft: 8,
flex: 1,
},
iconButton: {
padding: 10,
},
icon: {
boxSizing: 'content-box',
cursor: 'pointer',
borderRadius: theme.shape.borderRadius,
transition: theme.transitions.create(['background-color', 'box-shadow']),
fontSize: 40,
padding: theme.spacing(2),
'&:hover': {
backgroundColor: '#fff',
boxShadow: theme.shadows[1],
},
},
results: {
marginBottom: theme.spacing(2),
},
}));

const index = FlexSearch.create({
async: true,
tokenize: 'full',
});

const allIconsMap = {};
const allIcons = Object.keys(mui)
.sort()
.map(key => ({
key,
Icon: mui[key],
}))
.map(icon => {
let tag;
if (icon.key.indexOf('Outlined') !== -1) {
tag = 'Outlined';
} else if (icon.key.indexOf('TwoTone') !== -1) {
tag = 'Two tone';
} else if (icon.key.indexOf('Rounded') !== -1) {
tag = 'Rounded';
} else if (icon.key.indexOf('Sharp') !== -1) {
tag = 'Sharp';
} else {
tag = 'Filled';
}
icon.tag = tag;

index.add(icon.key, icon.key);
allIconsMap[icon.key] = icon;
return icon;
});

export default function Search() {
const classes = useStyles();
const [tags, setTags] = React.useState(['Filled']);
const [keys, setKeys] = React.useState(null);

const isMounted = React.useRef(false);
React.useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);

const handleChange = React.useMemo(
() =>
debounce(value => {
if (!isMounted.current) {
return;
}

if (value === '') {
setKeys(null);
} else {
index.search(value).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.ga('send', {
hitType: 'event',
eventCategory: 'material-icons',
eventAction: value,
eventLabel: 'no results',
});
}
});
}
}, 500),
[],
);

const icons = (keys === null ? allIcons : keys.map(key => allIconsMap[key])).filter(
icon => tags.indexOf(icon.tag) !== -1,
);

return (
<Grid container>
<Grid item sm={3}>
<form>
<FormGroup>
{['Filled', 'Outlined', 'Rounded', 'Two tone', 'Sharp'].map(key => {
return (
<FormControlLabel
key={key}
control={
<Checkbox
checked={tags.indexOf(key) !== -1}
onChange={() => {
setTags(prevTags => {
if (prevTags.indexOf(key) !== -1) {
return prevTags.filter(tag => tag !== key);
}

return [...prevTags, key];
});
}}
value={key}
/>
}
label={key}
/>
);
})}
</FormGroup>
</form>
</Grid>
<Grid item sm={9}>
<Paper className={classes.paper}>
<IconButton className={classes.iconButton} aria-label="search">
<SearchIcon />
</IconButton>
<InputBase
onChange={event => {
handleChange(event.target.value);
}}
className={classes.input}
placeholder="Search icons…"
inputProps={{ 'aria-label': 'search icons' }}
/>
</Paper>
<Typography className={classes.results}>{`${icons.length} matching results`}</Typography>
<div>
{icons.map(icon => {
return <icon.Icon title={icon.key} className={classes.icon} key={icon.key} />;
})}
</div>
</Grid>
</Grid>
);
}
14 changes: 14 additions & 0 deletions docs/src/pages/components/material-icons/material-icons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Material Icons
components: Icon, SvgIcon
---

# Material Icons

<p class="description">1,000+ React Material icons ready to use from the official website.</p>

The following npm package,
[@material-ui/icons](https://www.npmjs.com/package/@material-ui/icons),
includes the 1,000+ official [Material icons](https://material.io/tools/icons/?style=baseline) converted to `SvgIcon` components.

{{"demo": "pages/components/material-icons/Search.js", "hideHeader": true}}
Loading

0 comments on commit 36c9319

Please sign in to comment.