Elements
Standards-based custom elements for the complete Lumen catalog, ready for plain HTML or any framework through the same shared class and data contract.
- Surface
- Native
- API
- DOM
- Package
- Elements
Installation
Install the Elements package, load its stylesheet once, register Lumen elements, and use lumen-* tags anywhere HTML is valid. Behavior-backed elements include overlays, context menus, select, forms, rich text, schedule, toast, DataTable, ThemeBuilder, and VirtualList.
pnpm
pnpm add @santi020k/lumen-elementspnpm add @santi020k/lumen-elementsnpm
npm install @santi020k/lumen-elementsnpm install @santi020k/lumen-elementsyarn
yarn add @santi020k/lumen-elementsyarn add @santi020k/lumen-elementsUsage Example
<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-card>
<label for="email">Email</label>
<lumen-input id="email" type="email" placeholder="you@example.com"></lumen-input>
<lumen-button>Subscribe</lumen-button>
</lumen-card><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-card>
<label for="email">Email</label>
<lumen-input id="email" type="email" placeholder="you@example.com"></lumen-input>
<lumen-button>Subscribe</lumen-button>
</lumen-card>Overview
- Custom elements expose the shared class and data contract through lumen-* tags that work in plain HTML or any framework.
- Call defineLumenElements once before using the tags; behavior-backed elements include DataTable selection/sort, form validation, calendar grids, OTP segmentation, date range syncing, rich text commands, context menu triggers, schedule drag/drop, resizable pane sizing, ThemeBuilder export, VirtualList range events, overlays, select, tabs, tooltip, and toast.
- Use lumen add Component --target elements or lumen add recipe-name --target elements when you want local Elements starter files.
API Reference
DOM APIs, registration, and progressive enhancement functions for Lumen elements.
defineLumenElements
Registers all 79 Lumen web components in the custom element registry. Call once before using any <lumen-*> tags. Optionally pass a custom registry for scoped usage.
| Signature / Attribute | Description |
|---|---|
| registry CustomElementRegistry (optional) | Custom element registry to register against. Defaults to the global customElements. |
Example
<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-card>
<lumen-button>Click me</lumen-button>
</lumen-card><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-card>
<lumen-button>Click me</lumen-button>
</lumen-card>enhanceLumenForms
Enhances forms marked with [data-ui-form] with native constraint validation, custom error messages via data-error-* attributes, and field description syncing. Works without registering custom elements.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for [data-ui-form] forms. Defaults to document. |
| data-error-required attribute | Custom message shown when a required field is empty. |
| data-error-type attribute | Custom message shown when the value does not match the input type (e.g. email). |
| data-error-pattern attribute | Custom message shown when the value does not match the pattern attribute. |
| data-error-min / data-error-max attribute | Custom message for range violations. |
Example
<script type="module">
import { enhanceLumenForms } from '@santi020k/lumen-elements/define'
enhanceLumenForms()
</script>
<form data-ui-form>
<label for="email">Email</label>
<input
id="email"
type="email"
required
data-error-required="Please enter your email"
data-error-type="Enter a valid email address"
class="ui-input"
/>
<button type="submit" class="ui-button ui-button--default">Sign up</button>
</form><script type="module">
import { enhanceLumenForms } from '@santi020k/lumen-elements/define'
enhanceLumenForms()
</script>
<form data-ui-form>
<label for="email">Email</label>
<input
id="email"
type="email"
required
data-error-required="Please enter your email"
data-error-type="Enter a valid email address"
class="ui-input"
/>
<button type="submit" class="ui-button ui-button--default">Sign up</button>
</form>enhanceLumenCalendars
Enhances elements marked with [data-ui-calendar] or <lumen-calendar> with generated date grids, hidden input values, month navigation, selection, min/max clamping, and keyboard focus.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for calendars. Defaults to document. |
| month YYYY-MM | Visible month for generated calendars. |
| value YYYY-MM-DD | Initial selected date copied to the hidden input. |
| min / max YYYY-MM-DD | Inclusive selectable date bounds. |
| name attribute | Forwarded to the generated hidden input for form submission. |
Example
<script type="module">
import { enhanceLumenCalendars } from '@santi020k/lumen-elements/define'
enhanceLumenCalendars()
</script>
<lumen-calendar
max="2026-07-31"
min="2026-07-01"
month="2026-07"
name="delivery"
></lumen-calendar><script type="module">
import { enhanceLumenCalendars } from '@santi020k/lumen-elements/define'
enhanceLumenCalendars()
</script>
<lumen-calendar
max="2026-07-31"
min="2026-07-01"
month="2026-07"
name="delivery"
></lumen-calendar>enhanceLumenDateRangePickers
Enhances elements marked with [data-ui-date-range-picker] so paired native date inputs keep min/max constraints in sync. Works without registering custom elements.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for date range pickers. Defaults to document. |
| input[type="date"] native date inputs | The first date input is treated as the start date and the last date input is treated as the end date. |
Example
<script type="module">
import { enhanceLumenDateRangePickers } from '@santi020k/lumen-elements/define'
enhanceLumenDateRangePickers()
</script>
<section data-ui-date-range-picker class="ui-date-range-picker">
<input class="ui-input ui-date-picker" type="date" aria-label="Start date" />
<input class="ui-input ui-date-picker" type="date" aria-label="End date" />
</section><script type="module">
import { enhanceLumenDateRangePickers } from '@santi020k/lumen-elements/define'
enhanceLumenDateRangePickers()
</script>
<section data-ui-date-range-picker class="ui-date-range-picker">
<input class="ui-input ui-date-picker" type="date" aria-label="Start date" />
<input class="ui-input ui-date-picker" type="date" aria-label="End date" />
</section>enhanceLumenInputOTPs
Enhances elements marked with [data-ui-input-otp] or <lumen-input-otp> with a real native input, visual segments, sanitized input, paste handling, and caret navigation.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for OTP fields. Defaults to document. |
| length attribute | Number of OTP segments to create. Defaults to 6. |
| value attribute | Initial value copied to the generated native input. |
| name attribute | Forwarded to the generated native input for form submission. |
Example
<script type="module">
import { enhanceLumenInputOTPs } from '@santi020k/lumen-elements/define'
enhanceLumenInputOTPs()
</script>
<lumen-input-otp
aria-label="Verification code"
length="6"
name="code"
></lumen-input-otp><script type="module">
import { enhanceLumenInputOTPs } from '@santi020k/lumen-elements/define'
enhanceLumenInputOTPs()
</script>
<lumen-input-otp
aria-label="Verification code"
length="6"
name="code"
></lumen-input-otp>enhanceLumenResizable
Enhances elements marked with [data-ui-resizable] with pane sizing, generated separator handles, pointer resizing, keyboard resizing, and double-click reset.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for resizable groups. Defaults to document. |
| data-ui-resizable-default-sizes comma-separated percentages | Initial pane sizes normalized to 100%. |
| data-ui-resizable-min-size number or comma list | Minimum pane size percentage. Defaults to 12. |
| data-ui-resizable-max-size number or comma list | Maximum pane size percentage. Defaults to 88. |
| data-orientation "horizontal" | "vertical" | Resize axis. Defaults to horizontal. |
Example
<script type="module">
import { enhanceLumenResizable } from '@santi020k/lumen-elements/define'
enhanceLumenResizable()
</script>
<lumen-resizable data-ui-resizable-default-sizes="30,70">
<aside>Navigation</aside>
<main>Editor</main>
</lumen-resizable><script type="module">
import { enhanceLumenResizable } from '@santi020k/lumen-elements/define'
enhanceLumenResizable()
</script>
<lumen-resizable data-ui-resizable-default-sizes="30,70">
<aside>Navigation</aside>
<main>Editor</main>
</lumen-resizable>enhanceLumenRichTextEditors
Enhances elements marked with [data-ui-rich-text-editor] with toolbar command execution via document.execCommand. Works without registering custom elements.
| Signature / Attribute | Description |
|---|---|
| root ParentNode (optional) | Root element to search for editors. Defaults to document. |
| data-ui-command attribute | Set on toolbar buttons to specify the command name (bold, italic, insertUnorderedList, etc.). |
Example
<script type="module">
import { enhanceLumenRichTextEditors } from '@santi020k/lumen-elements/define'
enhanceLumenRichTextEditors()
</script>
<section data-ui-rich-text-editor class="ui-rich-text-editor">
<div role="toolbar">
<button data-ui-command="bold" class="ui-button ui-button--icon">B</button>
<button data-ui-command="italic" class="ui-button ui-button--icon">I</button>
</div>
<div contenteditable data-ui-rich-text-editable>
<p>Start writing...</p>
</div>
</section><script type="module">
import { enhanceLumenRichTextEditors } from '@santi020k/lumen-elements/define'
enhanceLumenRichTextEditors()
</script>
<section data-ui-rich-text-editor class="ui-rich-text-editor">
<div role="toolbar">
<button data-ui-command="bold" class="ui-button ui-button--icon">B</button>
<button data-ui-command="italic" class="ui-button ui-button--icon">I</button>
</div>
<div contenteditable data-ui-rich-text-editable>
<p>Start writing...</p>
</div>
</section>LumenToast
Global singleton toast API available after calling defineLumenElements(). Create, update, and dismiss toast notifications from anywhere.
| Signature / Attribute | Description |
|---|---|
| create(detail) (ToastDetail) => string | Create a toast with title, description, variant, duration, placement, and optional action. Returns the toast id. |
| dismiss(id?) (string?) => void | Dismiss a toast by id, or dismiss the most recent toast. |
| update(id, detail) (string, ToastDetail) => void | Update an existing toast with new content. |
Example
<script type="module">
import { defineLumenElements, LumenToast } from '@santi020k/lumen-elements/define'
defineLumenElements()
document.querySelector('#notify').addEventListener('click', () => {
LumenToast.create({
title: 'Saved',
description: 'Your changes are live.',
variant: 'success',
duration: 5000,
placement: 'bottom-right'
})
})
</script>
<lumen-sonner aria-label="Notifications"></lumen-sonner>
<lumen-button id="notify">Show toast</lumen-button><script type="module">
import { defineLumenElements, LumenToast } from '@santi020k/lumen-elements/define'
defineLumenElements()
document.querySelector('#notify').addEventListener('click', () => {
LumenToast.create({
title: 'Saved',
description: 'Your changes are live.',
variant: 'success',
duration: 5000,
placement: 'bottom-right'
})
})
</script>
<lumen-sonner aria-label="Notifications"></lumen-sonner>
<lumen-button id="notify">Show toast</lumen-button>Custom events
Lumen elements dispatch CustomEvents that you can listen for on the document or on specific elements.
| Signature / Attribute | Description |
|---|---|
| ui:toast CustomEvent<ToastDetail> | Dispatched on document when a toast is created. Listen on document to handle toasts globally. |
| ui:validate CustomEvent<{ control, form, value }> | Dispatched during form validation for each control. |
| ui:valid CustomEvent<{ form, controls? }> | Dispatched when a form passes validation. |
| ui:invalid CustomEvent<{ form, control?, controls? }> | Dispatched when a form fails validation. |
| ui:editor-command CustomEvent<{ command }> | Dispatched when a rich text editor command is executed. |
| ui:toast-action CustomEvent<{ event?, value? }> | Dispatched when a toast action button is clicked. |
Example
<script type="module">
// Listen for toast events globally
document.addEventListener('ui:toast', (event) => {
console.log('Toast created:', event.detail.title)
})
// Listen for form validation events
document.querySelector('form').addEventListener('ui:invalid', (event) => {
console.log('Invalid controls:', event.detail.controls)
})
// Listen for rich text commands
document.addEventListener('ui:editor-command', (event) => {
console.log('Command executed:', event.detail.command)
})
</script><script type="module">
// Listen for toast events globally
document.addEventListener('ui:toast', (event) => {
console.log('Toast created:', event.detail.title)
})
// Listen for form validation events
document.querySelector('form').addEventListener('ui:invalid', (event) => {
console.log('Invalid controls:', event.detail.controls)
})
// Listen for rich text commands
document.addEventListener('ui:editor-command', (event) => {
console.log('Command executed:', event.detail.command)
})
</script>