ux4g-components-web 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ux4g-components-web
2
2
 
3
- The CSS system, design tokens, utilities, and shared Class_Builder types for the UX4G Design System.
3
+ CSS bundle, design tokens, utilities, shared types, and runtime module for the **UX4G Design System**.
4
+
5
+ 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.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,38 +10,962 @@ The CSS system, design tokens, utilities, and shared Class_Builder types for the
8
10
  npm install ux4g-components-web
9
11
  ```
10
12
 
11
- ## Usage
13
+ ## Quick Start
14
+
15
+ ### HTML / CSS
12
16
 
13
- ### CSS Bundle
17
+ ```html
18
+ <!DOCTYPE html>
19
+ <html>
20
+ <head>
21
+ <link rel="stylesheet" href="node_modules/ux4g-components-web/styles/ux4g.css" />
22
+ </head>
23
+ <body>
24
+ <button class="ux4g-btn-primary ux4g-btn-md">Save</button>
25
+ </body>
26
+ </html>
27
+ ```
14
28
 
15
- Import the full CSS bundle in your application entry point:
29
+ ### JavaScript / TypeScript bundler
16
30
 
17
31
  ```ts
18
- // JavaScript/TypeScript
19
32
  import 'ux4g-components-web/styles.css';
20
33
  ```
21
34
 
22
- ```html
23
- <!-- HTML -->
24
- <link rel="stylesheet" href="node_modules/ux4g-components-web/styles/ux4g.css" />
25
- ```
35
+ ### CSS @import
26
36
 
27
37
  ```css
28
- /* CSS */
29
38
  @import 'ux4g-components-web/styles.css';
