npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ux4g-components-web

v1.4.1

Published

UX4G Design System — CSS bundle, design tokens, utilities, and shared Class_Builder types

Readme

ux4g-components-web

CSS bundle, design tokens, utilities, shared types, and runtime module for the UX4G Design System.

This is the foundation package — it provides the complete CSS system that powers all UX4G components. Framework wrappers (ux4g-components-react, ux4g-components-angular) depend on this package for styles and Class_Builder types.

Installation

npm install ux4g-components-web

Quick Start

HTML / CSS

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="node_modules/ux4g-components-web/styles/ux4g.css" />
</head>
<body>
  <button class="ux4g-btn-primary ux4g-btn-md">Save</button>
</body>
</html>

JavaScript / TypeScript bundler

import 'ux4g-components-web/styles.css';

CSS @import

@import 'ux4g-components-web/styles.css';

Available Exports

| Export Path | Description | |---|---| | ux4g-components-web/styles.css | Pre-built CSS bundle (~7 MB, fonts embedded as base64) | | ux4g-components-web/types | Class_Builder functions and TypeScript types | | ux4g-components-web/runtime | initRuntime() / destroyRuntime() — explicit control | | ux4g-components-web/runtime/bootstrap | Side-effect import — auto-initializes runtime on import |


CSS Bundle

The bundle includes all layers in the correct cascade order:

  1. Reset — browser normalization
  2. Tokens — CSS custom properties (primitive values)
  3. Semantic — semantic aliases (--ux4g-bg-primary-strong, etc.)
  4. Foundations — fonts and icons (base64-embedded)
  5. Utilities — 27 single-purpose helper class modules
  6. Components — approved component CSS
  7. Layout — container, flex-grid, grid utilities
  8. Cascade Fixes — vendor specificity overrides

Component Examples (Plain HTML/CSS)

Button

<!-- Primary button -->
<button class="ux4g-btn-primary ux4g-btn-md">Save</button>

<!-- Outline danger, large -->
<button class="ux4g-btn-outline-danger ux4g-btn-lg">Delete</button>

<!-- Tonal primary, pill shape, small -->
<button class="ux4g-btn-tonal-primary ux4g-btn-sm ux4g-btn-pill">Tag</button>

<!-- Disabled state -->
<button class="ux4g-btn-primary ux4g-btn-md ux4g-btn-disabled" disabled>Disabled</button>

<!-- Loading state -->
<button class="ux4g-btn-primary ux4g-btn-md ux4g-btn-loading">
  <span class="ux4g-btn-spinner" aria-hidden="true"></span>
  Saving...
</button>

Available classes:

  • Variants: ux4g-btn-primary, ux4g-btn-outline-primary, ux4g-btn-text-primary, ux4g-btn-tonal-primary, ux4g-btn-danger, ux4g-btn-outline-danger, ux4g-btn-text-danger, ux4g-btn-tonal-danger
  • Sizes: ux4g-btn-xl, ux4g-btn-lg, ux4g-btn-md, ux4g-btn-sm, ux4g-btn-xs
  • Modifiers: ux4g-btn-pill, ux4g-btn-disabled, ux4g-btn-loading

Spinner

<!-- Primary full spinner, medium (default) -->
<span class="ux4g-spinner-primary-full" role="status" aria-label="Loading"></span>

<!-- Danger split spinner, large -->
<span class="ux4g-spinner-danger-split ux4g-spinner-lg" role="status" aria-label="Loading"></span>

<!-- Inverse partial spinner, extra small -->
<span class="ux4g-spinner-inverse-partial ux4g-spinner-xs" role="status" aria-label="Loading"></span>

Pattern: ux4g-spinner-{variant}-{type} + optional ux4g-spinner-{size}

  • Variants: primary, inverse, danger
  • Types: full, split, partial
  • Sizes: ux4g-spinner-xl, ux4g-spinner-lg, ux4g-spinner-sm, ux4g-spinner-xs (md is default, no class needed)

Link

<!-- Default link, medium -->
<a href="#" class="ux4g-text-link-md">Learn more</a>

<!-- Neutral link, small -->
<a href="#" class="ux4g-text-link-neutral-sm">View details</a>

