Plain HTML and CDN
Use the custom elements and CSS classes on a page with no framework and no bundler, loading the scripts from a CDN.
Elements from a CDN
Each custom element is one ES module with no dependencies outside the package, so a
<script type="module"> tag can load it straight from a CDN. unpkg follows the
package's export map, so the URLs match the import paths; pin a version:
<script type="module" src="https://unpkg.com/@kyralabs/m3e-elements@1.8.0/menu.js"></script>
On CDNs that serve files by path, such as jsDelivr, use the file the export points to:
https://cdn.jsdelivr.net/npm/@kyralabs/m3e-elements@1.8.0/dist/menu/index.js.
Module scripts run after the document is parsed; elements render when their module loads.
The stylesheets
The token stylesheets are self-contained and load from a CDN too:
<link rel="stylesheet" href="https://unpkg.com/@kyralabs/m3e-tokens@1.8.0/fonts.css" />
<link rel="stylesheet" href="https://unpkg.com/@kyralabs/m3e-tokens@1.8.0/tokens.css" />
<link rel="stylesheet" href="https://unpkg.com/@kyralabs/m3e-tokens@1.8.0/theme.css" />
<link rel="stylesheet" href="https://unpkg.com/@kyralabs/m3e-tokens@1.8.0/material-symbols.css" />
The component stylesheets do not load from a CDN yet. The m3e-css files import
their component tokens by package name (@import "@kyralabs/m3e-tokens/…"), which
only a bundler resolves; a browser looks for those files next to the stylesheet and finds
nothing, so components render unstyled. A self-contained bundle is tracked in
issue #106.
Until then, bundle the CSS once and host the result with your page. One esbuild command resolves the imports and copies the font files:
npm install @kyralabs/m3exp-web esbuild
npx esbuild --bundle node_modules/@kyralabs/m3exp-web/dist/css/index.css \
--outfile=m3e/m3e.css --loader:.woff2=file --minify
m3e/m3e.css then holds the fonts, the tokens, the baseline theme and every
component class, and the font files sit beside it. To bundle fewer components, point esbuild at
a file of your own that imports the token stylesheets and the
@kyralabs/m3e-css/<component>.css files you use.
A complete page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light dark" />
<title>My page</title>
<!-- Fonts, tokens, theme and component classes: bundled once, see below -->
<link rel="stylesheet" href="./m3e/m3e.css" />
<!-- Icons -->
<link rel="stylesheet" href="https://unpkg.com/@kyralabs/m3e-tokens@1.8.0/material-symbols.css" />
<!-- One module per element -->
<script type="module" src="https://unpkg.com/@kyralabs/m3e-elements@1.8.0/ripple.js"></script>
<script type="module" src="https://unpkg.com/@kyralabs/m3e-elements@1.8.0/menu.js"></script>
<script type="module" src="https://unpkg.com/@kyralabs/m3e-elements@1.8.0/loading-indicator.js"></script>
</head>
<body>
<button type="button" class="m3e-button m3e-button--filled m3e-button--size-m">
<span class="m3e-icon" aria-hidden="true">save</span>
Save
</button>
<button id="more" type="button" class="m3e-icon-button" aria-label="More options">
<span class="m3e-icon" aria-hidden="true">more_vert</span>
</button>
<m3e-menu anchor="more">
<m3e-menu-item value="edit" icon="edit">Edit</m3e-menu-item>
<m3e-menu-item value="share" icon="share">Share</m3e-menu-item>
</m3e-menu>
<m3e-loading-indicator contained aria-label="Loading"></m3e-loading-indicator>
</body>
</html>
The button needs no script: m3e-css draws it, and ripple.js adds the press
ripple. The menu and the loading indicator are elements. The page reads its color scheme from
the system; add data-theme="dark" or data-theme="light" to
<html> to force one (theming).
For production, ship only the icons you use: material-symbols.css loads a font of
several megabytes. See fonts and icons.