30
39
  ```
31
40
 
32
- The bundle includes:
33
- - Design tokens (CSS custom properties)
34
- - Semantic layer (semantic aliases)
35
- - All 27 utility modules
36
- - Approved component CSS
37
- - Layout utilities
38
- - Cascade fixes
41
+ ---
42
+
43
+ ## Available Exports
44
+
45
+ | Export Path | Description |
46
+ |---|---|
47
+ | `ux4g-components-web/styles.css` | Pre-built CSS bundle (~7 MB, fonts embedded as base64) |
48
+ | `ux4g-components-web/types` | Class_Builder functions and TypeScript types |
49
+ | `ux4g-components-web/runtime` | `initRuntime()` / `destroyRuntime()` — explicit control |
50
+ | `ux4g-components-web/runtime/bootstrap` | Side-effect import — auto-initializes runtime on import |
51
+
52
+ ---
53
+
54
+ ## CSS Bundle
55
+
56
+ The bundle includes all layers in the correct cascade order:
57
+
58
+ 1. **Reset** — browser normalization
59
+ 2. **Tokens** — CSS custom properties (primitive values)
60
+ 3. **Semantic** — semantic aliases (`--ux4g-bg-primary-strong`, etc.)
61
+ 4. **Foundations** — fonts and icons (base64-embedded)
62
+ 5. **Utilities** — 27 single-purpose helper class modules
63
+ 6. **Components** — approved component CSS
64
+ 7. **Layout** — container, flex-grid, grid utilities
65
+ 8. **Cascade Fixes** — vendor specificity overrides
66
+
67
+ ---
68
+
69
+ ## Component Examples (Plain HTML/CSS)
70
+
71
+ ### Button
72
+
73
+ ```html
74
+ <!-- Primary button -->
75
+ <button class="ux4g-btn-primary ux4g-btn-md">Save</button>
76
+
77
+ <!-- Outline danger, large -->
78
+ <button class="ux4g-btn-outline-danger ux4g-btn-lg">Delete</button>
79
+
80
+ <!-- Tonal primary, pill shape, small -->
81
+ <button class="ux4g-btn-tonal-primary ux4g-btn-sm ux4g-btn-pill">Tag</button>
82
+
83
+ <!-- Disabled state -->
84
+ <button class="ux4g-btn-primary ux4g-btn-md ux4g-btn-disabled" disabled>Disabled</button>
85
+
86
+ <!-- Loading state -->
87
+ <button class="ux4g-btn-primary ux4g-btn-md ux4g-btn-loading">
88
+ <span class="ux4g-btn-spinner" aria-hidden="true"></span>
89
+ Saving...
90
+ </button>
91
+ ```
92
+
93
+ **Available classes:**
94
+ - 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`
95
+ - Sizes: `ux4g-btn-xl`, `ux4g-btn-lg`, `ux4g-btn-md`, `ux4g-btn-sm`, `ux4g-btn-xs`
96
+ - Modifiers: `ux4g-btn-pill`, `ux4g-btn-disabled`, `ux4g-btn-loading`
97
+
98
+
99
+ ### Spinner
100
+
101
+ ```html
102
+ <!-- Primary full spinner, medium (default) -->
103
+ <span class="ux4g-spinner-primary-full" role="status" aria-label="Loading"></span>
104
+
105
+ <!-- Danger split spinner, large -->
106
+ <span class="ux4g-spinner-danger-split ux4g-spinner-lg" role="status" aria-label="Loading"></span>
107
+
108
+ <!-- Inverse partial spinner, extra small -->
109
+ <span class="ux4g-spinner-inverse-partial ux4g-spinner-xs" role="status" aria-label="Loading"></span>
110
+ ```
111
+
112
+ **Pattern:** `ux4g-spinner-{variant}-{type}` + optional `ux4g-spinner-{size}`
113
+ - Variants: `primary`, `inverse`, `danger`
114
+ - Types: `full`, `split`, `partial`
115
+ - Sizes: `ux4g-spinner-xl`, `ux4g-spinner-lg`, `ux4g-spinner-sm`, `ux4g-spinner-xs` (md is default, no class needed)
116
+
117
+ ### Link
118
+
119
+ ```html
120
+ <!-- Default link, medium -->
121
+ <a href="#" class="ux4g-text-link-md">Learn more</a>
122
+
123
+ <!-- Neutral link, small -->
124
+ <a href="#" class="ux4g-text-link-neutral-sm">View details</a>
125
+ ```
126
+
127
+ **Pattern:** `ux4g-text-link-{size}` or `ux4g-text-link-neutral-{size}`
128
+ - Variants: `default`, `neutral`
129
+ - Sizes: `sm`, `md`
130
+
131
+ ### Badge
132
+
133
+ ```html
134
+ <!-- Dot badge, primary -->
135
+ <span class="ux4g-badge-dot-primary"></span>
136
+
137
+ <!-- Digit badge, danger, medium -->
138
+ <span class="ux4g-badge-digit-danger ux4g-badge-m">5</span>
139
+
140
+ <!-- Icon badge, success, large -->
141
+ <span class="ux4g-badge-icon-success ux4g-badge-l">
142
+ <i class="ux4g-icon-check"></i>
143
+ </span>
144
+ ```
145
+
146
+ **Pattern:** `ux4g-badge-{type}-{color}` + optional `ux4g-badge-{size}`
147
+ - Types: `dot`, `icon`, `digit`
148
+ - Colors: `primary`, `success`, `warning`, `danger`, `info`, `secondary`, `tertiary`, `neutral`
149
+ - Sizes: `s`, `m`, `l`, `profile-l`, `profile-xl`, `profile-2xl`, `profile-3xl`
150
+
151
+ ### Avatar
152
+
153
+ ```html
154
+ <!-- Status avatar, medium -->
155
+ <div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-m">
156
+ <img src="user.jpg" alt="User" />
157
+ </div>
158
+
159
+ <!-- Profile avatar, large -->
160
+ <div class="ux4g-avatar ux4g-avatar-profile ux4g-avatar-l">
161
+ <img src="profile.jpg" alt="Profile" />
162
+ </div>
163
+
164
+ <!-- Avatar group -->
165
+ <div class="ux4g-avatar-group">
166
+ <div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-s"><img src="u1.jpg" alt="" /></div>
167
+ <div class="ux4g-avatar ux4g-avatar-status ux4g-avatar-s"><img src="u2.jpg" alt="" /></div>
168
+ </div>
169
+ ```
170
+
171
+ **Pattern:** `ux4g-avatar ux4g-avatar-{type}` + optional `ux4g-avatar-{size}`
172
+ - Types: `status`, `profile`, `group`
173
+ - Sizes: `xs`, `s`, `m`, `l`, `xl`, `2xl`, `3xl`
174
+
175
+ ### Image
176
+
177
+ ```html
178
+ <!-- Basic image with ratio -->
179
+ <div class="ux4g-ratio-16-9">
180
+ <img src="photo.jpg" alt="Photo" />
181
+ </div>
182
+
183
+ <!-- Rounded image with overlay -->
184
+ <div class="ux4g-img-overlay ux4g-img-rounded ux4g-ratio-4-3">
185
+ <img src="photo.jpg" alt="Photo" />
186
+ <div class="ux4g-img-overlay-content">Caption</div>
187
+ </div>
188
+ ```
189
+
190
+ **Classes:** `ux4g-img-overlay`, `ux4g-img-rounded`, `ux4g-ratio-{ratio}`
191
+ - Ratios: `1-1`, `4-3`, `3-2`, `16-10`, `16-9`, `2-1`, `5-2`, `3-1`, `1-16`, `2-3`, `3-4`
192
+
193
+ ### Chip
194
+
195
+ ```html
196
+ <!-- Filter chip, medium -->
197
+ <button class="ux4g-filter-chip-md">Category</button>
198
+
199
+ <!-- Choice chip, small, active -->
200
+ <button class="ux4g-choice-chip-sm active">Selected</button>
201
+
202
+ <!-- Input chip, extra small -->
203
+ <span class="ux4g-input-chip-xs">Tag <button class="ux4g-chip-close">&times;</button></span>
204
+ ```
205
+
206
+ **Pattern:** `ux4g-{type}-chip-{size}` + optional `active`
207
+ - Types: `filter`, `choice`, `input`
208
+ - Sizes: `md`, `sm`, `xs` (xs only valid for input chips)
209
+
210
+ ### Tag
211
+
212
+ ```html
213
+ <!-- Tonal neutral tag -->
214
+ <span class="ux4g-tag-tonal-neutral">Default</span>
215
+
216
+ <!-- Filled success tag, small -->
217
+ <span class="ux4g-tag-filled-success ux4g-tag-s">Active</span>
218
+
219
+ <!-- Outline error tag -->
220
+ <span class="ux4g-tag-outline-error">Error</span>
221
+ ```
222
+
223
+ **Pattern:** `ux4g-tag-{variant}-{color}` + optional `ux4g-tag-s`
224
+ - Variants: `tonal`, `filled`, `outline`, `text`
225
+ - Colors: `neutral`, `brand`, `success`, `warning`, `error`, `info`
226
+
227
+ ### Divider
228
+
229
+ ```html
230
+ <!-- Horizontal divider -->
231
+ <hr class="ux4g-divider-horizontal" />
232
+
233
+ <!-- Vertical divider -->
234
+ <div class="ux4g-divider-vertical"></div>
235
+ ```
236
+
237
+ ### Breadcrumb
238
+
239
+ ```html
240
+ <!-- Breadcrumb with divider separator -->
241
+ <nav class="ux4g-breadcrumb ux4g-breadcrumb-divider">
242
+ <a href="#">Home</a>
243
+ <a href="#">Products</a>
244
+ <span>Current Page</span>
245
+ </nav>
246
+
247
+ <!-- Breadcrumb with icon separator -->
248
+ <nav class="ux4g-breadcrumb ux4g-breadcrumb-icon">
249
+ <a href="#">Home</a>
250
+ <a href="#">Category</a>
251
+ <span>Item</span>
252
+ </nav>
253
+ ```
254
+
255
+ ### Checkbox
256
+
257
+ ```html
258
+ <!-- Medium checkbox -->
259
+ <label class="ux4g-checkbox ux4g-checkbox-md">
260
+ <input type="checkbox" />
261
+ <span>Accept terms</span>
262
+ </label>
263
+
264
+ <!-- Small checkbox with error -->
265
+ <label class="ux4g-checkbox ux4g-checkbox-sm ux4g-checkbox-error">
266
+ <input type="checkbox" />
267
+ <span>Required field</span>
268
+ </label>
269
+ ```
270
+
271
+ **Sizes:** `ux4g-checkbox-sm`, `ux4g-checkbox-md`, `ux4g-checkbox-lg`
272
+
273
+ ### Radio
274
+
275
+ ```html
276
+ <!-- Medium radio -->
277
+ <label class="ux4g-radio ux4g-radio-md">
278
+ <input type="radio" name="option" />
279
+ <span>Option A</span>
280
+ </label>
281
+
282
+ <!-- Large radio with error -->
283
+ <label class="ux4g-radio ux4g-radio-lg ux4g-radio-error">
284
+ <input type="radio" name="option" />
285
+ <span>Option B</span>
286
+ </label>
287
+ ```
288
+
289
+ **Sizes:** `ux4g-radio-sm`, `ux4g-radio-md`, `ux4g-radio-lg`
290
+
291
+ ### Switch
292
+
293
+ ```html
294
+ <!-- Medium switch -->
295
+ <label class="ux4g-switch ux4g-switch-md">
296
+ <input type="checkbox" role="switch" />
297
+ <span>Enable notifications</span>
298
+ </label>
299
+ ```
300
+
301
+ **Sizes:** `ux4g-switch-sm`, `ux4g-switch-md`, `ux4g-switch-lg`
302
+
303
+ ### Card
304
+
305
+ ```html
306
+ <!-- Solid vertical card -->
307
+ <div class="ux4g-card ux4g-card-solid ux4g-card-vertical">
308
+ <div class="ux4g-card-header">Title</div>
309
+ <div class="ux4g-card-body">Content goes here.</div>
310
+ <div class="ux4g-card-footer">Footer</div>
311
+ </div>
312
+
313
+ <!-- Outline horizontal card -->
314
+ <div class="ux4g-card ux4g-card-outline ux4g-card-horizontal">
315
+ <img src="thumb.jpg" alt="" />
316
+ <div class="ux4g-card-body">Horizontal layout</div>
317
+ </div>
318
+ ```
319
+
320
+ **Variants:** `ux4g-card-solid`, `ux4g-card-outline`, `ux4g-card-no-fill`
321
+ **Layouts:** `ux4g-card-vertical`, `ux4g-card-horizontal`
322
+
323
+ ### Input
324
+
325
+ ```html
326
+ <!-- Medium input, default state -->
327
+ <div class="ux4g-input-container ux4g-input-md ux4g-input-default">
328
+ <label>Email</label>
329
+ <input type="email" placeholder="Enter email" />
330
+ </div>
331
+
332
+ <!-- Large input, error state -->
333
+ <div class="ux4g-input-container ux4g-input-lg ux4g-input-error">
334
+ <label>Password</label>
335
+ <input type="password" />
336
+ <span class="ux4g-input-helper">Password is required</span>
337
+ </div>
338
+ ```
339
+
340
+ **Sizes:** `ux4g-input-sm`, `ux4g-input-md`, `ux4g-input-lg`, `ux4g-input-xl`
341
+ **States:** `ux4g-input-default`, `ux4g-input-error`, `ux4g-input-success`, `ux4g-input-warning`
342
+
343
+ ### List
344
+
345
+ ```html
346
+ <ul class="ux4g-list ux4g-list-default ux4g-list-m">
347
+ <li>Item one</li>
348
+ <li>Item two</li>
349
+ <li>Item three</li>
350
+ </ul>
351
+ ```
352
+
353
+ **Variants:** `ux4g-list-default`, `ux4g-list-error`, `ux4g-list-success`, `ux4g-list-warning`
354
+ **Sizes:** `ux4g-list-s`, `ux4g-list-m`, `ux4g-list-l`, `ux4g-list-xl`
355
+
356
+ ### Dropdown
357
+
358
+ ```html
359
+ <div class="ux4g-dropdown ux4g-dropdown-selection ux4g-dropdown-single ux4g-dropdown-md ux4g-dropdown-default">
360
+ <button data-ux-toggle="dropdown" aria-expanded="false">Select option</button>
361
+ <ul class="dropdown-menu">
362
+ <li>Option 1</li>
363
+ <li>Option 2</li>
364
+ <li>Option 3</li>
365
+ </ul>
366
+ </div>
367
+ ```
368
+
369
+ **Types:** `ux4g-dropdown-selection`, `ux4g-dropdown-button`, `ux4g-dropdown-overflow`
370
+ **Modes:** `ux4g-dropdown-single`, `ux4g-dropdown-multi`
371
+ **Sizes:** `ux4g-dropdown-sm`, `ux4g-dropdown-md`, `ux4g-dropdown-lg`
372
+ **States:** `ux4g-dropdown-default`, `ux4g-dropdown-error`, `ux4g-dropdown-success`, `ux4g-dropdown-warning`
373
+ **Open state:** `is-open`
374
+
375
+ ### Combobox
376
+
377
+ ```html
378
+ <div class="ux4g-combobox ux4g-combobox-single ux4g-combobox-md ux4g-combobox-default">
379
+ <input type="text" role="combobox" aria-expanded="false" placeholder="Search..." />
380
+ <ul class="dropdown-menu" role="listbox">
381
+ <li role="option">Result 1</li>
382
+ <li role="option">Result 2</li>
383
+ </ul>
384
+ </div>
385
+ ```
386
+
387
+ **Types:** `ux4g-combobox-single`, `ux4g-combobox-multi`
388
+ **Sizes:** `ux4g-combobox-sm`, `ux4g-combobox-md`, `ux4g-combobox-lg`
389
+ **States:** `ux4g-combobox-default`, `ux4g-combobox-error`, `ux4g-combobox-success`, `ux4g-combobox-warning`
390
+
391
+ ### Modal
392
+
393
+ ```html
394
+ <!-- Trigger -->
395
+ <button data-ux-toggle="modal" data-ux-target="#myModal">Open Modal</button>
396
+
397
+ <!-- Modal -->
398
+ <div id="myModal" class="ux4g-modal-backdrop ux4g-modal-backdrop-50" role="dialog" aria-modal="true">
399
+ <div class="ux4g-modal-box ux4g-modal-m">
400
+ <div class="ux4g-modal-header">
401
+ <h2>Title</h2>
402
+ <button data-ux-dismiss="modal">&times;</button>
403
+ </div>
404
+ <div class="ux4g-modal-body">Content here</div>
405
+ <div class="ux4g-modal-footer">
406
+ <button class="ux4g-btn-primary ux4g-btn-md">Confirm</button>
407
+ </div>
408
+ </div>
409
+ </div>
410
+ ```
411
+
412
+ **Backdrop:** `ux4g-modal-backdrop-25`, `ux4g-modal-backdrop-50`, `ux4g-modal-backdrop-75`
413
+ **Blur:** `ux4g-modal-backdrop-blur`
414
+ **Sizes:** `ux4g-modal-s`, `ux4g-modal-m`, `ux4g-modal-l`
415
+ **Center content:** `ux4g-modal-center-content`
416
+
417
+ ### Alert / Toast
418
+
419
+ ```html
420
+ <!-- Inline alert -->
421
+ <div class="ux4g-alert ux4g-alert-info">
422
+ <span>This is an informational message.</span>
423
+ </div>
424
+
425
+ <!-- Context alert -->
426
+ <div class="ux4g-context-alert ux4g-alert-warning">
427
+ <span>Warning: Check your input.</span>
428
+ </div>
429
+
430
+ <!-- Alert container (for toast positioning) -->
431
+ <div class="ux4g-alert-container ux4g-alert-top-right">
432
+ <div class="ux4g-alert ux4g-alert-success">Saved successfully!</div>
433
+ </div>
434
+ ```
435
+
436
+ **Variants:** `ux4g-alert-info`, `ux4g-alert-success`, `ux4g-alert-warning`, `ux4g-alert-error`
437
+ **Layouts:** `ux4g-alert-center`, `ux4g-alert-wide`
438
+ **Positions:** `ux4g-alert-top-left`, `ux4g-alert-top-right`, `ux4g-alert-bottom-left`, `ux4g-alert-bottom-right`
439
+
440
+ ### Search
441
+
442
+ ```html
443
+ <div class="ux4g-search-container ux4g-search-m">
444
+ <input type="search" placeholder="Search..." />
445
+ <button class="ux4g-search-btn" aria-label="Search">
446
+ <i class="ux4g-icon-search"></i>
447
+ </button>
448
+ </div>
449
+ ```
450
+
451
+ **Sizes:** `ux4g-search-s`, `ux4g-search-m`, `ux4g-search-lg`
452
+
453
+ ### Pagination
454
+
455
+ ```html
456
+ <!-- Default pagination -->
457
+ <nav class="ux4g-pagination">
458
+ <button class="ux4g-pagination-prev">&laquo;</button>
459
+ <button class="active">1</button>
460
+ <button>2</button>
461
+ <button>3</button>
462
+ <button class="ux4g-pagination-next">&raquo;</button>
463
+ </nav>
464
+
465
+ <!-- Dotted pagination, solid style -->
466
+ <nav class="ux4g-pagination ux4g-pagination-dotted ux4g-pagination-solid">
467
+ <span class="active"></span>
468
+ <span></span>
469
+ <span></span>
470
+ </nav>
471
+ ```
472
+
473
+ **Variants:** default, `ux4g-pagination-dotted`
474
+ **Styles (dotted only):** `ux4g-pagination-solid`, `ux4g-pagination-translucent`
475
+
476
+ ### Table
477
+
478
+ ```html
479
+ <table class="ux4g-table ux4g-table-m">
480
+ <thead>
481
+ <tr><th>Name</th><th>Email</th><th>Role</th></tr>
482
+ </thead>
483
+ <tbody>
484
+ <tr><td>Alice</td><td>alice@example.com</td><td>Admin</td></tr>
485
+ <tr><td>Bob</td><td>bob@example.com</td><td>User</td></tr>
486
+ </tbody>
487
+ </table>
488
+
489
+ <!-- Interactive table with zebra rows and column dividers -->
490
+ <table class="ux4g-table ux4g-table-s ux4g-table-column-dividers ux4g-table-zebra-rows ux4g-table-interactive">
491
+ ...
492
+ </table>
493
+ ```
494
+
495
+ **Sizes:** `ux4g-table-s`, `ux4g-table-m`, `ux4g-table-lg`
496
+ **Dividers:** `ux4g-table-column-dividers`, `ux4g-table-no-row-dividers`
497
+ **Zebra:** `ux4g-table-zebra-rows`, `ux4g-table-zebra-cols`
498
+ **Modifiers:** `ux4g-table-interactive`, `ux4g-table-sortable`, `ux4g-table-resizable`, `ux4g-table-header-brand`
499
+
500
+ ### Popover
501
+
502
+ ```html
503
+ <button data-ux-toggle="popover" data-ux-content="Popover body text" data-ux-title="Popover Title" data-ux-placement="right">
504
+ Show Popover
505
+ </button>
506
+ ```
507
+
508
+ **Placements:** `top`, `top-start`, `top-end`, `bottom`, `bottom-start`, `bottom-end`, `left`, `left-start`, `left-end`, `right`, `right-start`, `right-end`
509
+
510
+ ### Tooltip
511
+
512
+ ```html
513
+ <button data-ux-toggle="tooltip" data-ux-content="Tooltip text" data-ux-placement="top" title="Tooltip text">
514
+ Hover me
515
+ </button>
516
+ ```
517
+
518
+ **Placements:** `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right`, `left-center`, `right-center`
519
+ **Sizes:** `ux4g-tooltip-s`, `ux4g-tooltip-xs`
520
+
521
+ ### Tab
522
+
523
+ ```html
524
+ <div class="ux4g-tab ux4g-tab-underline ux4g-tab-md">
525
+ <nav class="nav" role="tablist">
526
+ <button role="tab" data-ux-toggle="tab" data-ux-target="#tab1" class="active" aria-selected="true">Tab 1</button>
527
+ <button role="tab" data-ux-toggle="tab" data-ux-target="#tab2">Tab 2</button>
528
+ </nav>
529
+ <div class="tab-content">
530
+ <div id="tab1" class="tab-pane active show">Content 1</div>
531
+ <div id="tab2" class="tab-pane">Content 2</div>
532
+ </div>
533
+ </div>
534
+ ```
535
+
536
+ **Variants:** `ux4g-tab-underline`, `ux4g-tab-pill`
537
+ **Sizes:** `ux4g-tab-sm`, `ux4g-tab-md`, `ux4g-tab-lg`
538
+ **Vertical:** `ux4g-tab-vertical`
539
+
540
+ ### Icon Button
541
+
542
+ ```html
543
+ <button class="ux4g-icon-btn ux4g-icon-btn-primary ux4g-icon-btn-md">
544
+ <i class="ux4g-icon-edit"></i>
545
+ </button>
546
+
547
+ <!-- Pill icon button -->
548
+ <button class="ux4g-icon-btn ux4g-icon-btn-tonal-primary ux4g-icon-btn-lg ux4g-icon-btn-pill">
549
+ <i class="ux4g-icon-plus"></i>
550
+ </button>
551
+ ```
552
+
553
+ **Variants:** `ux4g-icon-btn-primary`, `ux4g-icon-btn-outline-primary`, `ux4g-icon-btn-tonal-primary`, `ux4g-icon-btn-text-primary`
554
+ **Sizes:** `ux4g-icon-btn-xl`, `ux4g-icon-btn-lg`, `ux4g-icon-btn-md`, `ux4g-icon-btn-sm`, `ux4g-icon-btn-xs`
555
+ **Pill:** `ux4g-icon-btn-pill`
556
+
557
+ ### Accessibility Bar
558
+
559
+ ```html
560
+ <div class="ux4g-topbar">
561
+ <a href="#main-content" class="ux4g-skip-link">Skip to main content</a>
562
+ <!-- Additional accessibility controls -->
563
+ </div>
564
+ ```
565
+
566
+ ### Accordion
567
+
568
+ ```html
569
+ <div class="ux4g-accordion ux4g-accordion-arrow-right">
570
+ <div class="ux4g-accordion-item">
571
+ <button data-ux-toggle="collapse" data-ux-target="#acc1" aria-expanded="false">
572
+ Section 1
573
+ </button>
574
+ <div id="acc1" class="collapse">
575
+ <div class="ux4g-accordion-body">Content for section 1</div>
576
+ </div>
577
+ </div>
578
+ </div>
579
+
580
+ <!-- Bordered variant with left arrow -->
581
+ <div class="ux4g-accordion ux4g-accordion-arrow-left ux4g-accordion-bordered">
582
+ ...
583
+ </div>
584
+ ```
585
+
586
+ **Arrow position:** `ux4g-accordion-arrow-right`, `ux4g-accordion-arrow-left`
587
+ **Variant:** `ux4g-accordion-bordered`
588
+
589
+ ### Stepper
590
+
591
+ ```html
592
+ <!-- Horizontal stepper -->
593
+ <div class="ux4g-stepper">
594
+ <div class="ux4g-stepper-step completed">Step 1</div>
595
+ <div class="ux4g-stepper-step active">Step 2</div>
596
+ <div class="ux4g-stepper-step">Step 3</div>
597
+ </div>
598
+
599
+ <!-- Vertical stepper, small -->
600
+ <div class="ux4g-stepper ux4g-stepper-vertical ux4g-stepper-s">
601
+ ...
602
+ </div>
603
+
604
+ <!-- Horizontal centered with bottom-line variant -->
605
+ <div class="ux4g-stepper ux4g-stepper-horizontal ux4g-stepper-center ux4g-stepper-bottom-line">
606
+ ...
607
+ </div>
608
+ ```
609
+
610
+ **Orientation:** `ux4g-stepper-vertical`, `ux4g-stepper-horizontal`
611
+ **Alignment:** `ux4g-stepper-center`, `ux4g-stepper-left`
612
+ **Variants:** `ux4g-stepper-bottom-line`, `ux4g-stepper-bottom-line-fill`, `ux4g-stepper-mobile`, `ux4g-stepper-progress`
613
+ **Size:** `ux4g-stepper-s`
614
+
615
+ ### Slider
616
+
617
+ ```html
618
+ <div class="ux4g-slider-field">
619
+ <input type="range" min="0" max="100" value="50" />
620
+ </div>
621
+
622
+ <!-- Medium slider -->
623
+ <div class="ux4g-slider-field ux4g-slider-md">
624
+ <input type="range" min="0" max="100" value="75" />
625
+ </div>
626
+ ```
627
+
628
+ **Sizes:** default (sm), `ux4g-slider-md`
629
+
630
+ ### Drawer
631
+
632
+ ```html
633
+ <!-- Trigger -->
634
+ <button data-ux-toggle="offcanvas" data-ux-target="#drawer1">Open Drawer</button>
635
+
636
+ <!-- Drawer -->
637
+ <div id="drawer1" class="ux4g-drawer ux4g-drawer-right">
638
+ <div class="ux4g-drawer-header">
639
+ <h3>Drawer Title</h3>
640
+ <button data-ux-dismiss="offcanvas">&times;</button>
641
+ </div>
642
+ <div class="ux4g-drawer-body">Drawer content</div>
643
+ </div>
644
+ ```
645
+
646
+ **Placements:** `ux4g-drawer-right`, `ux4g-drawer-left`, `ux4g-drawer-top`, `ux4g-drawer-bottom`
647
+ **Open state:** `ux4g-drawer-open`
648
+
649
+ ### Date-Time Picker
650
+
651
+ ```html
652
+ <!-- Date picker -->
653
+ <div class="ux4g-date-picker-container">
654
+ <input type="date" />
655
+ </div>
656
+
657
+ <!-- Time picker -->
658
+ <div class="ux4g-time-picker-container">
659
+ <input type="time" />
660
+ </div>
661
+ ```
662
+
663
+ ### Status Pipeline
664
+
665
+ ```html
666
+ <div class="ux4g-status-pipeline-stepper">
667
+ <div class="ux4g-status-pipeline-step completed">Submitted</div>
668
+ <div class="ux4g-status-pipeline-step active">In Review</div>
669
+ <div class="ux4g-status-pipeline-step">Approved</div>
670
+ </div>
671
+
672
+ <!-- Vertical status pipeline -->
673
+ <div class="ux4g-status-pipeline-stepper ux4g-status-pipeline-vertical">
674
+ ...
675
+ </div>
676
+ ```
677
+
678
+ **Orientation:** `ux4g-status-pipeline-vertical`, `ux4g-status-pipeline-horizontal`
679
+ **Alignment:** `ux4g-status-pipeline-center`, `ux4g-status-pipeline-left`
680
+ **Variants:** `ux4g-status-pipeline-bottom-line`, `ux4g-status-pipeline-bottom-line-fill`, `ux4g-status-pipeline-mobile`, `ux4g-status-pipeline-progress`
681
+ **Size:** `ux4g-status-pipeline-s`
682
+
683
+ ### Journey Timeline
684
+
685
+ ```html
686
+ <!-- Vertical timeline (default) -->
687
+ <div class="ux4g-journey-timeline ux4g-journey-timeline--vertical">
688
+ <div class="ux4g-journey-timeline-item">
689
+ <div class="ux4g-journey-timeline-marker"></div>
690
+ <div class="ux4g-journey-timeline-content">Event 1</div>
691
+ </div>
692
+ </div>
693
+
694
+ <!-- Horizontal timeline -->
695
+ <div class="ux4g-journey-timeline ux4g-journey-timeline--horizontal">
696
+ ...
697
+ </div>
698
+ ```
699
+
700
+ ### Form Field Group
701
+
702
+ ```html
703
+ <div class="ux4g-form-group">
704
+ <label>Full Name</label>
705
+ <input type="text" class="ux4g-input-md" />
706
+ <span class="ux4g-form-helper">Enter your full legal name</span>
707
+ </div>
708
+ ```
709
+
710
+ ### OTP Input
711
+
712
+ ```html
713
+ <!-- Default OTP -->
714
+ <div class="ux4g-otp">
715
+ <input type="text" maxlength="1" />
716
+ <input type="text" maxlength="1" />
717
+ <input type="text" maxlength="1" />
718
+ <input type="text" maxlength="1" />
719
+ </div>
720
+
721
+ <!-- Error state -->
722
+ <div class="ux4g-otp ux4g-otp-error">
723
+ ...
724
+ </div>
725
+ ```
726
+
727
+ **States:** default, `ux4g-otp-success`, `ux4g-otp-error`, `ux4g-otp-locked`
39
728
 