Pattern: ux4g-text-link-{size} or ux4g-text-link-neutral-{size}

  • Variants: default, neutral
  • Sizes: sm, md

Badge

<!-- Dot badge, primary -->
<span class="ux4g-badge-dot-primary"></span>

<!-- Digit badge, danger, medium -->
<span class="ux4g-badge-digit-danger ux4g-badge-m">5</span>

<!-- Icon badge, success, large -->
<span class="ux4g-badge-icon-success ux4g-badge-l">
  <i class="ux4g-icon-check"></i>
</span>

Pattern: ux4g-badge-{type}-{color} + optional ux4g-badge-{size}

  • Types: dot, icon, digit
  • Colors: primary, success, warning, danger, info, secondary, tertiary, neutral
  • Sizes: s, m, l, profile-l, profile-xl, profile-2xl, profile-3xl

Avatar

<!-- Status avatar, medium -->
<div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-m">
  <img src="user.jpg" alt="User" />
</div>

<!-- Profile avatar, large -->
<div class="ux4g-avatar ux4g-avatar-profile ux4g-avatar-l">
  <img src="profile.jpg" alt="Profile" />
</div>

<!-- Avatar group -->
<div class="ux4g-avatar-group">
  <div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-s"><img src="u1.jpg" alt="" /></div>
  <div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-s"><img src="u2.jpg" alt="" /></div>
</div>

Pattern: ux4g-avatar ux4g-avatar-{type} + optional ux4g-avatar-{size}

  • Types: status, profile, group
  • Sizes: xs, s, m, l, xl, 2xl, 3xl

Image

<!-- Basic image with ratio -->
<div class="ux4g-ratio-16-9">
  <img src="photo.jpg" alt="Photo" />
</div>

<!-- Rounded image with overlay -->
<div class="ux4g-img-overlay ux4g-img-rounded ux4g-ratio-4-3">
  <img src="photo.jpg" alt="Photo" />
  <div class="ux4g-img-overlay-content">Caption</div>
</div>

Classes: ux4g-img-overlay, ux4g-img-rounded, ux4g-ratio-{ratio}

  • Ratios: 1-1, 4-3, 3-2, 16-10, 16-9, 2-1, 5-2, 3-1, 1-16, 2-3, 3-4

Chip

<!-- Filter chip, medium -->
<button class="ux4g-filter-chip-md">Category</button>

<!-- Choice chip, small, active -->
<button class="ux4g-choice-chip-sm active">Selected</button>

<!-- Input chip, extra small -->
<span class="ux4g-input-chip-xs">Tag <button class="ux4g-chip-close">&times;</button></span>

Pattern: ux4g-{type}-chip-{size} + optional active

  • Types: filter, choice, input
  • Sizes: md, sm, xs (xs only valid for input chips)

Tag

<!-- Tonal neutral tag -->
<span class="ux4g-tag-tonal-neutral">Default</span>

<!-- Filled success tag, small -->
<span class="ux4g-tag-filled-success ux4g-tag-s">Active</span>

<!-- Outline error tag -->
<span class="ux4g-tag-outline-error">Error</span>

Pattern: ux4g-tag-{variant}-{color} + optional ux4g-tag-s

  • Variants: tonal, filled, outline, text
  • Colors: neutral, brand, success, warning, error, info

Divider

<!-- Horizontal divider -->
<hr class="ux4g-divider-horizontal" />

<!-- Vertical divider -->
<div class="ux4g-divider-vertical"></div>

Breadcrumb

<!-- Breadcrumb with divider separator -->
<nav class="ux4g-breadcrumb ux4g-breadcrumb-divider">
  <a href="#">Home</a>
  <a href="#">Products</a>
  <span>Current Page</span>
</nav>

<!-- Breadcrumb with icon separator -->
<nav class="ux4g-breadcrumb ux4g-breadcrumb-icon">
  <a href="#">Home</a>
  <a href="#">Category</a>
  <span>Item</span>
</nav>

Checkbox

<!-- Medium checkbox -->
<label class="ux4g-checkbox ux4g-checkbox-md">
  <input type="checkbox" />
  <span>Accept terms</span>
