MASTER-UI-ENGINE
Frameworks > Web Components

Web Components

Forty component modules registering 43 light-DOM custom elements — the shared sixteen plus the ported catalog entries. No build step, no runtime dependency, no shadow root — <mue-*> upgrades the markup you write and applies the same classes the vanilla previews use, so the one stylesheet styles every framework.

Name: Web Components bindings
Package: mue-web-components (frameworks/web-components)
Install: <script type="module" src="frameworks/web-components/index.js">
Runtime dependency: none (custom elements + the shared sheet)
Shadow DOM: no — light DOM, so document classes apply
Defined in: styles/components.css (classes only)
License: MIT

1 · Button

mue-button renders a real <button>. variant, size, state, block and icon map to the modifier classes in the sheet; disabled is the native attribute.

Solid

Primary Secondary Success Danger

Quiet

Outline Ghost Link

Sizes, states

Small Large Saving Disabled

2 · Input

mue-input owns the label/helper/error structure: label is joined by for/id, state="error" sets aria-invalid and points aria-describedby at the message. Emits mue-change.

3 · Textarea

mue-textarea is the same field contract as the input, plus rows.

4 · Select

mue-select upgrades the authored <option>s into a native <select>, so OS type-ahead and screen readers keep working untouched.

5 · Checkbox

mue-checkbox keeps a native input inside its own label, so Space toggles and the checked state is announced; each change emits mue-change.

I accept the MIT licence terms Email me release notes Unavailable option

6 · Radio group

mue-radio-group wraps mue-radio options in a labelled <fieldset> and shares one name, so arrow keys move the choice.

Standard · free Express · 12 USD Pickup · today

7 · Switch

mue-switch is a native checkbox given role="switch" and aria-checked; the visible track is decorative. Space flips it.

Reduce motion Beta features

8 · Card

Author children stay in the light DOM, so any markup that works in the vanilla preview works here; interactive and selected add the modifier and the aria state.

Binding

One design, several houses

The element adds markup and behaviour. It never adds a stylesheet.

A card with interactive takes role="button", so it cannot also hold a link — that nesting is a nested-interactive failure. A card that owns an action keeps it in a plain card like this one; a card that is the action uses interactive and carries no controls inside.

9 · Badge

mue-badge conveys state through text, not colour alone; the optional dot is aria-hidden.

Stable Experimental Planned

10 · Avatar

mue-avatar renders an image (keeps alt) or real-text initials; mue-avatar-group stacks them under a labelled role="group".

11 · Dialog

mue-dialog traps focus, closes on Escape and returns it to the trigger; [slot="footer"] children move into the dialog footer.

Nothing is claimed to work until the headless check has actually run against it. This dialog is that element, with its own title, close control and focus trap.

12 · Dropdown

mue-dropdown follows the menu pattern: the trigger carries aria-haspopup/aria-expanded, arrows walk the rows, and choosing one emits mue-select then closes.

13 · Tabs

mue-tabs pairs each mue-tab with the mue-tabpanel at the same index and marks its tablist data-mue-bound, so the vanilla script never double-wires it. Arrow keys move focus, Home/End jump, Enter/Space activate.

Markup Classes Tokens

The element writes the same class names the vanilla preview does.

Every class is defined in styles/components.css — the parity audit rejects any that are not.

Colour, radius, spacing and motion come from design-tokens.

14 · Accordion

mue-accordion-item triggers are real buttons with aria-expanded and aria-controls; single-open by default, add multiple for several.

No. Bindings emit classes; the single source of truth stays in styles/components.css. No. Import the index once and the tags are defined; loading it twice is harmless. No — light DOM, so document-level classes and theme tokens apply without piercing.

15 · Table

mue-table upgrades an authored <table>, wraps it in .table-wrap and sorts the columns that carry data-sort, emitting mue-sort.

Component Binding Status
Buttonmue-buttonverified
Dialogmue-dialogverified
Tabsmue-tabsverified

16 · Notification

mue-notification keeps the sheet's two shapes: a persistent alert and a toast shown by setting open, dismissed by its own button.

17 · Breadcrumbs

mue-breadcrumbs carries .breadcrumbs and its aria-label on the host itself and lays the trail out as real <a> links split by <span class="separator" aria-hidden>; the last entry becomes <span aria-current="page">. Feed it items (each Label or Label::href) or author the links as children.

Items attribute