40
- ### Shared Types (Class_Builders)
729
+ ### File Upload
41
730
 
42
- Framework wrapper packages import Class_Builder functions from this package:
731
+ ```html
732
+ <div class="ux4g-upload ux4g-upload-state-default">
733
+ <input type="file" />
734
+ <span>Drag & drop or click to upload</span>
735
+ </div>
736
+
737
+ <!-- Uploaded state -->
738
+ <div class="ux4g-upload ux4g-upload-state-uploaded">
739
+ <span>document.pdf</span>
740
+ <button class="ux4g-upload-remove">&times;</button>
741
+ </div>
742
+ ```
743
+
744
+ **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`
745
+
746
+ ### Progress Indicator
747
+
748
+ ```html
749
+ <!-- Bar progress -->
750
+ <div class="ux4g-progress-bar">
751
+ <div class="ux4g-progress-bar-fill" style="width: 60%"></div>
752
+ </div>
753
+
754
+ <!-- Circle progress -->
755
+ <div class="ux4g-progress-circle">
756
+ <svg><!-- circle SVG --></svg>
757
+ </div>
758
+ ```
759
+
760
+ **Types:** `ux4g-progress-bar`, `ux4g-progress-circle`
761
+
762
+ ### Feedback
763
+
764
+ ```html
765
+ <div class="ux4g-feedback">
766
+ <p>Was this helpful?</p>
767
+ <button>Yes</button>
768
+ <button>No</button>
769
+ </div>
770
+ ```
771
+
772
+ ### Draft Status Banner
773
+
774
+ ```html
775
+ <!-- Default -->
776
+ <div class="ux4g-daft-staus-bar">Draft saved</div>
777
+
778
+ <!-- Auto-save variant -->
779
+ <div class="ux4g-auto-daft-staus-bar">Auto-saving...</div>
780
+
781
+ <!-- Success variant -->
782
+ <div class="ux4g-success-daft-staus-bar">Published successfully</div>
783
+ ```
784
+
785
+ ### SLA Progress Indicator
786
+
787
+ ```html
788
+ <!-- Circle SLA -->
789
+ <div class="ux4g-sla-circle">
790
+ <span>75%</span>
791
+ </div>
792
+
793
+ <!-- Linear SLA -->
794
+ <div class="ux4g-sla-linear">
795
+ <div class="ux4g-sla-fill" style="width: 75%"></div>
796
+ </div>
797
+
798
+ <!-- Badge SLA -->
799
+ <span class="ux4g-sla-badge">On Track</span>
800
+ ```
801
+
802
+ **Types:** `ux4g-sla-circle`, `ux4g-sla-linear`, `ux4g-sla-badge`
803
+
804
+ ### Carousel
805
+
806
+ ```html
807
+ <div class="ux4g-carousel" data-ux-ride="carousel">
808
+ <div class="carousel-inner">
809
+ <div class="carousel-item active">Slide 1</div>
810
+ <div class="carousel-item">Slide 2</div>
811
+ <div class="carousel-item">Slide 3</div>
812
+ </div>
813
+ <button data-ux-slide="prev">Prev</button>
814
+ <button data-ux-slide="next">Next</button>
815
+ </div>
816
+ ```
817
+
818
+ ### Empty State
819
+
820
+ ```html
821
+ <div class="ux4g-empty-state">
822
+ <img src="empty-illustration.svg" alt="" />
823
+ <h3>No results found</h3>
824
+ <p>Try adjusting your search or filters.</p>
825
+ <button class="ux4g-btn-primary ux4g-btn-md">Reset Filters</button>
826
+ </div>
827
+ ```
828
+
829
+ ### Chip Group
830
+
831
+ ```html
832
+ <!-- Filter chip group -->
833
+ <div class="ux4g-filter-chip-group">
834
+ <button class="ux4g-filter-chip-md active">All</button>
835
+ <button class="ux4g-filter-chip-md">Category A</button>
836
+ <button class="ux4g-filter-chip-md">Category B</button>
837
+ </div>
838
+
839
+ <!-- Choice chip group -->
840
+ <div class="ux4g-choice-chip-group">
841
+ <button class="ux4g-choice-chip-md active">Option 1</button>
842
+ <button class="ux4g-choice-chip-md">Option 2</button>
843
+ </div>
844
+ ```
845
+
846
+ ### Navbar
847
+
848
+ ```html
849
+ <nav class="ux4g-navbar">
850
+ <a href="/" class="ux4g-navbar-brand">Logo</a>
851
+ <ul class="ux4g-navbar-nav">
852
+ <li><a href="#">Home</a></li>
853
+ <li><a href="#">About</a></li>
854
+ <li><a href="#">Contact</a></li>
855
+ </ul>
856
+ </nav>
857
+ ```
858
+
859
+ ### Social Links
860
+
861
+ ```html
862
+ <div class="ux4g-d-flex ux4g-gap-s">
863
+ <a href="#" aria-label="Twitter"><i class="ux4g-icon-twitter"></i></a>
864
+ <a href="#" aria-label="LinkedIn"><i class="ux4g-icon-linkedin"></i></a>
865
+ <a href="#" aria-label="GitHub"><i class="ux4g-icon-github"></i></a>
866
+ </div>
867
+ ```
868
+
869
+ **Size via gap:** `ux4g-gap-xs` (sm), `ux4g-gap-s` (md), `ux4g-gap-m` (lg)
870
+
871
+ ### Slot Grid
872
+
873
+ ```html
874
+ <!-- Weekly slot grid -->
875
+ <div class="ux4g-time-slot-weekly-container">
876
+ <div class="ux4g-time-slot">9:00 AM</div>
877
+ <div class="ux4g-time-slot">10:00 AM</div>
878
+ </div>
879
+
880
+ <!-- Compact slot grid -->
881
+ <div class="ux4g-time-slot-compact-container">
882
+ <div class="ux4g-time-slot">9:00</div>
883
+ <div class="ux4g-time-slot">9:30</div>
884
+ </div>
885
+ ```
886
+
887
+ ### Footer
888
+
889
+ ```html
890
+ <footer class="ux4g-footer-primary">
891
+ <div class="ux4g-footer-content">
892
+ <p>&copy; 2024 Company Name</p>
893
+ </div>
894
+ </footer>
895
+ ```
896
+
897
+ **Themes:** default (no class), `ux4g-footer-primary`, `ux4g-footer-dark`
898
+
899
+ ### Result List Row
900
+
901
+ ```html
902
+ <div class="ux4g-result-list">
903
+ <div class="ux4g-result-list-item">
904
+ <h4>Result Title</h4>
905
+ <p>Description text</p>
906
+ </div>
907
+ </div>
908
+
909
+ <!-- Variation v2 -->
910
+ <div class="ux4g-result-list ux4g-result-list-v2">
911
+ ...
912
+ </div>
913
+ ```
914
+
915
+ **Variations:** default, `ux4g-result-list-v1`, `ux4g-result-list-v2`, `ux4g-result-list-v3`, `ux4g-result-list-v4`, `ux4g-result-list-v5`
916
+
917
+ ---
918
+
919
+ ## Runtime Module
920
+
921
+ 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.
922
+
923
+ ### Explicit Initialization (recommended for apps that need control)
924
+
925
+ ```ts
926
+ import { initRuntime, destroyRuntime } from 'ux4g-components-web/runtime';
927
+
928
+ // Call once at app startup
929
+ initRuntime();
930
+
931
+ // Call for cleanup (testing, SSR teardown)
932
+ destroyRuntime();
933
+ ```
934
+
935
+ ### Auto-Bootstrap (side-effect import)
936
+
937
+ ```ts
938
+ import 'ux4g-components-web/runtime/bootstrap';
939
+ // Runtime is initialized immediately on import
940
+ ```
941
+
942
+ ### Behaviors Provided
943
+
944
+ | Behavior | Data Attribute | Description |
945
+ |---|---|---|
946
+ | Dropdown | `data-ux-toggle="dropdown"` | Toggle dropdown menus |
947
+ | Modal | `data-ux-toggle="modal"` | Open/close modals with escape/backdrop |
948
+ | Tooltip | `data-ux-toggle="tooltip"` | Show/hide on hover/focus |
949
+ | Popover | `data-ux-toggle="popover"` | Show/hide on click |
950
+ | Collapse | `data-ux-toggle="collapse"` | Expand/collapse sections |
951
+ | Tab | `data-ux-toggle="tab"` | Switch tab panels |
952
+ | Carousel | `data-ux-ride="carousel"` | Auto-slide, next/prev controls |
953
+ | Offcanvas/Drawer | `data-ux-toggle="offcanvas"` | Slide-in panels |
954
+ | Toast | `.toast` | Auto-hide notifications |
955
+ | ScrollSpy | `data-ux-spy="scroll"` | Highlight nav on scroll |
956
+
957
+ ### Design Notes
958
+
959
+ - **Singleton guard:** `window.__UX4G_RUNTIME_INITIALIZED__` prevents duplicate initialization
960
+ - **SSR-safe:** No-ops when `window`/`document` are unavailable
961
+ - **Event delegation:** All listeners attached to `document`
962
+ - **Cleanup:** `destroyRuntime()` removes all listeners and resets the guard
963
+
964
+ ---
965
+
966
+ ## Shared Types (Class_Builder)
967
+
968
+ Framework wrappers import Class_Builder functions from this package to map typed props to CSS class strings:
43
969
 
44
970
  ```ts