</label>

<!-- Small checkbox with error -->
<label class="ux4g-checkbox ux4g-checkbox-sm ux4g-checkbox-error">
  <input type="checkbox" />
  <span>Required field</span>
</label>

Sizes: ux4g-checkbox-sm, ux4g-checkbox-md, ux4g-checkbox-lg

Radio

<!-- Medium radio -->
<label class="ux4g-radio ux4g-radio-md">
  <input type="radio" name="option" />
  <span>Option A</span>
</label>

<!-- Large radio with error -->
<label class="ux4g-radio ux4g-radio-lg ux4g-radio-error">
  <input type="radio" name="option" />
  <span>Option B</span>
</label>

Sizes: ux4g-radio-sm, ux4g-radio-md, ux4g-radio-lg

Switch

<!-- Medium switch -->
<label class="ux4g-switch ux4g-switch-md">
  <input type="checkbox" role="switch" />
  <span>Enable notifications</span>
</label>

Sizes: ux4g-switch-sm, ux4g-switch-md, ux4g-switch-lg

Card

<!-- Solid vertical card -->
<div class="ux4g-card ux4g-card-solid ux4g-card-vertical">
  <div class="ux4g-card-header">Title</div>
  <div class="ux4g-card-body">Content goes here.</div>
  <div class="ux4g-card-footer">Footer</div>
</div>

<!-- Outline horizontal card -->
<div class="ux4g-card ux4g-card-outline ux4g-card-horizontal">
  <img src="thumb.jpg" alt="" />
  <div class="ux4g-card-body">Horizontal layout</div>
</div>

Variants: ux4g-card-solid, ux4g-card-outline, ux4g-card-no-fill Layouts: ux4g-card-vertical, ux4g-card-horizontal

Input

<!-- Medium input, default state -->
<div class="ux4g-input-container ux4g-input-md ux4g-input-default">
  <label>Email</label>
  <input type="email" placeholder="Enter email" />
</div>

<!-- Large input, error state -->
<div class="ux4g-input-container ux4g-input-lg ux4g-input-error">
  <label>Password</label>
  <input type="password" />
  <span class="ux4g-input-helper">Password is required</span>
</div>

Sizes: ux4g-input-sm, ux4g-input-md, ux4g-input-lg, ux4g-input-xl States: ux4g-input-default, ux4g-input-error, ux4g-input-success, ux4g-input-warning

List

<ul class="ux4g-list ux4g-list-default ux4g-list-m">
  <li>Item one</li>
  <li>Item two</li>
  <li>Item three</li>
</ul>

Variants: ux4g-list-default, ux4g-list-error, ux4g-list-success, ux4g-list-warning Sizes: ux4g-list-s, ux4g-list-m, ux4g-list-l, ux4g-list-xl

Dropdown

<div class="ux4g-dropdown ux4g-dropdown-selection ux4g-dropdown-single ux4g-dropdown-md ux4g-dropdown-default">
  <button data-ux-toggle="dropdown" aria-expanded="false">Select option</button>
  <ul class="dropdown-menu">
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
  </ul>
</div>

Types: ux4g-dropdown-selection, ux4g-dropdown-button, ux4g-dropdown-overflow Modes: ux4g-dropdown-single, ux4g-dropdown-multi Sizes: ux4g-dropdown-sm, ux4g-dropdown-md, ux4g-dropdown-lg States: ux4g-dropdown-default, ux4g-dropdown-error, ux4g-dropdown-success, ux4g-dropdown-warning Open state: is-open

Combobox

<div class="ux4g-combobox ux4g-combobox-single ux4g-combobox-md ux4g-combobox-default">
  <input type="text" role="combobox" aria-expanded="false" placeholder="Search..." />
  <ul class="dropdown-menu" role="listbox">
    <li role="option">Result 1</li>
    <li role="option">Result 2</li>
  </ul>
</div>

Types: ux4g-combobox-single, ux4g-combobox-multi Sizes: ux4g-combobox-sm, ux4g-combobox-md, ux4g-combobox-lg States: ux4g-combobox-default, ux4g-combobox-error, ux4g-combobox-success, ux4g-combobox-warning

