JavaScript API
Complete reference for VelinStyle's JavaScript APIs — web component methods, custom events, focus management, haptic feedback, and sanitization utilities.
Installation & Loading
VelinStyle ships its web components in three formats. Pick the one that fits your toolchain.
ES Modules (recommended)
Import individual components with tree-shaking support:
import { VelinModal, VelinTabs } from 'velinstyle/components';IIFE (global script)
Include a single script tag — all components are registered automatically:
<script src="dist/velinstyle-components.iife.js"></script>CDN
Load directly from a CDN with no build step required:
<script type="module"
src="https://unpkg.com/@birdapi/velinstyle@0.8.0/dist/velinstyle-components.min.js">
</script>Web Component APIs
Every VelinStyle web component extends HTMLElement and registers a custom element tag. The table below lists all 22 components with their programmatic methods and custom events.
| Component | Key Methods | Key Events |
|---|---|---|
<velin-modal> | open(), close() | velin-close |
<velin-drawer> | open(), close() | velin-close |
<velin-tabs> | — | velin-tab-change |
<velin-accordion> | — | — |
<velin-dropdown> | open(), close(), toggle() | — |
<velin-toast> | show({message, type, duration}) | — |
<velin-popover> | open(), close(), toggle() | — |
<velin-tooltip-wc> | — | — |
<velin-collapse> | open(), close(), toggle() | velin-open, velin-close |
<velin-carousel> | goTo(index), next(), prev() | velin-slide-change |
<velin-lightbox> | open(index), close() | velin-close |
<velin-dialog> | alert(msg, opts), confirm(msg, opts), prompt(msg, opts) | velin-dialog-close |
<velin-stepper-wc> | next(), prev(), goTo(i) | velin-step-change |
<velin-countdown> | — | velin-countdown-end |
<velin-progress-ring> | — | — |
<velin-copy> | — | velin-copied |
<velin-scroll-top> | — | — |
<velin-theme-toggle> | — | velin-theme-change |
<velin-scrollspy> | — | velin-spy-change |
<velin-persist> | clear() | velin-persist-restore, velin-persist-clear, velin-persist-error |
<velin-icon> | VelinIcon.registerProvider(name, url), VelinIcon.providers | — |
<velin-haptic> | (utility, not element) | — |
Common Attributes
Most components accept HTML attributes that map to internal properties. Changes via setAttribute() or property assignment are reflected automatically.
const modal = document.querySelector('velin-modal');
// Attribute approach
modal.setAttribute('open', '');
// Property approach (equivalent)
modal.open();Programmatic Usage Examples
Common patterns for interacting with VelinStyle components from JavaScript.
Modal
const modal = document.querySelector('velin-modal');
// Open programmatically
modal.open();
// Listen for close
modal.addEventListener('velin-close', () => {
console.log('Modal closed');
});Toast Notifications
const toast = document.querySelector('velin-toast');
// Success toast
toast.show({
message: 'Saved!',
type: 'success',
duration: 3000
});
// Error toast
toast.show({
message: 'Something went wrong.',
type: 'error',
duration: 5000
});Dialog with Promises
const dialog = document.querySelector('velin-dialog');
// Alert
await dialog.alert('File uploaded successfully.');
// Confirm with danger styling
const confirmed = await dialog.confirm('Delete this item?', {
danger: true
});
if (confirmed) {
deleteItem();
}
// Prompt for input
const name = await dialog.prompt('Enter your name:', {
placeholder: 'John Doe'
});
if (name !== null) {
updateName(name);
}Carousel Navigation
const carousel = document.querySelector('velin-carousel');
carousel.next();
carousel.prev();
carousel.goTo(2);
carousel.addEventListener('velin-slide-change', (e) => {
console.log('Active slide:', e.detail.index);
});Custom Icon Provider
// Register a custom icon provider
VelinIcon.registerProvider('myicons',
'https://cdn.example.com/icons/{name}.svg'
);
// List all registered providers
console.log(VelinIcon.providers);
// Use in HTML: <velin-icon provider="myicons" name="star"></velin-icon>Stepper Control
const stepper = document.querySelector('velin-stepper-wc');
stepper.next();
stepper.prev();
stepper.goTo(0);
stepper.addEventListener('velin-step-change', (e) => {
console.log('Step:', e.detail.step);
});Persist & Restore State
const persist = document.querySelector('velin-persist');
persist.addEventListener('velin-persist-restore', (e) => {
console.log('State restored:', e.detail);
});
persist.addEventListener('velin-persist-error', (e) => {
console.error('Persist error:', e.detail.error);
});
// Clear all persisted state
persist.clear();Focus Management API
VelinStyle includes a set of focus-management utilities used internally by modal, drawer, and dialog components. You can import and use them directly for custom components or advanced layouts.
import {
trapFocus,
rovingTabindex,
saveFocus,
restoreFocus,
getFocusableElements,
setBackgroundInert,
clearBackgroundInert
} from 'velinstyle/components';| Function | Signature | Description |
|---|---|---|
trapFocus |
trapFocus(shadowRoot, event) |
Traps keyboard focus within a container (e.g. a modal's shadow root). Call from a keydown handler — it prevents Tab from leaving the boundary. |
rovingTabindex |
rovingTabindex(container, selector) |
Enables arrow-key navigation between elements matching selector inside container. Used by tabs, toolbars, and menu components. |
saveFocus |
saveFocus() |
Captures the currently focused element and returns a reference token. Call before opening an overlay. |
restoreFocus |
restoreFocus(saved) |
Returns focus to the element captured by saveFocus(). Call after closing an overlay. |
getFocusableElements |
getFocusableElements(root) |
Returns an array of all focusable elements (buttons, inputs, links, etc.) within the given root node. |
setBackgroundInert |
setBackgroundInert(exceptEl) |
Marks sibling nodes of the overlay with inert (0.7.0) — used by modal/drawer. |
clearBackgroundInert |
clearBackgroundInert() |
Removes inert applied by setBackgroundInert. |
Example: Custom Focus Trap
import { trapFocus, saveFocus, restoreFocus } from 'velinstyle/components';
const panel = document.getElementById('custom-panel');
let savedFocus;
function openPanel() {
savedFocus = saveFocus();
panel.hidden = false;
panel.addEventListener('keydown', (e) => trapFocus(panel, e));
panel.querySelector('button').focus();
}
function closePanel() {
panel.hidden = true;
restoreFocus(savedFocus);
}Haptic API
The Haptic API provides vibration feedback on supported devices (mobile browsers with the Vibration API). It degrades gracefully — calling haptic functions on unsupported devices is a no-op.
import { vibrate, applyHaptic, VelinHapticObserver } from 'velinstyle/components';| Export | Description |
|---|---|
vibrate(pattern) |
Trigger a vibration using a named pattern or a custom array of durations in milliseconds. |
applyHaptic(element) |
Binds haptic feedback to an element — vibrates on click/tap using the element's haptic attribute value as the pattern. |
VelinHapticObserver |
A MutationObserver-based class that automatically discovers and activates all elements with a [haptic] attribute in the DOM. |
Built-in Patterns
| Pattern Name | Duration (ms) | Use Case |
|---|---|---|
tap | [10] | Button press, link tap |
double-tap | [10, 50, 10] | Double-tap action |
success | [10, 30, 20] | Form submit, save confirmation |
error | [30, 50, 30, 50, 30] | Validation error, failed action |
warning | [20, 40, 20] | Caution, warning dialogs |
long | [50] | Long-press feedback |
Example: Programmatic & Declarative
import { vibrate, applyHaptic, VelinHapticObserver } from 'velinstyle/components';
// Programmatic: trigger on form submit
document.querySelector('form').addEventListener('submit', () => {
vibrate('success');
});
// Bind to a specific element
const btn = document.querySelector('#delete-btn');
applyHaptic(btn); // uses btn's haptic="error" attribute
// Auto-observe all [haptic] elements in the document
const observer = new VelinHapticObserver(document.body);
observer.observe();Declarative usage via HTML attributes:
<button class="velin-btn velin-btn-primary" haptic="tap">Save</button>
<button class="velin-btn velin-btn-danger" haptic="error">Delete</button>
<a href="/next" haptic="double-tap">Continue</a>Sanitization API
Security-focused utilities used internally by VelinStyle components. Available for use in your own code to prevent XSS and injection attacks.
import { escapeHTML, sanitizeURL, getTrustedPolicy } from 'velinstyle/components';| Function | Signature | Description |
|---|---|---|
escapeHTML |
escapeHTML(str: string): string |
Escapes &, <, >, ", and ' to their HTML entity equivalents. Use when inserting user-provided text into the DOM. |
sanitizeURL |
sanitizeURL(url: string): string |
Validates and sanitizes a URL. Rejects javascript:, data:, and vbscript: protocols — returns an empty string for unsafe inputs. |
getTrustedPolicy |
getTrustedPolicy(): TrustedTypePolicy | null |
Returns VelinStyle's Trusted Types policy if the browser supports it, or null otherwise. Used internally for safe innerHTML assignments. |
Example: Safe DOM Insertion
import { escapeHTML, sanitizeURL } from 'velinstyle/components';
// Safe text insertion
const userInput = '<img src=x onerror=alert(1)>';
el.innerHTML = escapeHTML(userInput);
// Output: <img src=x onerror=alert(1)>
// Safe URL handling
const url = sanitizeURL('javascript:alert(1)');
// Returns '' (empty string — blocked)
const safeUrl = sanitizeURL('https://example.com');
// Returns 'https://example.com'TypeScript Support
VelinStyle ships with full TypeScript declarations. All component classes, events, and utility functions are typed.
import type { VelinModal, VelinDialog, VelinToast } from 'velinstyle';
const modal = document.querySelector('velin-modal') as VelinModal;
modal.open();
const dialog = document.querySelector('velin-dialog') as VelinDialog;
const confirmed: boolean = await dialog.confirm('Proceed?');Augmenting HTMLElementTagNameMap
VelinStyle automatically augments the global HTMLElementTagNameMap interface, giving you type-safe querySelector results:
// No cast needed — TypeScript knows the return type
const tabs = document.querySelector('velin-tabs');
// tabs is VelinTabs | null
tabs?.addEventListener('velin-tab-change', (e) => {
// e.detail is fully typed
console.log(e.detail.index, e.detail.tab);
});Custom Event Types
import type { VelinTabChangeEvent, VelinCloseEvent } from 'velinstyle';
document.addEventListener('velin-tab-change', (e: VelinTabChangeEvent) => {
console.log(e.detail.index);
});
document.addEventListener('velin-close', (e: VelinCloseEvent) => {
console.log('Component closed:', e.target);
});