45
971
  import { buildButtonClasses, ButtonVariant, ButtonSize } from 'ux4g-components-web/types';
@@ -48,7 +974,25 @@ const classes = buildButtonClasses('primary', 'md', false, false);
48
974
  // → "ux4g-btn-primary ux4g-btn-md"
49
975
  ```
50
976
 
51
- ### Utility Classes
977
+ ### Custom Integrations
978
+
979
+ You can use Class_Builder functions in any framework (Vue, Svelte, vanilla JS):
980
+
981
+ ```ts
982
+ import { buildCardClasses } from 'ux4g-components-web/types';
983
+ import { buildSpinnerClasses } from 'ux4g-components-web/types';
984
+
985
+ // Use in a Vue component
986
+ const cardClass = buildCardClasses('outline', 'horizontal');
987
+ // → "ux4g-card ux4g-card-outline ux4g-card-horizontal"
988
+
989
+ const spinnerClass = buildSpinnerClasses('primary', 'lg', 'full');
990
+ // → "ux4g-spinner-primary-full ux4g-spinner-lg"
991
+ ```
992
+
993
+ ---
994
+
995
+ ## Utility Classes
52
996
 
53
997
  Use utility classes directly in HTML — no wrapper component needed:
54
998
 
@@ -58,12 +1002,74 @@ Use utility classes directly in HTML — no wrapper component needed:
58
1002
  </div>
59
1003
  ```