Modal

<!-- Trigger -->
<button data-ux-toggle="modal" data-ux-target="#myModal">Open Modal</button>

<!-- Modal -->
<div id="myModal" class="ux4g-modal-backdrop ux4g-modal-backdrop-50" role="dialog" aria-modal="true">
  <div class="ux4g-modal-box ux4g-modal-m">
    <div class="ux4g-modal-header">
      <h2>Title</h2>
      <button data-ux-dismiss="modal">&times;</button>
    </div>
    <div class="ux4g-modal-body">Content here</div>
    <div class="ux4g-modal-footer">
      <button class="ux4g-btn-primary ux4g-btn-md">Confirm</button>
    </div>
  </div>
</div>

Backdrop: ux4g-modal-backdrop-25, ux4g-modal-backdrop-50, ux4g-modal-backdrop-75 Blur: ux4g-modal-backdrop-blur Sizes: ux4g-modal-s, ux4g-modal-m, ux4g-modal-l Center content: ux4g-modal-center-content

Alert / Toast

<!-- Inline alert -->
<div class="ux4g-alert ux4g-alert-info">
  <span>This is an informational message.</span>
</div>

<!-- Context alert -->
<div class="ux4g-context-alert ux4g-alert-warning">
  <span>Warning: Check your input.</span>
</div>

<!-- Alert container (for toast positioning) -->
<div class="ux4g-alert-container ux4g-alert-top-right">
  <div class="ux4g-alert ux4g-alert-success">Saved successfully!</div>
</div>

Variants: ux4g-alert-info, ux4g-alert-success, ux4g-alert-warning, ux4g-alert-error Layouts: ux4g-alert-center, ux4g-alert-wide Positions: ux4g-alert-top-left, ux4g-alert-top-right, ux4g-alert-bottom-left, ux4g-alert-bottom-right

Search

<div class="ux4g-search-container ux4g-search-m">
  <input type="search" placeholder="Search..." />
  <button class="ux4g-search-btn" aria-label="Search">
    <i class="ux4g-icon-search"></i>
  </button>
</div>

Sizes: ux4g-search-s, ux4g-search-m, ux4g-search-lg

Pagination

<!-- Default pagination -->
<nav class="ux4g-pagination">
  <button class="ux4g-pagination-prev">&laquo;</button>
  <button class="active">1</button>
  <button>2</button>
  <button>3</button>
  <button class="ux4g-pagination-next">&raquo;</button>
</nav>

<!-- Dotted pagination, solid style -->
<nav class="ux4g-pagination ux4g-pagination-dotted ux4g-pagination-solid">
  <span class="active"></span>
  <span></span>
  <span></span>
</nav>

Variants: default, ux4g-pagination-dotted Styles (dotted only): ux4g-pagination-solid, ux4g-pagination-translucent

Table

<table class="ux4g-table ux4g-table-m">
  <thead>
    <tr><th>Name</th><th>Email</th><th>Role</th></tr>
  </thead>
  <tbody>
    <tr><td>Alice</td><td>[email protected]</td><td>Admin</td></tr>
    <tr><td>Bob</td><td>[email protected]</td><td>User</td></tr>
  </tbody>
</table>

<!-- Interactive table with zebra rows and column dividers -->
<table class="ux4g-table ux4g-table-s ux4g-table-column-dividers ux4g-table-zebra-rows ux4g-table-interactive">
  ...
</table>

Sizes: ux4g-table-s, ux4g-table-m, ux4g-table-lg Dividers: ux4g-table-column-dividers, ux4g-table-no-row-dividers Zebra: ux4g-table-zebra-rows, ux4g-table-zebra-cols Modifiers: ux4g-table-interactive, ux4g-table-sortable, ux4g-table-resizable, ux4g-table-header-brand

Popover

<button data-ux-toggle="popover" data-ux-content="Popover body text" data-ux-title="Popover Title" data-ux-placement="right">
  Show Popover
</button>

Placements: top, top-start, top-end, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end

Tooltip

<button data-ux-toggle="tooltip" data-ux-content="Tooltip text" data-ux-placement="top" title="Tooltip text">
  Hover me
</button>

