The page navigation is complete. You may now navigate the page content as you wish.
Skip to main content

Web Components

Use i80 in plain HTML and server-rendered apps with <i80-*> tags.

The components on this site are also available as Web Components: <i80-*> tags that render the same HTML and styles. They need no framework and no build step, so they work in plain HTML and in Django, Flask, Rails or PHP templates.

<link rel="stylesheet" href="https://design.i80.dk/v/0.5.2/components.css">
<script type="module" src="https://design.i80.dk/v/0.5.2/i80.js"></script>

<i80-button color="primary" icon="plus">New plan</i80-button>

Native elements written inside a tag are kept, so server-rendered forms keep their field names, ids, values and CSRF tokens:

<i80-text-input label="Email" error="{{ form.email.errors.0 }}">
  {{ form.email }}
</i80-text-input>

See all Web Components with live examples, or a whole screen built from them.

Each component page on this site shows the same thing: on the Code tab, pick .html to see that example written as HTML.

In a framework

Custom elements are part of the browser, so they work in any framework that renders HTML. What differs is how a framework passes data to them. We test i80 in plain HTML, in server-rendered templates and with HTMX; the notes below are what to expect elsewhere.

What to do
HTMX, Alpine, Turbo Nothing. Swapped-in tags are set up as soon as they are inserted.
Svelte, Solid, Lit Nothing. They set properties and attributes on custom elements.
React 19 and later Nothing. React 19 sets properties, and onI80Close-style props are not needed — add listeners with a ref if you want events.
React 18 and earlier String attributes work; for events, attach a listener to a ref.
Vue 3 Tell the compiler these are custom elements, otherwise it warns: compilerOptions.isCustomElement: (tag) => tag.startsWith('i80-').
Angular Add CUSTOM_ELEMENTS_SCHEMA to the module or component.

Server-side rendering frameworks (Next.js, Nuxt, Rails with Turbo) render the tags as plain markup; i80.js upgrades them in the browser. Nothing breaks before it loads, because a tag's content is real HTML — a form still submits.

React and Vue are not in scope for us yet, so there are no wrapper packages: you use the tags directly. If a product needs deeper integration, that is worth designing then.