Custom separator

Authored children

ChartsBar seriesLegend

18 · Pagination

mue-pagination carries .pagination + aria-label on the host and renders real <button> cells. The ‹ / › arrows use the native disabled attribute at the bounds, the active page carries aria-current="true", and a range wider than the window inserts <span class="ellipsis" aria-hidden>. Choosing a page emits mue-page-change.

All pages (total 5, page 2)

Windowed (total 20, page 10)

19 · Header navigation

mue-header-nav moves the authored <a class="nav-link"> children into <li class="nav-item"> inside <ul class="nav-links">, then adds the brand, a .nav-spacer, the [slot="actions"] row and a built .hamburger that toggles the sheet's drawer under 768px. It owns the toggle and the 8px scroll shadow itself, so styles/mue.js never double-wires it. A link click emits mue-navigate and closes the drawer.

20 · Navigation menu

mue-nav-menu upgrades to the sheet's .navbar and keeps an authored .dropdown working inside it: the element marks the trigger aria-haspopup/aria-expanded and the list role="menu" + aria-hidden, closes on Escape or click-outside, emits mue-select for a .menu-item and mue-navigate for a plain link.

21 · Sidebar

Three tags compose it: mue-sidebar carries .sidebar + role="complementary" and groups its children into .sidebar-section blocks, mue-sidebar-heading replaces itself with <div class="sidebar-heading"> and opens a new section, and mue-sidebar-link replaces itself with <a class="sidebar-link"> holding a decorative icon plus <span class="sidebar-label">. Clicking a link moves aria-current="page" to it and emits mue-navigate — the one behaviour the static sidebar had none of.

22 · Data table