Placements: top-left, top-center, top-right, bottom-left, bottom-center, bottom-right, left-center, right-center Sizes: ux4g-tooltip-s, ux4g-tooltip-xs

Tab

<div class="ux4g-tab ux4g-tab-underline ux4g-tab-md">
  <nav class="nav" role="tablist">
    <button role="tab" data-ux-toggle="tab" data-ux-target="#tab1" class="active" aria-selected="true">Tab 1</button>
    <button role="tab" data-ux-toggle="tab" data-ux-target="#tab2">Tab 2</button>
  </nav>
  <div class="tab-content">
    <div id="tab1" class="tab-pane active show">Content 1</div>
    <div id="tab2" class="tab-pane">Content 2</div>
  </div>
</div>

Variants: ux4g-tab-underline, ux4g-tab-pill Sizes: ux4g-tab-sm, ux4g-tab-md, ux4g-tab-lg Vertical: ux4g-tab-vertical

Icon Button

<button class="ux4g-icon-btn ux4g-icon-btn-primary ux4g-icon-btn-md">
  <i class="ux4g-icon-edit"></i>
</button>

<!-- Pill icon button -->
<button class="ux4g-icon-btn ux4g-icon-btn-tonal-primary ux4g-icon-btn-lg ux4g-icon-btn-pill">
  <i class="ux4g-icon-plus"></i>
</button>

Variants: ux4g-icon-btn-primary, ux4g-icon-btn-outline-primary, ux4g-icon-btn-tonal-primary, ux4g-icon-btn-text-primary Sizes: ux4g-icon-btn-xl, ux4g-icon-btn-lg, ux4g-icon-btn-md, ux4g-icon-btn-sm, ux4g-icon-btn-xs Pill: ux4g-icon-btn-pill

Accessibility Bar

<div class="ux4g-topbar">
  <a href="#main-content" class="ux4g-skip-link">Skip to main content</a>
  <!-- Additional accessibility controls -->
</div>

Accordion

<div class="ux4g-accordion ux4g-accordion-arrow-right">
  <div class="ux4g-accordion-item">
    <button data-ux-toggle="collapse" data-ux-target="#acc1" aria-expanded="false">
      Section 1
    </button>
    <div id="acc1" class="collapse">
      <div class="ux4g-accordion-body">Content for section 1</div>
    </div>
  </div>
</div>

<!-- Bordered variant with left arrow -->
<div class="ux4g-accordion ux4g-accordion-arrow-left ux4g-accordion-bordered">
  ...
</div>

Arrow position: ux4g-accordion-arrow-right, ux4g-accordion-arrow-left Variant: ux4g-accordion-bordered

Stepper

<!-- Horizontal stepper -->
<div class="ux4g-stepper">
  <div class="ux4g-stepper-step completed">Step 1</div>
  <div class="ux4g-stepper-step active">Step 2</div>
  <div class="ux4g-stepper-step">Step 3</div>
</div>

<!-- Vertical stepper, small -->
<div class="ux4g-stepper ux4g-stepper-vertical ux4g-stepper-s">
  ...
</div>

<!-- Horizontal centered with bottom-line variant -->
<div class="ux4g-stepper ux4g-stepper-horizontal ux4g-stepper-center ux4g-stepper-bottom-line">
  ...
</div>

Orientation: ux4g-stepper-vertical, ux4g-stepper-horizontal Alignment: ux4g-stepper-center, ux4g-stepper-left Variants: ux4g-stepper-bottom-line, ux4g-stepper-bottom-line-fill, ux4g-stepper-mobile, ux4g-stepper-progress Size: ux4g-stepper-s

Slider

<div class="ux4g-slider-field">
  <input type="range" min="0" max="100" value="50" />
</div>

<!-- Medium slider -->
<div class="ux4g-slider-field ux4g-slider-md">
  <input type="range" min="0" max="100" value="75" />
</div>

Sizes: default (sm), ux4g-slider-md

Drawer

<!-- Trigger -->
<button data-ux-toggle="offcanvas" data-ux-target="#drawer1">Open Drawer</button>

