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_cased
rather thankebab-cased
(eg.two-tone
is 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.js
to 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
.js
to 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-cased
folder names tosnake_cased
- (eg.
two-tone
is not a valid JavaScript identifier, as the hyphen is the subtraction operator)
- (eg.
- Appending the
ic_
prefix to every icon- (eg.
1k
is 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.