mue-datatable takes the authored toolbar, selection bar, table and footer you write inside it — it adds no markup of its own beyond the pager cells — and wires search, sort cycling none → asc → desc with aria-sort, the status filter dropdown, row expansion into a .descriptions panel, select-all with a truthful indeterminate head checkbox, page size, refresh (the loading tbody is the sheet's skeleton cells), the empty state and the sticky .is-scrolled rule. It only ever toggles classes the sheet already defines.

Open orders, sortable, filterable and selectable
Expand row Order Actions
Kai Tanaka kai.tanaka@meridianlabs.jp ORD-98214 Paid $11,480.00
Amara Okafor amara@brightline.co ORD-98207 In transit $2,340.00
Lucas Meyer l.meyer@northwind.example ORD-98199 Disputed $8,910.50
Priya Raman priya.raman@fieldstack.io ORD-98186 Paid $460.00
Sofia Almeida sofia@harborworks.pt ORD-98175 In transit $14,200.00
Noah Berg noah.berg@fjordtech.no ORD-98163 Paid $3,125.75
Elena Rossi elena.rossi@ateliermi.it ORD-98152 Disputed $780.00
Marcus Bell marcus@northline.dev ORD-98141 Paid $649.00
Showing 0 of 0 orders

23 · Date picker

mue-date-picker owns the .field wrapper — .field-label joined by for/id, .field-helper or .field-msg, and state="error" writing .is-error + aria-invalid="true" + aria-describedby. The calendar surface is the platform's own: min/max are forwarded untouched so the browser greys out-of-range days. It emits mue-change.

24 · File upload (dropzone)

mue-dropzone renders the .dropzone target around a real <input type="file" class="dropzone-input">, labels it with an .sr-only <label>, and lists each chosen file as a .file-row (icon, .truncated name, size, remove button) in a .dropzone-list. .is-dragging is the only state class it toggles, on dragover. Choosing files emits mue-change; removing one emits mue-remove.

25 · Progress

mue-progress renders the sheet's .progress-group → .progress-label (span + .percent) → .track (role="progressbar", aria-valuenow/min/max) → .bar. Only the --value custom property is set inline, exactly as the vanilla bar does; variant and striped add .progress-success / .progress-warning / .progress-striped, and indeterminate renders the bare .progress-indeterminate track. Press Nudge build to set a new value on the first bar and watch mue-change.

26 · Skeleton

mue-skeleton sets the host to the atomic shape (.skeleton.skeleton-text|title|avatar|img|btn) or, for row and card, composes the sheet's .skeleton-row / .skeleton-body with .stack. Every placeholder is aria-hidden="true" — the shimmer and its reduced-motion pause are the sheet's.

Atomic shapes

Row (list item)

Card

27 · Empty state

mue-empty carries .empty + role="status" + aria-label on the host, paints the decorative .empty-icon, .empty-title and .empty-desc, and moves the action children you author into the sheet's .row — so the buttons stay yours and keep their focus order.

Read the docs

28 · Error state

mue-error carries .error-state + role="alert" on the host, adds .error-inline for the card variant, and paints an aria-hidden .error-icon beside an .error-body that reuses .empty-title/.empty-desc plus a .row of your recovery actions. The message is text plus an icon, never colour alone.

Copy the error

29 · Stepper

mue-stepper takes the <ol class="stepper"> you author and adds one <span class="stepper-dot" aria-hidden> per step plus the single state class the sheet knows — .is-done (check glyph), .is-current (+ aria-current="step") or .is-upcoming. current is 1-based and clamped; changing it emits mue-step. The rail itself is a status display: the wizard buttons beside it own Back / Next.

  1. AccountVerified
  2. WorkspaceName and team
  3. BindingsPick frameworks
  4. Review
Step 2 of 4

30 · Rating

mue-rating renders read-only as <p class="rating" role="img"> with an aria-label that spells the score, .rating-stars of .star.is-filled/.is-half (the half fill is the sheet's gradient) and a .rating-value. With interactive it is a real <fieldset class="rating-input"> of .rating-radio inputs plus .rating-star labels, each carrying an .sr-only name — so the arrow keys are the platform's radio-group path. Choosing a star emits mue-change.

31 · Popover

mue-popover builds <span class="popover-wrap"> around a real .popover-trigger button (aria-describedby → the surface) and moves your children into <span class="popover" role="note">, so the .popover-title/.popover-body/.popover-list markup stays yours. placement adds .popover-below/.popover-start/.popover-end. Reveal is pure CSS (:hover, :focus-within) plus the one state class .is-open it toggles on click; Escape closes it and refocuses the trigger.

Above (default)

No shadow root The elements build light-DOM children, so the document stylesheet reaches them.

Below

Three placements below, start and end each add the sheet's own class.

Start-anchored

Keeps a near-edge trigger inside the viewport.

Pinned open

Gate checks
  • Every class defined in the sheet
  • No local stylesheet
  • Zero shadow roots

32 · Modal

mue-modals renders .overlay → .modal (role="dialog", aria-modal="true", aria-labelledby) with .modal-header/.modal-title/.modal-close, your children in .modal-body and [slot="footer"] buttons in .modal-footer. A <button slot="trigger"> stays outside the overlay and gets aria-haspopup="dialog". Escape closes, Tab wraps inside the panel, focus returns to the opener, and width is the only inline property (--modal-w).

Shown on the card.

The element sets --modal-w on the panel only when the attribute is present, mirroring the vanilla page's override.

33 · Charts

mue-charts renders <figure class="chart"> with a .chart-title figcaption and an <svg viewBox="0 0 700 180" role="img"> carrying <title>/<desc> joined by aria-labelledby: bars are <rect class="bar bar-primary|bar-success|bar-warning"> over <text class="axis"> labels, a line is <polyline class="line"> with <circle class="point"> markers, and legend builds .legend / .legend-item / .legend-dot. Only the dot colour is inline, as in the vanilla page; the optional summary caption is emitted as a plain <p> because the class the vanilla page writes there (.value) is defined by no shared stylesheet.

35 · Guidance (tour + float dock)

mue-guidance keeps the surface you author inside a .tour-stage.card, adds a .row with a .btn-outline.btn-sm replay control and a .badge.badge-info status, then moves the single state class .is-open between the <span class="tour" data-step> stops you wrote — each one a .tour-target around the real control plus a .tour-card (role="dialog", .tour-arrow, .tour-step, .tour-title, .tour-body, .tour-actions). Next / Back / Skip / Finish drive it, Escape closes it, and current is 1-based. mue-fab carries .float-btn-group around the .float-btn children you author: static shows the dock in place, without it the dock gets .is-visible only past the reveal scroll threshold.

Forecast workspace — the tour spotlights each control it is talking about.

Float dock shown in place (static)

Remove static and the same dock stays hidden until the page has scrolled past reveal (420px by default).

Live events

Every custom element emits on the host with a detail payload. Clicking, typing or toggling anything above appends the real event here — nothing in this log is invented.

Waiting for interaction…
Support matrix Package README Machine-readable element registry