Material Design Icons by Google, in a tree-shakable, SVG string, ESModule form. Based off of @material-design-icons/svg, & automatically updates via GitHub Actions.
<script>
import { ic_done } from 'maic/two_tone';
// ^ '<svg xmlns="http://www.w3.org/2000/svg" ...'
</script>
<div class='component'>
{@html ic_done}
</div>The structure of importables are as so:
┌/maic
└─┬/{variant}
└──/ic_{icon}
{variant} & {icon} correspond to the variant (eg. filled, outline, rounded, sharp, two_tone) of the icon, & the icon font ligature (eg. done, search, settings), respectfully. See the full list of both on Google Fonts or @material-design-icons/svg's demo.
This structure is exposed both in the module exported paths, as well as each level's import. This enables, but is not limited to, the following patterns:
import * as maic from 'maic';
import { filled } from 'maic';
import * as filled from 'maic/filled';
import { ic_done } from 'maic/filled';
import ic_done from 'maic/filled/done';❗Caveat 1
Unlike the folder structure found in
@material-design-icons/svg,{variant}s here aresnake_casedrather thankebab-cased(eg.two-toneis cased astwo_tone).For more info, see ESM compatibility.
❗Caveat 2
{icon}s are always prefixed withic_(eg.import done from 'ic_done').For more info, see ESM compatibility.
Before you start using maic, ensure your bundler, import loader, or simply your JavaScript environment, performs NodeJS-style module resolution. This is the default for most popular bundlers, but you may have to enable it manually, even for NodeJS itself.
If you aren't able to modify such a setting, you may have to modify your import specifiers (see below).
After that, simply use one of the import strategies below:
Import the variant, & get access to each icon individually through named imports.
ℹ️ Hint
This is the recommended way of using
maic, as it balances terseness with tree-shakability.For more info, see Tree-shaking.
import { ic_1k_plus } from 'maic/filled';
// ^ '<svg xmlns="http://www.w3.org/2000/svg" ...'ℹ️ Hint
If you're having trouble importing & you're not using NodeJS-style imports, try appending
/index.jsto the end of the import specifier (eg.maic/filled→maic/filled/index.js).
Import only a specific icon, & gain access to it through a default import.
Use this when you're not using a bundler, or one that doesn't support tree-shaking. Also use this you're using dynamic imports (eg.
await import('maic/filled/ic_1k_plus')).For more info, see Tree-shaking.
import ic_1k_plus from 'maic/filled/ic_1k_plus';
// ^ '<svg xmlns="http://www.w3.org/2000/svg" ...'ℹ️ Hint
If you're having trouble importing & you're not using NodeJS-style imports, try appending
.jsto the end of the import specifier (eg.maic/filled/ic_1k_plus→maic/filled/ic_1k_plus.js).
Import the whole module, & gain access to variants, with their respective icons inside.
⚠️ WarningUse this with caution! as to not "leak" the imported SVGs into un-tree-shakable contexts (such as cloning the immutable module object into a mutable, regular, JavaScript object)
For more info, see Tree-shaking.
import { filled } from 'maic';
// ^ {
// ic_1k_plus: '<svg xmlns="http://www.w3.org/2000/...',
// ic_1k: '<svg xmlns="http://www.w3.org/2000/svg" ...',
// ...
// }To speed up development reloads when using vite/rollup, you may use the maic/helper plugin like below to only import the required icons during development.
// vite/rollup.config.js
import maicHelper from 'maic/helper';
export default {
plugins: [
maicHelper({
enabled: !process.env.NODE_ENV !== 'production',
}),
],
};maic is a large module, having a file for each icon, for each variant. On certain build pipelines, treeshaking doesn't apply for SSR builds & they leak overly wide maic imports, such as import {} from 'maic', causing runtimes to load the entire maic library & crashing. In this case, using maic/helper for both the development & production build may help.
// vite/rollup.config.js
import maicHelper from 'maic/helper';
export default {
plugins: [
maicHelper(),
],
};The assumption of a working, tree-shaking-capable bundles is the crux of why this module can even exist. maic utilises the fact that any code that is not imported, or is imported & not used, will be shed away in modern bundlers. This enables maic to lump the (surprisingly massive) collection of Material Design Icon SVGs into a few JavaScript files & call it a day.
...Somewhat.
Unfortunately, tree-shaking in the JavaScript ecosystem is often fragile. This is due to the dynamism of JavaScript's interpreted nature. You can do really nasty things to access & assign properties (eg. eval). Due to this bundlers have a relatively limited scope of when & where tree-shaking happens. The gist of import-related rules are as follows:
- ✔️ Import maps
- (eg.
import { ic_done } from 'maic/filled')
- (eg.
- ✔️ Immutable imported objects
- (eg.
import * as filled from 'maic/filled')
- (eg.
- ❌ Dynamic imports
- (eg.
const { ic_done } = await import('maic'))
- (eg.
In the situations where tree-shaking doesn't kick in, you may want to consider using only icon-level imports, or vite/rollup hot reloads. However, if the problem permuates through your codebase, a build chain refactor is commonly the only way out.
There have been a few changes that were carried out to enable ESM compatibility:
- Transforming
kebab-casedfolder names tosnake_cased- (eg.
two-toneis not a valid JavaScript identifier, as the hyphen is the subtraction operator)
- (eg.
- Appending the
ic_prefix to every icon- (eg.
1kis not a valid JavaScript identifier, as it starts with a number)
- (eg.
Both of these choices were made to allow imports to be consistent across folder structures & ESModule imports.
// `two_tone` can be imported & is consistent with directory imports
// the `ic_` prefix appears everywhere instead of only certain places
import { ic_1k } from 'maic/filled';
import ic_1k_plus from 'maic/filled/ic_1k_plus';
import { two_tone } from 'maic';
import { ic_1x_mobiledata } from 'maic/two_tone';
import ic_2k_plus from 'maic/two_tone/ic_2k_plus';The sematic version of maic is linked to @material-design-icons's.
Any hotfixes to maic itself, orthogonal to the version of icons it depends on, will be appended to the end of the version (eg. the first fix for @[email protected] will be [email protected]).
The only prerequisites is having npm & NodeJS installed. Run the following to build the maic workspace, & publish it to npm:
npm run build
npm run publish- Material design icons are created by Google, licensed under the Apache License Version 2.0.
- SVG's are sourced from
@material-design-icons, licensed under the Apache License Version 2.0. - This project is distributed under the MIT License.