60
1004
 
61
- ## What's Included
1005
+ ### Available Utility Categories (27 modules)
62
1006
 
63
- | Export | Description |
64
- |--------|-------------|
65
- | `ux4g-components-web/styles.css` | Pre-built CSS bundle (~7MB, fonts embedded as base64) |
66
- | `ux4g-components-web/types` | Class_Builder functions and TypeScript types |
1007
+ | Category | Modules |
1008
+ |---|---|
1009
+ | Typography & Text | `typography`, `typescale`, `colors`, `text-transform`, `vertical-align` |
1010
+ | Layout & Spacing | `spacing`, `sizing`, `gap`, `object-fit`, `overflow`, `position`, `z-index`, `visibility`, `display`, `display-responsive` |
1011
+ | Flexbox & Grid | `flex`, `flex-responsive`, `align`, `justify`, `order` |
1012
+ | Visual Effects | `background`, `border`, `radius`, `shadow`, `opacity`, `blur` |
1013
+ | Interaction | `interaction` |
1014
+
1015
+ ### Common Utility Examples
1016
+
1017
+ ```html
1018
+ <!-- Flexbox layout -->
1019
+ <div class="ux4g-d-flex ux4g-justify-between ux4g-align-center ux4g-gap-m">
1020
+ ...
1021
+ </div>
1022
+
1023
+ <!-- Typography -->
1024
+ <h1 class="ux4g-heading-xl-bold">Title</h1>
1025
+ <p class="ux4g-body-m-default">Body text</p>
1026
+
1027
+ <!-- Spacing -->
1028
+ <div class="ux4g-p-l ux4g-m-m">Padded and margined</div>
1029
+
1030
+ <!-- Background and border -->
1031
+ <div class="ux4g-bg-neutral-soft ux4g-border-neutral ux4g-radius-lg ux4g-shadow-md">
1032
+ Card-like container
1033
+ </div>
1034
+ ```
1035
+
1036
+ ---
1037
+
1038
+ ## Dark Theme
1039
+
1040
+ Apply the dark theme by adding the `data-theme="dark"` attribute to any container or the `<html>` element:
1041
+
1042
+ ```html
1043
+ <html data-theme="dark">
1044
+ <!-- All components automatically use dark tokens -->
1045
+ </html>
1046
+ ```
1047
+
1048
+ Or scope it to a section:
1049
+
1050
+ ```html
1051
+ <div data-theme="dark">
1052
+ <button class="ux4g-btn-primary ux4g-btn-md">Dark themed button</button>
1053
+ </div>
1054
+ ```
1055
+
1056
+ The design tokens automatically switch values based on the `data-theme` attribute — no additional CSS imports needed.
1057
+
1058
+ ---
1059
+
1060
+ ## Focus Ring
1061
+
1062
+ 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:
1063
+
1064
+ ```html
1065
+ <!-- Focus ring is applied automatically to interactive elements -->
1066
+ <button class="ux4g-btn-primary ux4g-btn-md">Focusable</button>
1067
+
1068
+ <!-- Custom focus ring via utility -->
1069
+ <div tabindex="0" class="ux4g-focus-ring">Custom focusable element</div>
1070
+ ```
1071
+
1072
+ ---
67
1073
 
68
1074
  ## Related Packages
69
1075