@telperion/elements
v5.3.1
Published
Framework-agnostic web components built with Lit: Material Symbols / Simple Icons / theSVG icons, declarative client-side router, drag-and-drop primitives, details accordion with FIFO open caps, a CSS-anchored popover, a form-associated selectbox with sin
Downloads
2,303
Maintainers
Readme
@telperion/elements
A collection of custom web components built with Lit Elements. This library provides a suite of reusable, framework-independent web components for modern web applications.
✨ Features
- 🌐 Framework Independent: Built as custom web elements, works with any framework (React, Vue, Angular, Vanilla JS)
- 🔧 Custom Components: A growing collection of useful web components
- 🎨 CSS Custom Properties: Rich CSS variable support for styling
- 📦 Modular: Import only the components you need
- 🔄 Reactive: Built on Lit's reactive properties system
- 🎯 TypeScript: Full TypeScript support with type definitions
📦 Installation
npm install @telperion/elementsyarn add @telperion/elementspnpm add @telperion/elementsTailwind v4 consumers: some elements (e.g.
<tp-icon>) render Tailwind utility classes from inside the published package. Add@source "@telperion/elements";to your Tailwind entry CSS so the JIT scanner picks them up. See each module's README for details.
🚀 Usage
import '@telperion/elements';
// Use the components in your HTMLLoading via <script> tag (no bundler)
Every component module ships a self-contained, minified IIFE bundle that you can load directly from a CDN with a classic <script> tag — no bundler, no import, no npm install.
Use the explicit /iife/... path so the CDN serves the standalone bundle (subpath shorthand like /icon resolves to the ESM build via the package exports map and will not run as a classic script):
<!-- All elements registered (TelperionElements global) -->
<script src="https://unpkg.com/@telperion/elements/iife/elements.js"></script>
<!-- Or just the icon module (TelperionElements.Icon) -->
<script src="https://unpkg.com/@telperion/elements/iife/icon/index.js"></script>
<!-- Or just the router module (TelperionElements.Router) -->
<script src="https://unpkg.com/@telperion/elements/iife/router/index.js"></script>
<!-- Or just the drag-and-drop module (TelperionElements.DragDrop) -->
<script src="https://unpkg.com/@telperion/elements/iife/drag-drop/index.js"></script>
<!-- Or just the details-set module (TelperionElements.DetailsSet) -->
<script src="https://unpkg.com/@telperion/elements/iife/details-set/index.js"></script>
<!-- Or just the popover module (TelperionElements.Popover) -->
<script src="https://unpkg.com/@telperion/elements/iife/popover/index.js"></script>
<!-- Or just the select module (TelperionElements.Select) -->
<script src="https://unpkg.com/@telperion/elements/iife/select/index.js"></script>
<!-- Or just the button module (TelperionElements.Button) -->
<script src="https://unpkg.com/@telperion/elements/iife/button/index.js"></script>Each per-module bundle is fully self-contained: side-effect imports register the custom elements as soon as the script is evaluated. jsDelivr (https://cdn.jsdelivr.net/npm/@telperion/elements/iife/...) and other npm CDNs work the same way.
The package also declares a non-standard
"script"export condition pointing at these files for tooling that wants to discover them programmatically, but no browser or major CDN currently resolves it — always use the full/iife/...path in<script src>.
📚 Components
Icon
A framework-agnostic icon element with two families: Material Symbols and Simple Icons (brand icons).
Includes:
<tp-icon>— renders a single glyph from the chosen family
Features:
- Material Symbols: three variants (
outlined,round,sharp) and all four variable-font axes exposed as attributes (filled,grade,weight,optical-size) - Simple Icons (
family="simple-icons"): brand icons (YouTube, LinkedIn, GitHub, …) loaded on demand fromcdn.simpleicons.orginto a single shared<svg>sprite — one HTTP request per slug, ever; autoaria-labelfrom the brand title;tp-icon-load/tp-icon-errorevents; configurable base URL for self-hosting - theSVG (
family="thesvg"): multi-color, multi-variant brand icons from thesvg.org (~5,600 SVGs). Lazy-fetched into a separate<svg data-tp-thesvg>sprite with per-symbol id namespacing so multi-gradient logos coexist without collisions.variantattribute selectsdefault/mono/wordmark/ …;tp-icon-load/tp-icon-errorevents fire with{ slug, variant, viewBox }; configurable base URL. - Light-DOM rendering so consumer styling (Tailwind, CSS variables, color/size) "just works"
- Material Symbols fonts loaded via the Google Fonts CSS API — no broken hash URLs when Google rotates them; self-host friendly
JS/TS
import "@telperion/elements/icon";CSS
@import "@telperion/elements/icon/material-symbols.css";HTML
<tp-icon>home</tp-icon>
<tp-icon variant="round" filled weight="700">favorite</tp-icon>
<tp-icon family="simple-icons" slug="facebook" style="color:#1877F2"></tp-icon>
<tp-icon family="thesvg" slug="google" variant="wordmark"></tp-icon>Router Components
A complete client-side routing solution for single-page applications, built with declarative web components.
Includes:
<tha-router>- Main router component managing URL matching and navigation<tha-route>- Route definitions with URLPattern syntax for path matching<tha-router-outlet>- Content rendering outlet for active routes<tha-router-link>- Navigation links with automatic active state detection<tha-route-config>- Global router configuration
Features:
- Template-based routing without JavaScript configuration
- Multiple history strategies (browser, hash, memory)
- Dynamic route parameters and wildcards
- Relative path navigation
- Automatic active link detection
- Signal-based reactive updates
Details Set
A grouping element for native <details> that caps how many can be open at
once, supports cloned summary markers, and offers marker-only toggling.
Includes:
<tp-details-set>— manages direct-child<details>elements
Features:
max-open-itemsattribute — FIFO eviction when the cap is exceeded (0= unlimited)- Declarative summary markers via
<template summary-marker index="…">direct children — cloned into every direct-child<summary>at the requested splice index; multiple templates and dynamic add/remove supported - Cloned marker elements are auto-tagged with
tp-summary-markerso the native disclosure triangle is hidden and CSS can style markers state-aware (details[open] > summary > [tp-summary-marker]) toggle-on="summary" | "marker"(set-level + per-<details>override) — restrict toggling to clicks on the marker (keyboard activation always works; falls back to summary-toggle when no marker is present)tp-details-set-changeevent with{ opened, closed }arrays- Light-DOM rendering; modern CSS (
::details-content,interpolate-size) opt-in for animated open/close
JS/TS
import "@telperion/elements/details-set";HTML
<tp-details-set max-open-items="1" toggle-on="marker">
<template summary-marker index="0"><span class="chev">▸</span></template>
<details><summary>One</summary>...</details>
<details><summary>Two</summary>...</details>
</tp-details-set>Popover
Framework-agnostic popover element built on the native Popover API and CSS Anchor Positioning. Placement is pure CSS — JavaScript only parses attributes, resolves the anchor, and (optionally) wires triggers.
Includes:
<tp-popover>— auto-applies the nativepopoverattribute and anchors itself via CSS
Features:
- Auto
popoverattribute (autoby default; switch withmode="manual") - Anchor resolved from a
targetquerySelector string, falling back toparentElement - Declarative
positionsyntax with three forms:- Full:
<pop-inline> to <target-inline> / <pop-block> to <target-block> - Two-keyword:
<inline> / <block>(e.g.center / top) - Single axis or single keyword (e.g.
top to bottom,start,bottom)
- Full:
- Inline keywords:
start | center | end; block keywords:top | middle | bottom - Optional
trigger="click" | "hover"(hover also opens on focus) - Use plain CSS
marginon the popover for a gap from its anchor - Automatic edge-flipping via the default
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline(override withposition-try-fallbacks: none) - Light-DOM rendering; no JS positioning loop
JS/TS
import "@telperion/elements/popover";HTML
<div>
<button>Anchor</button>
<tp-popover position="top">Above the parent.</tp-popover>
</div>
<button id="trigger">Click me</button>
<tp-popover target="#trigger" position="start / bottom" trigger="click">
Anchored via target="#trigger".
</tp-popover>Select
Form-associated, framework-agnostic selectbox built on <tp-popover>. Single-select by default; switches to multi-select with FIFO eviction via max. Selection state is signal-backed and discoverable across nested shadow DOM boundaries via @lit/context.
Includes:
<tp-select>— the selectbox itself<tp-option>— a single selectable item<tp-selected-content>— live mirror of the current selection (used as the trigger label by default)
Features:
- Form-associated custom element with full
<form>integration viaElementInternals(name,disabled,required, reset/restore callbacks,validity) maxattribute —1for single-select, any positive integer for multi-select with FIFO eviction at the cap, orinfinitefor unbounded selection- Single-select submits a string; multi-select submits a
FormDatawith one entry per value (matching native<select multiple>) - Auto-closes the popover when a selection fills the quota; stays open while accumulating in multi-select
- Three slots:
slot="button"(replace trigger),slot="popover"(replace panel content while keeping<tp-option>children registered for selection / validation / submission), and the default slot (option list) <tp-selected-content>works anywhere in the descendant composed tree — including across shadow DOM boundaries- Signal-driven re-rendering via the
SignalWatchermixin — no manual change listeners
JS/TS
import "@telperion/elements/select";HTML
<tp-select name="fruit" required placeholder="Pick a fruit">
<tp-option value="apple">Apple</tp-option>
<tp-option value="banana">Banana</tp-option>
<tp-option value="cherry">Cherry</tp-option>
</tp-select>
<!-- Multi-select with FIFO cap of 3 -->
<tp-select name="tags" max="3">…</tp-select>
<!-- Unbounded multi-select -->
<tp-select name="tags" max="infinite">…</tp-select>Button
Framework-agnostic, form-associated button built with Lit. Behaves like the native <button> element — tab-selectable, activates on Space / Enter, and submits or resets its containing form via type="submit" / type="reset".
Includes:
<tp-button>— the button itself
Features:
- Four variants:
solid·outline·ghost·text(ghostisoutlinewithout the border) - Form-associated via
ElementInternals—type="submit"callsform.requestSubmit(),type="reset"callsform.reset(), and.formmirrorsHTMLButtonElement.form - Tab-selectable out of the box (
tabindex="0");disabledremoves the button from the tab order, blocks click/keyboard activation, and setsaria-disabled Space/Enteractivation matching native button semantics- Announces
role="button"to assistive technology through element internals - Palette-driven color via the shared
ShadeMixerLitElementmixin: pick acolortoken (primary,secondary,success, …) and tune intensity withshade(0–1000,500is the base color);mixer(none/black/white) is auto-derived fromshade - Themable design system: every palette token (
--tp-color-primary,--tp-color-success, …) is overridable at:rootor any ancestor; add brand-specific names with a single rule (tp-button[color="brand"] { --tp-element-color: …; }) - Light-DOM rendering so consumer styling (Tailwind, CSS variables, design tokens) applies directly; pure-CSS hover, focus, and active transitions
JS/TS
import "@telperion/elements/button";HTML
<tp-button>Click me</tp-button>
<tp-button variant="outline" color="success">Save</tp-button>
<tp-button variant="ghost" color="primary">Cancel</tp-button>
<tp-button variant="text" color="danger" disabled>Delete</tp-button>
<form>
<input name="email" type="email" required />
<tp-button type="submit" color="primary">Subscribe</tp-button>
<tp-button type="reset" variant="outline">Reset</tp-button>
</form>This library is actively being developed. More components will be added over time.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © Telperion Technology