<!-- Drawer -->
<div id="drawer1" class="ux4g-drawer ux4g-drawer-right">
  <div class="ux4g-drawer-header">
    <h3>Drawer Title</h3>
    <button data-ux-dismiss="offcanvas">&times;</button>
  </div>
  <div class="ux4g-drawer-body">Drawer content</div>
</div>

Placements: ux4g-drawer-right, ux4g-drawer-left, ux4g-drawer-top, ux4g-drawer-bottom Open state: ux4g-drawer-open

Date-Time Picker

<!-- Date picker -->
<div class="ux4g-date-picker-container">
  <input type="date" />
</div>

<!-- Time picker -->
<div class="ux4g-time-picker-container">
  <input type="time" />
</div>

Status Pipeline

<div class="ux4g-status-pipeline-stepper">
  <div class="ux4g-status-pipeline-step completed">Submitted</div>
  <div class="ux4g-status-pipeline-step active">In Review</div>
  <div class="ux4g-status-pipeline-step">Approved</div>
</div>

<!-- Vertical status pipeline -->
<div class="ux4g-status-pipeline-stepper ux4g-status-pipeline-vertical">
  ...
</div>

Orientation: ux4g-status-pipeline-vertical, ux4g-status-pipeline-horizontal Alignment: ux4g-status-pipeline-center, ux4g-status-pipeline-left Variants: ux4g-status-pipeline-bottom-line, ux4g-status-pipeline-bottom-line-fill, ux4g-status-pipeline-mobile, ux4g-status-pipeline-progress Size: ux4g-status-pipeline-s

Journey Timeline

<!-- Vertical timeline (default) -->
<div class="ux4g-journey-timeline ux4g-journey-timeline--vertical">
  <div class="ux4g-journey-timeline-item">
    <div class="ux4g-journey-timeline-marker"></div>
    <div class="ux4g-journey-timeline-content">Event 1</div>
  </div>
</div>

<!-- Horizontal timeline -->
<div class="ux4g-journey-timeline ux4g-journey-timeline--horizontal">
  ...
</div>

Form Field Group

<div class="ux4g-form-group">
  <label>Full Name</label>
  <input type="text" class="ux4g-input-md" />
  <span class="ux4g-form-helper">Enter your full legal name</span>
</div>

OTP Input

<!-- Default OTP -->
<div class="ux4g-otp">
  <input type="text" maxlength="1" />
  <input type="text" maxlength="1" />
  <input type="text" maxlength="1" />
  <input type="text" maxlength="1" />
</div>

<!-- Error state -->
<div class="ux4g-otp ux4g-otp-error">
  ...
</div>

States: default, ux4g-otp-success, ux4g-otp-error, ux4g-otp-locked

File Upload

<div class="ux4g-upload ux4g-upload-state-default">
  <input type="file" />
  <span>Drag & drop or click to upload</span>
</div>

<!-- Uploaded state -->
<div class="ux4g-upload ux4g-upload-state-uploaded">
  <span>document.pdf</span>
  <button class="ux4g-upload-remove">&times;</button>
</div>

States: ux4g-upload-state-default, ux4g-upload-state-default-vle, ux4g-upload-state-selecting, ux4g-upload-state-scanning, ux4g-upload-state-uploaded, ux4g-upload-state-uploaded-vle, ux4g-upload-state-error

Progress Indicator

<!-- Bar progress -->
<div class="ux4g-progress-bar">
  <div class="ux4g-progress-bar-fill" style="width: 60%"></div>
</div>

<!-- Circle progress -->
<div class="ux4g-progress-circle">
  <svg><!-- circle SVG --></svg>
</div>

Types: ux4g-progress-bar, ux4g-progress-circle

Feedback

<div class="ux4g-feedback">
  <p>Was this helpful?</p>
  <button>Yes</button>
  <button>No</button>
</div>

Draft Status Banner

<!-- Default -->
<div class="ux4g-daft-staus-bar">Draft saved</div>

<!-- Auto-save variant -->
<div class="ux4g-auto-daft-staus-bar">Auto-saving...</div>

<!-- Success variant -->
<div class="ux4g-success-daft-staus-bar">Published successfully</div>

SLA Progress Indicator

