Using the elements
Zeno's elements are custom elements with the tag prefix zeno-. They work in
plain HTML and in any framework that renders HTML.
Load them
import '@usezeno/tokens/css';
import '@usezeno/core/web-components';
The first line loads the design tokens. The elements have no colours of their own without it. The second line registers every element. There is one entry point for all of them, so an app that uses two elements still loads them all.
<zeno-button variant="primary">Save</zeno-button>
Attributes and properties
Text, numbers and on/off settings can be written as attributes:
<zeno-input label="Email" type="email" required></zeno-input>
A property with a two-word name has a kebab-case attribute: the property
fullWidth is the attribute full-width.
Arrays, objects and functions have to be set as properties from script:
document.querySelector('zeno-select').options = [
{ value: 'free', label: 'Free' },
{ value: 'team', label: 'Team' },
];
An on/off attribute is on whenever it is present. disabled="false" still
disables the element. Remove the attribute, or set the property to false.
Events
Listen with addEventListener, or with your framework's event syntax.
inputandchangecome from form controls. They bubble and cross shadow boundaries, like the native events, so one listener on a form hears every control inside it.inputfires on each change andchangewhen the change is committed.- Every other event (
open,close,request-close,sort, …) does not bubble. Listen on the element itself. - Events are
CustomEvents. The new state is inevent.detail, for exampleevent.detail.valueorevent.detail.checked. - Clickable elements such as
zeno-buttonandzeno-chipsend the browser's ownclickevent. There is no separate custom click event.
Forms
These elements are form controls: zeno-input, zeno-textarea,
zeno-select, zeno-checkbox, zeno-switch, zeno-radio,
zeno-radio-group, zeno-slider, zeno-date-picker and zeno-file-upload.
They take part in a <form> the way native controls do:
<form>
<zeno-input name="email" type="email" label="Email" required></zeno-input>
<zeno-checkbox name="updates" label="Send me updates"></zeno-checkbox>
<zeno-button type="submit">Sign up</zeno-button>
<zeno-button type="reset" variant="ghost">Clear</zeno-button>
</form>
- Submitting. A control with a
nameadds its value to the form's data.zeno-buttonwithtype="submit"submits the form, andtype="reset"resets it. - Labels. Set the
labelattribute, or point a<label for>at the element'sid. Clicking either one focuses or toggles the control, and screen readers announce it as the control's name. - Validation.
required,type,pattern,min,max,minlengthandmaxlengthare checked as the browser checks them. An invalid control blocks the submit and matches the:invalidCSS selector. The message shows under the control once the user has left it or a submit was refused. - From script.
checkValidity(),reportValidity()andsetCustomValidity(message)work as on a native input, andvalidity,validationMessage,formandlabelsare there to read. Set theerrorproperty to show a message of your own, for example one a server returned. - Disabled. A control is disabled by its own
disabledattribute or by a<fieldset disabled>around it. A disabled control is left out of the form's data. - Reset. Resetting the form puts each control back to the value it had when it was added to the page.
The validation messages that Zeno writes itself, such as "Please fill out this field.", are in English only for now.
Overlays
zeno-modal and zeno-drawer are built on the browser's <dialog> element.
While one is open the rest of the page cannot be reached by mouse, keyboard or
screen reader, and focus returns to where it was when it closes.
<zeno-modal heading="Delete this file?">
<p>This cannot be undone.</p>
<zeno-button slot="footer" variant="destructive">Delete</zeno-button>
</zeno-modal>
const modal = document.querySelector('zeno-modal');
modal.show();
modal.addEventListener('close', () => console.log('closed'));
- Open with
show()or by settingopen. Close withclose(). - The close button, a click on the backdrop and the Escape key each ask to
close. They send a
request-closeevent first, withevent.detail.sourceset toclose-button,backdroporescape. Callevent.preventDefault()to keep the dialog open, for example while a form has unsaved changes. no-backdrop-close,no-escape-closeandno-close-buttonswitch each route off.
zeno-tooltip, the list of zeno-select and the calendar of
zeno-date-picker use the browser's popover feature. They show above
everything else on the page and are never cut off by a scrolling container.
Styling
- Tokens. Change a
--zeno-*custom property on:root, or on any element to affect what is inside it. See Tokens and theming. - Parts. Elements expose their inner pieces as CSS parts:
zeno-button::part(base). Each element page lists that element's parts, slots, properties and events. The same data is in the custom-elements manifest,@usezeno/core/custom-elements.json, for editors and tools.