Getting started

No build step is required to use these components — files in public/ are served directly.

Link the stylesheet

Every page links /ui/ui.css (shared component CSS + Open Props tokens) and /index.css (project-level semantic aliases + theme):

Show code <link rel="stylesheet" href="/ui/ui.css"> <link rel="stylesheet" href="/index.css">

Load preload.mjs first

/preload.mjs must be the page's first module script, before all components. It installs polyfills that components need during initialization. Loading it later can silently lose property writes and leave popovers in the wrong position. <link rel="modulepreload"> only fetches a module; it does not execute it. See Browser support · Polyfills.

Show code <script type="module" src="/preload.mjs"></script>

Import the components you need

Each custom element is a separate ES module. Import only what the page uses.

Show code <script type="module" src="/ui/components/ui-icon.mjs"></script> <script type="module" src="/ui/components/ui-dialog.mjs"></script> <script type="module" src="/ui/components/ui-menu.mjs"></script>

Lib helpers (toast(), tooltip(), spin()) are imported from /ui/lib/*.mjs.

Prevent theme flashes

Put a small inline script in <head> before the stylesheet links so a returning dark-mode user doesn't see a flash of light. See Color · Flash prevention for the full pattern.

Dev server

For local development, the project includes a Vite dev server:

Show code npm run dev # localhost:8080

Vite is not required at runtime — you can also serve public/ with any static server.

Tests

First page

A minimal page using the shared stylesheet and a couple of components:

Show code <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>My page</title> <link rel="stylesheet" href="/ui/ui.css"> <link rel="stylesheet" href="/index.css"> <script type="module" src="/preload.mjs"></script> <script type="module" src="/ui/components/ui-icon.mjs"></script> <script type="module" src="/ui/components/ui-dialog.mjs"></script> </head> <body> <h1>Hello</h1> <button class="btn">Primary action</button> </body> </html>

See also