<!-- Circle SLA -->
<div class="ux4g-sla-circle">
  <span>75%</span>
</div>

<!-- Linear SLA -->
<div class="ux4g-sla-linear">
  <div class="ux4g-sla-fill" style="width: 75%"></div>
</div>

<!-- Badge SLA -->
<span class="ux4g-sla-badge">On Track</span>

Types: ux4g-sla-circle, ux4g-sla-linear, ux4g-sla-badge

Carousel

<div class="ux4g-carousel" data-ux-ride="carousel">
  <div class="carousel-inner">
    <div class="carousel-item active">Slide 1</div>
    <div class="carousel-item">Slide 2</div>
    <div class="carousel-item">Slide 3</div>
  </div>
  <button data-ux-slide="prev">Prev</button>
  <button data-ux-slide="next">Next</button>
</div>

Empty State

<div class="ux4g-empty-state">
  <img src="empty-illustration.svg" alt="" />
  <h3>No results found</h3>
  <p>Try adjusting your search or filters.</p>
  <button class="ux4g-btn-primary ux4g-btn-md">Reset Filters</button>
</div>

Chip Group

<!-- Filter chip group -->
<div class="ux4g-filter-chip-group">
  <button class="ux4g-filter-chip-md active">All</button>
  <button class="ux4g-filter-chip-md">Category A</button>
  <button class="ux4g-filter-chip-md">Category B</button>
</div>

<!-- Choice chip group -->
<div class="ux4g-choice-chip-group">
  <button class="ux4g-choice-chip-md active">Option 1</button>
  <button class="ux4g-choice-chip-md">Option 2</button>
</div>

Navbar

<nav class="ux4g-navbar">
  <a href="/" class="ux4g-navbar-brand">Logo</a>
  <ul class="ux4g-navbar-nav">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

Social Links

<div class="ux4g-d-flex ux4g-gap-s">
  <a href="#" aria-label="Twitter"><i class="ux4g-icon-twitter"></i></a>
  <a href="#" aria-label="LinkedIn"><i class="ux4g-icon-linkedin"></i></a>
  <a href="#" aria-label="GitHub"><i class="ux4g-icon-github"></i></a>
</div>

Size via gap: ux4g-gap-xs (sm), ux4g-gap-s (md), ux4g-gap-m (lg)

Slot Grid

<!-- Weekly slot grid -->
<div class="ux4g-time-slot-weekly-container">
  <div class="ux4g-time-slot">9:00 AM</div>
  <div class="ux4g-time-slot">10:00 AM</div>
</div>

<!-- Compact slot grid -->
<div class="ux4g-time-slot-compact-container">
  <div class="ux4g-time-slot">9:00</div>
  <div class="ux4g-time-slot">9:30</div>
</div>

Footer

<footer class="ux4g-footer-primary">
  <div class="ux4g-footer-content">
    <p>&copy; 2024 Company Name</p>
  </div>
</footer>

Themes: default (no class), ux4g-footer-primary, ux4g-footer-dark

Result List Row

<div class="ux4g-result-list">
  <div class="ux4g-result-list-item">
    <h4>Result Title</h4>
    <p>Description text</p>
  </div>
</div>

<!-- Variation v2 -->
<div class="ux4g-result-list ux4g-result-list-v2">
  ...
</div>

Variations: default, ux4g-result-list-v1, ux4g-result-list-v2, ux4g-result-list-v3, ux4g-result-list-v4, ux4g-result-list-v5


Runtime Module

The runtime module provides interactive behaviors (dropdowns, modals, tooltips, accordions, carousels, drawers, tabs) without requiring React or Angular. It uses event delegation on document — no per-element binding needed.

Explicit Initialization (recommended for apps that need control)

import { initRuntime, destroyRuntime } from 'ux4g-components-web/runtime';

// Call once at app startup
initRuntime();

// Call for cleanup (testing, SSR teardown)
destroyRuntime();

Auto-Bootstrap (side-effect import)

import 'ux4g-components-web/runtime/bootstrap';
// Runtime is initialized immediately on import

Behaviors Provided

| Behavior | Data Attribute | Description | |---|---|---| | Dropdown | data-ux-toggle="dropdown" | Toggle dropdown menus | | Modal | data-ux-toggle="modal" | Open/close modals with escape/backdrop | | Tooltip | data-ux-toggle="tooltip" | Show/hide on hover/focus | | Popover | data-ux-toggle="popover" | Show/hide on click | | Collapse | data-ux-toggle="collapse" | Expand/collapse sections | | Tab | data-ux-toggle="tab" | Switch tab panels | | Carousel | data-ux-ride="carousel" | Auto-slide, next/prev controls | | Offcanvas/Drawer | data-ux-toggle="offcanvas" | Slide-in panels | | Toast | .toast | Auto-hide notifications | | ScrollSpy | data-ux-spy="scroll" | Highlight nav on scroll |

Design Notes

  • Singleton guard: window.__UX4G_RUNTIME_INITIALIZED__ prevents duplicate initialization
  • SSR-safe: No-ops when window/document are unavailable
  • Event delegation: All listeners attached to document
  • Cleanup: destroyRuntime() removes all listeners and resets the guard

Shared Types (Class_Builder)

Framework wrappers import Class_Builder functions from this package to map typed props to CSS class strings:

import { buildButtonClasses, ButtonVariant, ButtonSize } from 'ux4g-components-web/types';

const classes = buildButtonClasses('primary', 'md', false, false);
// → "ux4g-btn-primary ux4g-btn-md"

Custom Integrations

You can use Class_Builder functions in any framework (Vue, Svelte, vanilla JS):

import { buildCardClasses } from 'ux4g-components-web/types';
import { buildSpinnerClasses } from 'ux4g-components-web/types';

// Use in a Vue component
const cardClass = buildCardClasses('outline', 'horizontal');
// → "ux4g-card ux4g-card-outline ux4g-card-horizontal"

const spinnerClass = buildSpinnerClasses('primary', 'lg', 'full');
// → "ux4g-spinner-primary-full ux4g-spinner-lg"

Utility Classes

Use utility classes directly in HTML — no wrapper component needed:

<div class="ux4g-d-flex ux4g-gap-4 ux4g-p-m ux4g-bg-primary-soft ux4g-radius-md">
  <span class="ux4g-body-m-default ux4g-text-neutral-primary">Content</span>
</div>

Available Utility Categories (27 modules)

| Category | Modules | |---|---| | Typography & Text | typography, typescale, colors, text-transform, vertical-align | | Layout & Spacing | spacing, sizing, gap, object-fit, overflow, position, z-index, visibility, display, display-responsive | | Flexbox & Grid | flex, flex-responsive, align, justify, order | | Visual Effects | background, border, radius, shadow, opacity, blur | | Interaction | interaction |

Common Utility Examples

<!-- Flexbox layout -->
<div class="ux4g-d-flex ux4g-justify-between ux4g-align-center ux4g-gap-m">
  ...
</div>

<!-- Typography -->
<h1 class="ux4g-heading-xl-bold">Title</h1>
<p class="ux4g-body-m-default">Body text</p>

<!-- Spacing -->
<div class="ux4g-p-l ux4g-m-m">Padded and margined</div>

<!-- Background and border -->
<div class="ux4g-bg-neutral-soft ux4g-border-neutral ux4g-radius-lg ux4g-shadow-md">
  Card-like container
</div>

Dark Theme

Apply the dark theme by adding the data-theme="dark" attribute to any container or the <html> element:

<html data-theme="dark">
  <!-- All components automatically use dark tokens -->
</html>

Or scope it to a section:

<div data-theme="dark">
  <button class="ux4g-btn-primary ux4g-btn-md">Dark themed button</button>
</div>

The design tokens automatically switch values based on the data-theme attribute — no additional CSS imports needed.


Focus Ring

UX4G provides built-in focus ring styles for keyboard accessibility. Focus rings appear automatically when users navigate with the keyboard and are suppressed for mouse interactions:

<!-- Focus ring is applied automatically to interactive elements -->
<button class="ux4g-btn-primary ux4g-btn-md">Focusable</button>

<!-- Custom focus ring via utility -->
<div tabindex="0" class="ux4g-focus-ring">Custom focusable element</div>

Related Packages

License

MIT