@uxelle/skills 0.2.1-beta.0 → 0.2.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.
Files changed (48) hide show
  1. package/README.md +3 -5
  2. package/dist/index.js +96 -86
  3. package/index.json +96 -86
  4. package/package.json +1 -1
  5. package/skills/uxelle-components/ChoiceChip.md +1 -1
  6. package/skills/uxelle-components/ChoiceChipGroup.md +3 -3
  7. package/skills/uxelle-components/FilterChip.md +2 -2
  8. package/skills/uxelle-components/FilterChipGroup.md +1 -1
  9. package/skills/uxelle-components/Hero.md +2 -2
  10. package/skills/uxelle-components/Image.md +10 -3
  11. package/skills/uxelle-components/MultiSelect.md +3 -2
  12. package/skills/uxelle-components/SKILL.md +3 -1
  13. package/skills/uxelle-components/Select.md +2 -1
  14. package/skills/uxelle-components/Table.md +7 -4
  15. package/skills/uxelle-components/getting-started.md +54 -0
  16. package/skills/uxelle-design-harness/SKILL.md +44 -20
  17. package/skills/uxelle-design-harness/a2ui.md +22 -2
  18. package/skills/uxelle-design-harness/density.md +138 -0
  19. package/skills/uxelle-design-harness/how-to-accessibility.md +2 -0
  20. package/skills/uxelle-design-harness/how-to-color.md +6 -3
  21. package/skills/uxelle-design-harness/how-to-host.md +5 -22
  22. package/skills/uxelle-design-harness/how-to-page-layout.md +51 -6
  23. package/skills/uxelle-design-harness/principles.md +10 -6
  24. package/skills/uxelle-design-harness/recipe-app-chrome.md +20 -16
  25. package/skills/uxelle-design-harness/recipe-card-grid.md +14 -5
  26. package/skills/uxelle-design-harness/recipe-cta-band.md +16 -6
  27. package/skills/uxelle-design-harness/recipe-dashboard-overview.md +17 -5
  28. package/skills/uxelle-design-harness/recipe-data-table-page.md +30 -137
  29. package/skills/uxelle-design-harness/recipe-feature-section.md +9 -7
  30. package/skills/uxelle-design-harness/recipe-footer.md +7 -4
  31. package/skills/uxelle-design-harness/recipe-form-section.md +2 -2
  32. package/skills/uxelle-design-harness/recipe-hero.md +35 -15
  33. package/skills/uxelle-design-harness/recipe-landing-page.md +27 -4
  34. package/skills/uxelle-design-harness/recipe-logo-wall.md +11 -9
  35. package/skills/uxelle-design-harness/recipe-multi-step-flow.md +5 -3
  36. package/skills/uxelle-design-harness/recipe-page-header.md +14 -4
  37. package/skills/uxelle-design-harness/recipe-page-shell.md +2 -2
  38. package/skills/uxelle-design-harness/recipe-pricing.md +5 -2
  39. package/skills/uxelle-design-harness/recipe-query-bar.md +21 -5
  40. package/skills/uxelle-design-harness/recipe-record-detail.md +5 -2
  41. package/skills/uxelle-design-harness/recipe-settings-page.md +3 -3
  42. package/skills/uxelle-design-harness/recipe-stat-callouts.md +8 -3
  43. package/skills/uxelle-design-harness/recipe-states.md +9 -4
  44. package/skills/uxelle-design-harness/recipe-summary-list.md +5 -3
  45. package/skills/uxelle-design-harness/recipe-template.md +6 -0
  46. package/skills/uxelle-design-harness/recipe-testimonial.md +5 -3
  47. package/skills/uxelle-design-harness/spacing-steps.md +17 -8
  48. package/skills/uxelle-design-harness/tokens.md +45 -4
package/index.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.2.1-beta.0",
3
+ "version": "0.2.2",
4
4
  "skills": [
5
5
  {
6
6
  "name": "uxelle-components",
7
- "description": "Reference for uxElle Generative Product Foundation (GPF) components. Use when generating UI with uxElle, implementing designs, building layouts, or when the user mentions uxElle components, design system, or enterprise UI.",
7
+ "description": "Reference for uxElle Generative Product Foundation (GPF) components. Use when generating UI with uxElle, implementing designs, building layouts, installing or setting up a React or Next.js app with @uxelle/components, loading theme CSS, or when the user mentions uxElle components or enterprise UI.",
8
8
  "files": [
9
9
  {
10
10
  "path": "Accordion.md",
@@ -68,13 +68,13 @@
68
68
  },
69
69
  {
70
70
  "path": "ChoiceChip.md",
71
- "size": 3796,
72
- "hash": "sha256:9c2dc57310d28631817bb75acd151a9c23ff5644d19cb345c7bd65fa8d75797a"
71
+ "size": 4061,
72
+ "hash": "sha256:6d3233c0895eb04bad20f0adb1818e0f591afa94c2cd3dba36d3d7af1baa4ee8"
73
73
  },
74
74
  {
75
75
  "path": "ChoiceChipGroup.md",
76
- "size": 4756,
77
- "hash": "sha256:91de9bc2984cbfb640e1ba117661fcfd7633bb9c16ef3f3b2b9fd7c2d1f0c032"
76
+ "size": 4999,
77
+ "hash": "sha256:97f3f8c26837e0adb78b7bea234e04160c58819dc8ff4664f8852a9080da54cc"
78
78
  },
79
79
  {
80
80
  "path": "DatePicker.md",
@@ -138,23 +138,28 @@
138
138
  },
139
139
  {
140
140
  "path": "FilterChip.md",
141
- "size": 2891,
142
- "hash": "sha256:da8c799773f8f94c82a29f777015d1516cedec9bb53d042fd079ff2b4dd25a41"
141
+ "size": 3290,
142
+ "hash": "sha256:feaa21e3cf7b095ea8f9d37bc84693206bf479209ee8a7b4a77ccb66c5028e4d"
143
143
  },
144
144
  {
145
145
  "path": "FilterChipGroup.md",
146
- "size": 4369,
147
- "hash": "sha256:fa8e1c2544071de8fc268c0c4aceda4ddea9aebe62f63b4bc32894632d857aa5"
146
+ "size": 4422,
147
+ "hash": "sha256:811a57ccac9b6777f8264651e52ca0ccb13da9bad3c428fe5ad8ffe324ed0772"
148
148
  },
149
149
  {
150
150
  "path": "Footer.md",
151
151
  "size": 1276,
152
152
  "hash": "sha256:e2ca30ae7eba1e8c206d70791f4636a66e4f654059dbddda1b508bfd08e7b5c2"
153
153
  },
154
+ {
155
+ "path": "getting-started.md",
156
+ "size": 2276,
157
+ "hash": "sha256:c40148458f76df3bdd9a0cf85732cd09bbe621c5625d20c4251aa7f4bd808a90"
158
+ },
154
159
  {
155
160
  "path": "Hero.md",
156
- "size": 3330,
157
- "hash": "sha256:56619429625460a459b3ea7c37379769342628b35e461ed2614fe233fb99ebbc"
161
+ "size": 3578,
162
+ "hash": "sha256:e79223c6415b55c68cbe9d86e00d19a66ff369f43d6158231356cc409055a419"
158
163
  },
159
164
  {
160
165
  "path": "Icon.md",
@@ -168,8 +173,8 @@
168
173
  },
169
174
  {
170
175
  "path": "Image.md",
171
- "size": 2065,
172
- "hash": "sha256:75ee6ba8c65372ecbbf013c264b2bafaac509847949fb08d571538179c053560"
176
+ "size": 3893,
177
+ "hash": "sha256:37e001e0dde7ec499fe1d2ac3a805402972d12e64fc773991579310ff6738a7a"
173
178
  },
174
179
  {
175
180
  "path": "Label.md",
@@ -238,8 +243,8 @@
238
243
  },
239
244
  {
240
245
  "path": "MultiSelect.md",
241
- "size": 5923,
242
- "hash": "sha256:2bf934ef37ddb1a39867fa5167bfc6693477b2dff72b37684446315570e2562e"
246
+ "size": 6171,
247
+ "hash": "sha256:1b106b8d5368b4236e1671e0000545fb41dea75ff6ffc67595ec33a360a04f17"
243
248
  },
244
249
  {
245
250
  "path": "Navigation.md",
@@ -323,8 +328,8 @@
323
328
  },
324
329
  {
325
330
  "path": "Select.md",
326
- "size": 6032,
327
- "hash": "sha256:546f35666100ff9e3fc65c9b8a07908e3f73182abca021518f34b6f9b4118e47"
331
+ "size": 6321,
332
+ "hash": "sha256:629e02b1014c0134b8c2a0f8716e2e161ac268a502b64568429d5060f68ccd06"
328
333
  },
329
334
  {
330
335
  "path": "Sheet.md",
@@ -338,8 +343,8 @@
338
343
  },
339
344
  {
340
345
  "path": "SKILL.md",
341
- "size": 13949,
342
- "hash": "sha256:ea3ea17c6e11456ace3d1890d9cacdadd2eac8f2ff2e6ec4e68e697184928944"
346
+ "size": 14408,
347
+ "hash": "sha256:de312111538d710c822a0212af2188584591d594d4f99ba7f3efb7a4435e9021"
343
348
  },
344
349
  {
345
350
  "path": "Spinner.md",
@@ -368,8 +373,8 @@
368
373
  },
369
374
  {
370
375
  "path": "Table.md",
371
- "size": 2727,
372
- "hash": "sha256:bfe8aa99f3cd9ee3bea87f151c5f42f091f93d4dd47006c76e0ed456a18b7af8"
376
+ "size": 3695,
377
+ "hash": "sha256:5455212f7c8f0370d369702dc6198c95e37fbde14695823413b7930b8421eefd"
373
378
  },
374
379
  {
375
380
  "path": "TabsCompact.md",
@@ -409,163 +414,168 @@
409
414
  "files": [
410
415
  {
411
416
  "path": "a2ui.md",
412
- "size": 3438,
413
- "hash": "sha256:79acf8d1fb2df2dd82bf979f05807c4d2d0f75b4fafd94e32b31a103bdac86f4"
417
+ "size": 4779,
418
+ "hash": "sha256:e557e7caba1471f250a651f6449aa4b8e73b40e05c331dcbda25892b958ecd99"
419
+ },
420
+ {
421
+ "path": "density.md",
422
+ "size": 7471,
423
+ "hash": "sha256:1f819b3670222a54105b50c5c6f76059dd0e739b4b642c245be586e5c03f6e4a"
414
424
  },
415
425
  {
416
426
  "path": "how-to-accessibility.md",
417
- "size": 3160,
418
- "hash": "sha256:d84f9acbb4f9e55420f355acaeabca61533f5febc8d0ec688a4c9072b95ae501"
427
+ "size": 3554,
428
+ "hash": "sha256:c19043086e302c1681ae462efa9f7282a9e227aeb78dfe93bf66f6c4f4710bf7"
419
429
  },
420
430
  {
421
431
  "path": "how-to-color.md",
422
- "size": 3724,
423
- "hash": "sha256:de6a183f582582cf43f4eb901706dca062f36b8d27601fc442c8ada4f56d2bf8"
432
+ "size": 3923,
433
+ "hash": "sha256:a72c5a4d88d007d68e6b640bccba0434fdd2c23ae8f291a77bdaec8689163425"
424
434
  },
425
435
  {
426
436
  "path": "how-to-host.md",
427
- "size": 3080,
428
- "hash": "sha256:b3cbd747f0913075e0db35747dc47e088b291bcf7a128a14648b6bf5c12e7009"
437
+ "size": 2647,
438
+ "hash": "sha256:bdab3b08e77adaabcd582dff4b64838e0723ade66d5c9416be9111f9dc9b49cd"
429
439
  },
430
440
  {
431
441
  "path": "how-to-page-layout.md",
432
- "size": 8414,
433
- "hash": "sha256:9f6eb01b3a160d0ef6bc809fa416d2134869b3da31c3cc95039e906798454603"
442
+ "size": 10962,
443
+ "hash": "sha256:b01626a0661950a5bbb9a7def38e82b6b3ce9ded32a328edd72aa5c256588a84"
434
444
  },
435
445
  {
436
446
  "path": "principles.md",
437
- "size": 4174,
438
- "hash": "sha256:1d1a83cf5af7a32e4758cf1c7cd3da54f711ff6aae15dd12a8c1ad4a554c9fbe"
447
+ "size": 4551,
448
+ "hash": "sha256:7e93db6f61f469237feb5405b61f2d49e5aeef4d15425efdaa947bfafb6aabc8"
439
449
  },
440
450
  {
441
451
  "path": "recipe-app-chrome.md",
442
- "size": 9152,
443
- "hash": "sha256:8d42d4fba9c8df38a72394a2512c584ad271855edf58013116f598c232d6b777"
452
+ "size": 10042,
453
+ "hash": "sha256:225ebbfabfa65538c9275744c4cc6e5cc7798a36ab496643b41283efae3ea1a3"
444
454
  },
445
455
  {
446
456
  "path": "recipe-card-grid.md",
447
- "size": 3411,
448
- "hash": "sha256:1ceb77d6de97f560b34c2de166142fc78fb3eb7c81e9af40262f59c2c1ceeffd"
457
+ "size": 4099,
458
+ "hash": "sha256:3e594d337994417cf391f31222464c99fc84b9f4f251560c82d8f3501bdee5f4"
449
459
  },
450
460
  {
451
461
  "path": "recipe-cta-band.md",
452
- "size": 3033,
453
- "hash": "sha256:5d3973dc04c2cffd8beeb2c1e0c8f20eaefe9c047f090e70b6e01641cc84eb1a"
462
+ "size": 3645,
463
+ "hash": "sha256:4259be1f810e29abe43400010bde395ebf3e3e7ed7dc465b1c58d6ed87f3154c"
454
464
  },
455
465
  {
456
466
  "path": "recipe-dashboard-overview.md",
457
- "size": 4004,
458
- "hash": "sha256:ab2e8a60dc61444564eb352a35d2a9a2be152e8b493d898e0f0aadbd87676d6e"
467
+ "size": 4708,
468
+ "hash": "sha256:a6a581ca179595535d9d3df0469d362d8e7175e5595bea3222a32733c66c4615"
459
469
  },
460
470
  {
461
471
  "path": "recipe-data-table-page.md",
462
- "size": 14766,
463
- "hash": "sha256:45dfcc1ef9ba681715e9a1b34e7e691870966d09f9851d5d416f6753c389bf55"
472
+ "size": 14334,
473
+ "hash": "sha256:3133781fb670d44f0d0e6c25c75520272800127d4a11dab00b0bebcccf75f53c"
464
474
  },
465
475
  {
466
476
  "path": "recipe-feature-section.md",
467
- "size": 3239,
468
- "hash": "sha256:8f77b15b331599bb384c02567fee0b2215691c69a76d364c29580b0930de1a7b"
477
+ "size": 3422,
478
+ "hash": "sha256:4e6927fe2efdc1eafc94511037a4cdeb528896e377eebaef16728f7a29cffe20"
469
479
  },
470
480
  {
471
481
  "path": "recipe-footer.md",
472
- "size": 7107,
473
- "hash": "sha256:534369d865b44b752c51cc60d0c141c9e8f476ac59462e7d2013c5c0dc8dab9b"
482
+ "size": 7241,
483
+ "hash": "sha256:8c2bd3e9b3c88c7444b2d9a92308f883541cb61cd8f039d757ca885ba9d122af"
474
484
  },
475
485
  {
476
486
  "path": "recipe-form-section.md",
477
- "size": 8676,
478
- "hash": "sha256:ef5c72a29137302c7c939c666574c639abe3f737d32eccc6e8218e13bd4cbbf1"
487
+ "size": 9125,
488
+ "hash": "sha256:dfdac68a0788e17fe48a5b8084717bbac7f59a80b0fbfcb1622ce2421211706c"
479
489
  },
480
490
  {
481
491
  "path": "recipe-hero.md",
482
- "size": 3138,
483
- "hash": "sha256:a3276a485257f8ba745482b75d9ca368812918d6f6a3e9dc351c2ddedffcc817"
492
+ "size": 4106,
493
+ "hash": "sha256:14a1e862832226591244646ff442cf46b25ca8e088c2f15b0376a8ac8bde0cc2"
484
494
  },
485
495
  {
486
496
  "path": "recipe-landing-page.md",
487
- "size": 3513,
488
- "hash": "sha256:fdab8439e7a21ba901cc86c577092f9765a33d822044b66384b4c02c473a18cf"
497
+ "size": 4900,
498
+ "hash": "sha256:7cf05d3d24e98b680e28f52b9691c59f881b420993f7af2ed1adc6ef1279ccc1"
489
499
  },
490
500
  {
491
501
  "path": "recipe-logo-wall.md",
492
- "size": 2702,
493
- "hash": "sha256:d9ffed408a5dd0adeab19bc425413432db143fc12c2b58b73b49c31b5c608c40"
502
+ "size": 2920,
503
+ "hash": "sha256:6b9c2199a0a18d20cf8350013ebbba4f9a8c94f4d5b50642d93ac1551c054eff"
494
504
  },
495
505
  {
496
506
  "path": "recipe-multi-step-flow.md",
497
- "size": 3712,
498
- "hash": "sha256:4921735a867d6635bc7a0152e2045fbcffb94b5ba047004fbbd5720e46080077"
507
+ "size": 3876,
508
+ "hash": "sha256:351069ddf1e5d085d9f1a89caa47c368874b5d15d4cb9a53e9e1691c3df44a14"
499
509
  },
500
510
  {
501
511
  "path": "recipe-page-header.md",
502
- "size": 3483,
503
- "hash": "sha256:83728fd741f2518ef97d927ea5bb33969b1609a1fca38ceb836ed733178cb42f"
512
+ "size": 4161,
513
+ "hash": "sha256:7487c48c7ea6ba57a613d9e91b4b4a1c6271ea27120f4a3c857dc1501dfce518"
504
514
  },
505
515
  {
506
516
  "path": "recipe-page-shell.md",
507
- "size": 3537,
508
- "hash": "sha256:1392b86cafabeeb375b62d791804f8d4012345a72716cac6f80824253beb842e"
517
+ "size": 3826,
518
+ "hash": "sha256:0e87856ed26f73a19cc057f63c505bfce7a6973b2f389f257ffdde9bac64faca"
509
519
  },
510
520
  {
511
521
  "path": "recipe-pricing.md",
512
- "size": 3106,
513
- "hash": "sha256:babee8bad4e2a8ddaf3baf5fbbddf82914a2f910be0c52e2b4df2e191407a084"
522
+ "size": 3374,
523
+ "hash": "sha256:072d554945710df4b2a2be3c78836a3aa1d0b910bace362c2838272130e152e1"
514
524
  },
515
525
  {
516
526
  "path": "recipe-query-bar.md",
517
- "size": 4024,
518
- "hash": "sha256:caeb50b6bf583bc55963fa225677d9adb0701db7e705219f380490e450767739"
527
+ "size": 4990,
528
+ "hash": "sha256:d63bc538947160d1cf14209c9777233bc78e9cc1b2b52278b21b7959ff4e06c2"
519
529
  },
520
530
  {
521
531
  "path": "recipe-record-detail.md",
522
- "size": 3249,
523
- "hash": "sha256:8322cff9a5a1b344e10b7e63f25297d5cdfe58e21b6d53419910ef75acb2ef53"
532
+ "size": 3480,
533
+ "hash": "sha256:1d21484544c0307fc409570aeacf5f10bd03cde564e91e32ad271d46b29c7da6"
524
534
  },
525
535
  {
526
536
  "path": "recipe-settings-page.md",
527
- "size": 7978,
528
- "hash": "sha256:837984d7079f0334b5c3f12a7490f7febdca050ecb4ec675284f4e17259a7ec4"
537
+ "size": 8287,
538
+ "hash": "sha256:eda9f10d2367b9bab26ef66ae471d65f6189c410829ea2176c07d6b1a82f89f8"
529
539
  },
530
540
  {
531
541
  "path": "recipe-stat-callouts.md",
532
- "size": 3684,
533
- "hash": "sha256:b0f0c70364f797265413b40b741e349f1e88429bf3e1bd9fc9c020cce37730ee"
542
+ "size": 4017,
543
+ "hash": "sha256:fb3857880f691fd016cb1414ee788e3a9fdfc49f7e61376442965aa018896f6e"
534
544
  },
535
545
  {
536
546
  "path": "recipe-states.md",
537
- "size": 3684,
538
- "hash": "sha256:9d25de854ed1ea06a74412aa26f3e238d559977075aa02877ef17f2a398b8605"
547
+ "size": 4150,
548
+ "hash": "sha256:cda9dedd98d44e1eddcb25b1cca721f686e15a7642d53ebcfe926c8241cca38d"
539
549
  },
540
550
  {
541
551
  "path": "recipe-summary-list.md",
542
- "size": 2808,
543
- "hash": "sha256:c3ee287cdac7986994d53041cf2d6cf461018d039dca6224bd01e01275ef3b9a"
552
+ "size": 2951,
553
+ "hash": "sha256:a7fad25286bc6b6e357acfcc2b1afb5c562078b3bf633a190ad68648b2748cc4"
544
554
  },
545
555
  {
546
556
  "path": "recipe-template.md",
547
- "size": 3268,
548
- "hash": "sha256:9117d2cfccb0c1d33ebb05272b7fac5d98f92570f44dff06b0072e7a72a1d45e"
557
+ "size": 3703,
558
+ "hash": "sha256:d3fe331af035c4af72d143b0d65ebba7a719a6b104af34ef7939afb1f05ef14a"
549
559
  },
550
560
  {
551
561
  "path": "recipe-testimonial.md",
552
- "size": 2324,
553
- "hash": "sha256:ee43cacccda063d1843759d117153e5ae658d2a0f0130c504e3d62dabedc9171"
562
+ "size": 2453,
563
+ "hash": "sha256:7a755896fb14b0d3f4771ead61996f494033bb856e6ac847dfb78eb216bfce6c"
554
564
  },
555
565
  {
556
566
  "path": "SKILL.md",
557
- "size": 9065,
558
- "hash": "sha256:e9b12497656c5258cb88968548689a8e4a960b701861012c853c0b969dc946d4"
567
+ "size": 10810,
568
+ "hash": "sha256:096a85cb85d2fe413bc5f2abb241c45ea6e59dfc3b9547a00b639c7739fc014e"
559
569
  },
560
570
  {
561
571
  "path": "spacing-steps.md",
562
- "size": 2379,
563
- "hash": "sha256:f2b089b1575994f2f15b6220e76436e475c45c57efa6951aecbf497fa31bdb81"
572
+ "size": 2959,
573
+ "hash": "sha256:dcfcadc6371c478bd80f796231502fdaf65548914cda7786457a26e59b37e8ab"
564
574
  },
565
575
  {
566
576
  "path": "tokens.md",
567
- "size": 4547,
568
- "hash": "sha256:de72dee7c0334a6dc074f02223e5142a53742c8889baac4402a18d3d74a5bba3"
577
+ "size": 6758,
578
+ "hash": "sha256:69af34fc3fbfbf63a7796c2c49dc123c4cefc7b8553c3678b86bce6cd33dcdaf"
569
579
  }
570
580
  ]
571
581
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxelle/skills",
3
- "version": "0.2.1-beta.0",
3
+ "version": "0.2.2",
4
4
  "description": "uxElle generate-UI agent skills: component API reference and design harness, as versioned markdown with a machine-readable manifest",
5
5
  "type": "module",
6
6
  "repository": {
@@ -41,4 +41,4 @@ Toggle pill for choice sets (facets, sort, view options).
41
41
 
42
42
  ## Notes
43
43
 
44
- - Uses `checked` / `defaultChecked` with `aria-pressed`. Checked chips show a leading check. Selection policy (single vs multi) is owned by the app — this control only toggles itself. Compose in **ChoiceChipGroup**. For exclusive single-select, keep one checked value in app state and set `role="radiogroup"` on the group. Use **FilterChip** for dismissible applied filters. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values. Controlled: set `checked` from `onChange` (next pressed value). Uncontrolled: `defaultChecked` is mount-only.
44
+ - Uses `checked` / `defaultChecked` with `aria-pressed`. Checked chips show a leading check. Unchecked labels use **Text** type `Condensed`; checked labels use `Condensed Alt`. Pass `label` as a string — do not wrap a `Text` node. Selection policy (single vs multi) is owned by the app — this control only toggles itself. Compose in **ChoiceChipGroup**. For exclusive single-select, keep one checked value in app state and leave `role="group"`. ChoiceChip stays a toggle button (`aria-pressed`), not a radio — use **RadioGroup** or **SegmentedControl** when you need radio semantics. Use **FilterChip** for dismissible applied filters. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values. Controlled: set `checked` from `onChange` (next pressed value). Uncontrolled: `defaultChecked` is mount-only.
@@ -17,7 +17,7 @@ Groups choice toggles under an optional legend, wrapping to new rows as needed.
17
17
  | fieldMessageType | `"Info" \| "Danger" \| "Warning" \| "Success"` | `CHOICE_CHIP_GROUP_DEFAULTS.fieldMessageType` | Tone of the wrapped **FieldMessage** — `Info`, `Danger`, `Warning`, or `Success`. Forced to `Danger` while `invalid` is true. `Danger` wires the message as `aria-errormessage` and announces it politely; other tones link through `aria-describedby`. |
18
18
  | required | `boolean` | `false` | Sets `aria-required` on the fieldset and shows the **Label** asterisk while a legend is visible. No native validation is enforced — the app owns that. |
19
19
  | invalid | `boolean` | `false` | Sets `aria-invalid="true"` and shows a Danger field message (uses `fieldMessage` when set, otherwise a default error string). Also wires `aria-errormessage` and announces the message politely. `aria-invalid={true}` does the same; `false` is treated as omitted so this prop can still apply. |
20
- | role | `string` | `"group"` | ARIA role on the fieldset. Keep `group` for independent toggles; switch to `radiogroup` only when the app enforces exclusive selection and the chips carry matching roles. |
20
+ | role | `string` | `"group"` | ARIA role on the fieldset. Default `group`. Chip children are not radio buttons — do not set `radiogroup`. For exclusive choice, keep one checked value in app state. Use **RadioGroup** or **SegmentedControl** for radio semantics. |
21
21
  | "aria-label" | `string` | `""` | Accessible name for the fieldset, used only when no legend is showing. Prefer a visible legend via `label` and `labelText`; this value is dropped while one renders. |
22
22
  | "aria-labelledby" | `string` | `""` | IDs of elements that name the fieldset when no legend renders, space-separated. Dropped while a legend is showing, since the legend already names the group. |
23
23
  | "aria-describedby" | `string` | `""` | IDs of elements describing the group, space-separated. Merged with the field-message region id for non-`Danger` messages rather than replacing it. |
@@ -38,7 +38,7 @@ Groups choice toggles under an optional legend, wrapping to new rows as needed.
38
38
 
39
39
  ```tsx
40
40
  // Exclusive single-select (app-owned)
41
- <ChoiceChipGroup label labelText="Sort by" role="radiogroup">
41
+ <ChoiceChipGroup label labelText="Sort by">
42
42
  <ChoiceChip label="Relevance" checked onChange={() => {}} />
43
43
  <ChoiceChip label="Newest" onChange={() => {}} />
44
44
  </ChoiceChipGroup>
@@ -47,4 +47,4 @@ Groups choice toggles under an optional legend, wrapping to new rows as needed.
47
47
 
48
48
  ## Notes
49
49
 
50
- - Pass **ChoiceChip** children. Root is a **`fieldset`** with default **`role="group"`**; name it with the legend (`label` + `labelText`) or `aria-label` / `aria-labelledby`. Selection policy (single vs multi) is app-owned — this group does not enforce exclusivity. Keep **`role="group"`** for independent toggles. For exclusive single-select, keep one checked value in app state and set **`role="radiogroup"`** on the group. Form parity: **`fieldMessage`**, **`required`**, **`invalid`**, and merged **`aria-describedby`** / **`aria-errormessage`**. For dismissible applied filters, use **FilterChipGroup**. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values.
50
+ - Pass **ChoiceChip** children. Root is a **`fieldset`** with default **`role="group"`**; name it with the legend (`label` + `labelText`) or `aria-label` / `aria-labelledby`. Each chip owns its label type: `Condensed` when unchecked, `Condensed Alt` when checked. Selection policy (single vs multi) is app-owned — this group does not enforce exclusivity. Keep **`role="group"`**. For exclusive single-select, keep one checked value in app state — the chips remain `aria-pressed` toggles. Do not set **`role="radiogroup"`** (that role requires radio children). Use **RadioGroup** or **SegmentedControl** for radio semantics. Form parity: **`fieldMessage`**, **`required`**, **`invalid`**, and merged **`aria-describedby`** / **`aria-errormessage`**. For dismissible applied filters, use **FilterChipGroup**. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values.
@@ -10,7 +10,7 @@ Removable pill for an applied filter value.
10
10
 
11
11
  | Prop | Type | Default | Description |
12
12
  |------|------|---------|-------------|
13
- | label (required) | `string` | `"Filter Chip"` | Filter value shown on the chip; also seeds the remove control's default name (`Remove {label}`). Whitespace is trimmed, an empty result renders no chip, and long values are not truncated. |
13
+ | label (required) | `string` | `"Filter Chip"` | Filter value shown on the chip; also seeds the remove control's default name (`Remove {label}`). Whitespace is trimmed, an empty result renders no chip. The label hugs content so chips wrap as units; it ellipsizes only when the chip itself is narrower than the label, so the dismiss control stays visible. |
14
14
  | disabled | `boolean` | `false` | Applies disabled styling and blocks dismissal — the remove control ignores clicks and keys, and arrow-key navigation inside **FilterChipGroup** skips it. |
15
15
  | leadingIcon | `boolean` | `false` | Adds a decorative icon before the label, useful for showing which facet the value belongs to. |
16
16
  | leadingIconName | `string` | `"add"` | Material Symbol drawn before the label. Ignored unless `leadingIcon` is `true`. |
@@ -32,4 +32,4 @@ Removable pill for an applied filter value.
32
32
 
33
33
  ## Notes
34
34
 
35
- - Always requires `onRemove` — the chip’s job is to represent a filter that can be dismissed. Root is a non-interactive `span` so the dismiss Icon Button nests correctly; the surface does not use hover/pressed fills. Prefer **ChoiceChip** for selectable option sets. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values. Keyboard: focus the remove control, then **Enter** / **Space** or **Delete** / **Backspace** to dismiss. Inside **FilterChipGroup**, arrow keys move between chips (one Tab stop for the set). Removal is announced via a polite live region.
35
+ - Always requires `onRemove` — the chip’s job is to represent a filter that can be dismissed. The label uses **Text** type `Condensed`. Pass `label` as a string — do not wrap a `Text` node. The label hugs content so chips wrap as whole units in **FilterChipGroup**. When a single chip is wider than its container, the label ellipsizes so the dismiss control stays visible. Root is a non-interactive `span` so the dismiss Icon Button nests correctly; the surface does not use hover/pressed fills. Prefer **ChoiceChip** for selectable option sets. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values. Keyboard: focus the remove control, then **Enter** / **Space** or **Delete** / **Backspace** to dismiss. Inside **FilterChipGroup**, arrow keys move between chips (one Tab stop for the set). Removal is announced via a polite live region.
@@ -39,4 +39,4 @@ Groups dismissible applied-filter chips under an optional legend, wrapping to ne
39
39
 
40
40
  ## Notes
41
41
 
42
- - Pass **FilterChip** children. Root is a **`fieldset`** with default **`role="group"`**; name it with the legend (`label` + `labelText`) or `aria-label` / `aria-labelledby`. Keyboard: one Tab stop into the set; **Arrow** keys move between remove controls; **Delete** / **Backspace** dismisses the focused chip. Removals are announced politely. Form parity: **`fieldMessage`**, **`required`**, **`invalid`**, and merged **`aria-describedby`** / **`aria-errormessage`**. For choice option toggles, use **ChoiceChipGroup**. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values.
42
+ - Pass **FilterChip** children. Root is a **`fieldset`** with default **`role="group"`**; name it with the legend (`label` + `labelText`) or `aria-label` / `aria-labelledby`. Each child’s label uses **Text** type `Condensed`. Keyboard: one Tab stop into the set; **Arrow** keys move between remove controls; **Delete** / **Backspace** dismisses the focused chip. Removals are announced politely. Form parity: **`fieldMessage`**, **`required`**, **`invalid`**, and merged **`aria-describedby`** / **`aria-errormessage`**. For choice option toggles, use **ChoiceChipGroup**. There is no InputChip — compose entry (e.g. Textfield) with FilterChips for removable values.
@@ -11,7 +11,7 @@ Full-bleed marketing band with overlaid copy and actions.
11
11
  | Prop | Type | Default | Description |
12
12
  |------|------|---------|-------------|
13
13
  | contentDirection | `"Left" \| "Right" \| "Bottom"` | `"Left"` | Where the content panel sits over the media. From the tablet breakpoint (678px) up, `Left` and `Right` pin a half-width, vertically centered panel to that edge, while `Bottom` keeps a full-width panel along the bottom. Below 678px all three collapse to the same full-width bottom panel. |
14
- | image (required) | `ReactNode` | `—` | Full-bleed media behind the hero. Pass a **direct** child `Image`, `img`, `picture`, or `video` — extra wrappers are unsupported and will not fill the media layer. Prefer `Image` for source, alt text, and optional overlay. Do not rely on `Image` aspect ratio — Hero owns the responsive crop. Keep this region non-interactive; put actions in `contentSlot`. |
14
+ | image (required) | `ReactNode` | `—` | Full-bleed media behind the hero. Pass a **direct** child `Image`, `img`, `picture`, or `video` — extra wrappers are unsupported and will not fill the media layer. Prefer `Image` for source, alt text, and optional overlay. Do not set `Image` `aspectRatio` or box size (`width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`) — Hero owns the responsive crop. Keep this region non-interactive; put actions in `contentSlot`. |
15
15
  | contentSlot (required) | `ReactNode` | `—` | Overlay panel content, stacked in a column with theme gap — typically a `Lockup` plus a `ButtonGroup`. Required: the hero always renders the panel, and it is where any interactive content belongs. |
16
16
  | "data-color-switcher" | `string` | `—` | Color-switcher palette applied to the hero root, which drives the content panel surface and text colors. Falls back to `brand-1`; pass another palette name such as `brand-2` or `neutral` to override it. |
17
17
 
@@ -58,4 +58,4 @@ Full-bleed marketing band with overlaid copy and actions.
58
58
 
59
59
  ## Notes
60
60
 
61
- - Pass media in `image` as a direct child `Image`, `img`, `picture`, or `video` (wrappers are unsupported) and composed intro content in `contentSlot` (usually `Lockup` and `ButtonGroup`). `contentDirection` controls panel placement: `Left` / `Right` for side panels on tablet and up, `Bottom` for a full-width bottom panel at every size. Below the tablet breakpoint, `Left` and `Right` use the bottom panel layout. Content-area spacing remaps through theme breakpoint aliases that currently start at 375px — widths below that need a theme update before spacing sign-off. The root defaults to `data-color-switcher="brand-1"`; pass a different attribute to override. Do not add a landmark role by default — pass `role="region"` with `aria-label` or `aria-labelledby` when a named region is needed. Remaining HTML attributes are forwarded to the root element.
61
+ - Pass media in `image` as a direct child `Image`, `img`, `picture`, or `video` (wrappers are unsupported) and composed intro content in `contentSlot` (usually `Lockup` and `ButtonGroup`). `contentDirection` controls panel placement: `Left` / `Right` for side panels on tablet and up, `Bottom` for a full-width bottom panel at every size. Below the tablet breakpoint, `Left` and `Right` use the bottom panel layout. Content-area spacing remaps through theme breakpoint aliases that currently start at 375px — widths below that need a theme update before spacing sign-off. The root defaults to `data-color-switcher="brand-1"`; pass a different attribute to override. Do not add a landmark role by default — pass `role="region"` with `aria-label` or `aria-labelledby` when a named region is needed. Remaining HTML attributes are forwarded to the root element. Nested `Image` `aspectRatio` and box size (`width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`) have no effect — this component sizes the media layer.
@@ -12,7 +12,13 @@ Responsive image that optionally crops its source to a selected aspect ratio.
12
12
  |------|------|---------|-------------|
13
13
  | src (required) | `string` | `""` | Source URL forwarded to the inner `img` element. Nothing renders in its place when the request fails, so guard missing values upstream. |
14
14
  | alt (required) | `string` | `""` | Text alternative announced by assistive technology. Describe what the image conveys, or pass an empty string to mark it decorative and drop it from the accessibility tree. |
15
- | aspectRatio | `"1:1" \| "4:3" \| "3:2" \| "16:9" \| "21:9" \| "3:4" \| "2:3"` | `undefined` | Crops the image to a fixed ratio — `1:1`, `4:3`, `3:2`, `16:9`, `21:9`, `3:4`, or `2:3`. The image fills the available width and covers the box, so overflow is trimmed; omit to keep the source's intrinsic proportions. |
15
+ | aspectRatio | `"1:1" \| "4:3" \| "3:2" \| "16:9" \| "21:9" \| "3:4" \| "2:3"` | `undefined` | Crops the image to a fixed ratio — `1:1`, `4:3`, `3:2`, `16:9`, `21:9`, `3:4`, or `2:3` — and covers the box so overflow is trimmed. With `width` or `height` it sizes the missing axis; with both, the explicit box wins and this only crops. Omit to keep the source's intrinsic proportions. |
16
+ | width | `string` | `""` | Layout width of the image box. Numbers are pixels; strings pass through as CSS (`400px`, `var(--uxl-…)`). Omit to fill the parent width. |
17
+ | minWidth | `string` | `""` | Floor for the box width. Numbers are pixels; strings pass through as CSS. With `aspectRatio`, this clamps the computed width rather than replacing the ratio. |
18
+ | maxWidth | `string` | `""` | Ceiling for the box width. Numbers are pixels; strings pass through as CSS. With `aspectRatio`, this clamps the computed width rather than replacing the ratio. |
19
+ | height | `string` | `""` | Layout height of the image box. Numbers are pixels; strings pass through as CSS. With `aspectRatio` and no `width`, this sizes the box and the ratio computes width. Omit to size height from the source or from `aspectRatio`. |
20
+ | minHeight | `string` | `""` | Floor for the box height. Numbers are pixels; strings pass through as CSS. With `aspectRatio`, this clamps the computed height rather than replacing the ratio. |
21
+ | maxHeight | `string` | `""` | Ceiling for the box height. Numbers are pixels; strings pass through as CSS. With `aspectRatio`, this clamps the computed height rather than replacing the ratio. |
16
22
  | overlay | `"100" \| "200"` | `undefined` | Layers a decorative gradient wash over the image so text placed on top keeps contrast: `100` is a light wash, `200` a dark wash weighted to the bottom edge. Omit for no overlay. |
17
23
 
18
24
  <!-- prettier-ignore-end -->
@@ -27,6 +33,7 @@ Responsive image that optionally crops its source to a selected aspect ratio.
27
33
  <Image
28
34
  src="/images/hero.jpg"
29
35
  alt="Crop field at sunrise"
36
+ width={640}
30
37
  aspectRatio="21:9"
31
38
  overlay="200"
32
39
  />
@@ -35,6 +42,6 @@ Responsive image that optionally crops its source to a selected aspect ratio.
35
42
 
36
43
  ## Notes
37
44
 
38
- - When `aspectRatio` is set, the image fills its available width and uses `object-fit: cover` to preserve the ratio. Omit `aspectRatio` to keep the intrinsic proportions. Supply meaningful `alt` text when the image conveys information, or `alt=""` when it is decorative.
45
+ - `width` and `height` size the layout box (numbers are pixels; strings pass through as CSS). `aspectRatio` is a preferred ratio used when at least one axis is still automatic: with only `width` it computes height, with only `height` it computes width, and with both the explicit box wins while the image still covers that box. `minWidth` / `maxWidth` and `minHeight` / `maxHeight` clamp the computed axis rather than replacing the ratio. Omit `aspectRatio` to keep the source's intrinsic proportions, except when `height` is set — then the image covers the box. Supply meaningful `alt` text when the image conveys information, or `alt=""` when it is decorative.
39
46
  - Set `overlay` to `"100"` or `"200"` to layer a decorative gradient wash for contrast (for example under text). The wash is non-interactive and hidden from assistive technologies.
40
- - This component is non-interactive. Wrap it in a link or button only when the surrounding experience requires an action, and name that control separately.
47
+ - This component is non-interactive. Wrap it in a link or button only when the surrounding experience requires an action, and name that control separately. Inside Hero, omit `aspectRatio` and box-size props (`width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`) — Hero owns the media box.
@@ -34,6 +34,7 @@ Multi-select dropdown with removable chips, label, optional `FieldMessage`, and
34
34
  | readOnly | `boolean` | `false` | Shows the selection as comma-separated text instead of chips, blocks opening the listbox, and hides the trailing chevron; the trigger stays focusable. |
35
35
  | required | `boolean` | `—` | Adds the asterisk to `Label` and `aria-required` on the trigger. Advisory only — no native constraint validation runs on the hidden inputs. |
36
36
  | name | `string` | `—` | Form field name for the hidden inputs that post the selection — one input per selected value, and none at all while nothing is selected. |
37
+ | onClick | `MouseEventHandler<HTMLDivElement>` | `—` | Fired on the field chrome. `currentTarget` is the trigger wrapper, not the combobox input. |
37
38
  | disabled | `boolean` | `false` | Blocks interaction, collapses chips to comma-separated text, and removes the trigger from the tab order; a `name` hidden input still submits each selected value. |
38
39
 
39
40
  <!-- prettier-ignore-end -->
@@ -49,6 +50,6 @@ Multi-select dropdown with removable chips, label, optional `FieldMessage`, and
49
50
  ## Notes
50
51
 
51
52
  - Chips stay on one row when interactive; overflowed chips collapse to “and N more”. Read-only and disabled states show comma-separated text with truncation.
52
- - **Accessibility**: Visible label uses `<Label htmlFor>`; selected values render as Filter Chip–styled tags inside the combobox (standard tag-in-input pattern). Remove controls use `tabIndex={-1}` and are omitted from the accessibility tree; toggle selections via the listbox. Overflowed labels are included in a screen-reader-only summary on the combobox. Composable list rows should use `listboxOptionProps()`. `FieldMessage` uses `aria-describedby` (info) or `aria-errormessage` (error). Pass `id` for stable ids; use `aria-label` when `label={false}`.
53
- - **Focus**: Tab focuses the combobox trigger; **Arrow** keys move the active option while open. **Enter** / **Space** toggle the active option; **Escape** closes the list.
53
+ - **Accessibility**: Visible label uses `<Label htmlFor>`; selected values render as Filter Chip–styled tags beside a readonly combobox `<input>` (standard tag-in-input pattern). Remove controls use `tabIndex={-1}` and are omitted from the accessibility tree; toggle selections via the listbox. The combobox `value` is the comma-separated selection summary, including overflowed labels. Composable list rows should use `listboxOptionProps()`. `FieldMessage` uses `aria-describedby` (info) or `aria-errormessage` (error). Pass `id` for stable ids; use `aria-label` when `label={false}`.
54
+ - **Focus**: The combobox is a readonly `<input>` (not a `<button>`) so Safari's default Tab cycle can land on it. **Arrow** keys move the active option while open. **Enter** / **Space** toggle the active option; **Escape** closes the list.
54
55
  - **Forms**: With `name`, one hidden input is rendered per selected value.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: uxelle-components
3
- description: Reference for uxElle Generative Product Foundation (GPF) components. Use when generating UI with uxElle, implementing designs, building layouts, or when the user mentions uxElle components, design system, or enterprise UI.
3
+ description: Reference for uxElle Generative Product Foundation (GPF) components. Use when generating UI with uxElle, implementing designs, building layouts, installing or setting up a React or Next.js app with @uxelle/components, loading theme CSS, or when the user mentions uxElle components or enterprise UI.
4
4
  ---
5
5
 
6
6
  # uxElle Components — Generative Workflow Reference
@@ -10,6 +10,7 @@ Reference for accurately using uxElle Generative Product Foundation (GPF) compon
10
10
  ## Context discipline
11
11
 
12
12
  - Load this SKILL.md when working with uxElle components.
13
+ - New app or host without packages and CSS? Read [getting-started.md](getting-started.md) first, then [how-to-host.md](../uxelle-design-harness/how-to-host.md). Skip getting-started when the host already loads theme CSS, component CSS, and `data-*`.
13
14
  - Load individual component files (e.g. Button.md, ListItem.md) only when you need that component's props or examples.
14
15
  - Do not preload all component files.
15
16
 
@@ -236,6 +237,7 @@ For secondary nav or brand hero bands: `data-color-switcher="brand-2"` on second
236
237
 
237
238
  ## Additional Resources
238
239
 
240
+ - [Getting started](getting-started.md) — install `@uxelle/components` and `@uxelle/themes`, load CSS, theme provider, Next.js/SSR
239
241
  - [Design harness](../uxelle-design-harness/SKILL.md) — principles, variables, page chrome, responsiveness, WCAG AA, recipes
240
242
  - [Form field contract](../../docs/guides/form-field-contract.md) — HTML `value` / `checked` (not Figma `Selected` / `Activated`)
241
243
  - [Design variables (`--uxl-*`)](../uxelle-design-harness/tokens.md) — spacing, radius, elevation, color switcher, type
@@ -34,6 +34,7 @@ Single-select dropdown with label, design tokens, optional `FieldMessage`, and l
34
34
  | readOnly | `boolean` | `false` | Shows the current selection but blocks opening the listbox and hides the trailing chevron; the trigger stays focusable and reports `aria-readonly`. |
35
35
  | required | `boolean` | `—` | Adds the asterisk to `Label` and `aria-required` on the trigger. Advisory only — no native constraint validation runs on the hidden input. |
36
36
  | name | `string` | `—` | Form field name for the hidden input that posts the selected value. No input is rendered while nothing is selected, so an empty selection is never submitted. |
37
+ | onClick | `MouseEventHandler<HTMLDivElement>` | `—` | Fired on the field chrome. `currentTarget` is the trigger wrapper, not the combobox input. |
37
38
  | disabled | `boolean` | `false` | Blocks interaction, removes the trigger from the tab order, and applies disabled styling; a `name` hidden input still submits the current value. |
38
39
 
39
40
  <!-- prettier-ignore-end -->
@@ -51,5 +52,5 @@ Single-select dropdown with label, design tokens, optional `FieldMessage`, and l
51
52
  - **Simple API** — pass `options` with `value` / `onChange` for controlled usage; optional `leadingIcon` / `leadingIconName`.
52
53
  - **Composable API** — pass `children` to render custom `ListItem` rows in the listbox; pass `leading` for a custom leading slot. Each row should spread `listboxOptionProps()` plus selection handlers (see dev console when the list opens).
53
54
  - **Accessibility**: Visible label uses `<Label htmlFor>`; the combobox name uses `aria-labelledby` on the label text only (not `fieldDescription`, which is linked via `aria-describedby`). `FieldMessage` uses `aria-describedby` (info) or `aria-errormessage` (error). Pass `id` for stable ids; use `aria-label` when `label={false}`.
54
- - **Focus**: Tab focuses the combobox trigger only; **Arrow** keys move the active option (`aria-activedescendant`) while open. **Enter** commits the active option; **Escape** closes the list. Options use `tabIndex={-1}` and are not separate tab stops.
55
+ - **Focus**: The combobox is a readonly `<input>` (not a `<button>`) so Safari's default Tab cycle — text fields, not buttons — can land on it, and a click actually focuses the control. **Arrow** keys move the active option (`aria-activedescendant`) while open. **Enter** commits the active option; **Escape** closes the list. Options use `tabIndex={-1}` and are not separate tab stops.
55
56
  - **Forms**: With `name`, a hidden input posts the selected value; when nothing is selected, no hidden input is rendered.
@@ -11,7 +11,7 @@ Composable table shell and semantic grid for tabular data. Columns support resiz
11
11
  | Prop | Type | Default | Description |
12
12
  |------|------|---------|-------------|
13
13
  | topSlot | `ReactNode` | `—` | Band rendered above the table and outside its horizontal scrollport — typically a title, toolbar, filters, or search. Omitted entirely when unset. |
14
- | bottomSlot | `ReactNode` | `—` | Band rendered below the table and outside its horizontal scrollport — typically pagination or bulk actions. Omitted entirely when unset. |
14
+ | bottomSlot | `ReactNode` | `—` | Band rendered below the table and outside its horizontal scrollport — typically **Pagination** or bulk actions. Omitted entirely when unset. |
15
15
  | tableSlot | `ReactNode` | `—` | The table itself: one **TableGrid** with its head, body, rows, and cells, placed in the scroll region that drives the horizontal scroll hint. Same slot as `children`, and it wins when both are passed. |
16
16
  | children | `ReactNode` | `—` | Alias for `tableSlot`, ignored when `tableSlot` is also passed. Compose one `TableGrid` (give it `aria-label` and `gridTemplateColumns`) holding a `TableHead` with a `TableRow` of `TableHeaderCell` children, then a `TableBody` with one `TableRow` of `TableCell` children per record — all exported from `@uxelle/components`. |
17
17
 
@@ -23,7 +23,7 @@ Extends `HTMLAttributes` — supports standard HTML attributes.
23
23
 
24
24
  ```tsx
25
25
  const columns = [
26
- { flex: 0.5, minWidth: 48 },
26
+ { flex: 0, minWidth: 48, maxWidth: 72 },
27
27
  { flex: 1, minWidth: 120 },
28
28
  ] as const;
29
29
 
@@ -44,12 +44,15 @@ function OrdersGrid() {
44
44
  <OrdersGrid />
45
45
  </TableColumnSizingProvider>
46
46
  }
47
+ bottomSlot={
48
+ <Pagination totalItems={100} defaultItemsPerPage={10} aria-label="Orders pagination" />
49
+ }
47
50
  />
48
51
  ```
49
52
 
50
53
 
51
54
  ## Notes
52
55
 
53
- - Optional top and bottom slots frame the table region; a horizontal scroll hint appears when the grid is wider than its container. Fixed columns are implemented as sticky cells inside one `TableGrid`—not as a separate grid—so each row stays a single unit for assistive technology. Use **TableColumnPinProvider** or `pinned="start"` on **TableHeaderCell** and **TableCell** with **usePinnedStartOffsets** to keep leading columns visible during horizontal scroll.
54
- - Horizontal scroll and the trailing-edge hint appear automatically when content overflows the container. Define column proportions with **TableColumnSizingProvider** and **useColumnGridTemplate**.
56
+ - Optional top and bottom slots frame the table region; pass **Pagination** in `bottomSlot` when the dataset is paged. A horizontal scroll hint appears when the grid is wider than its container. Fixed columns are implemented as sticky cells inside one `TableGrid`—not as a separate grid—so each row stays a single unit for assistive technology. Use **TableColumnPinProvider** or `pinned="start"` on **TableHeaderCell** and **TableCell** with **usePinnedStartOffsets** to keep leading columns visible during horizontal scroll.
57
+ - Horizontal scroll and the trailing-edge hint appear automatically when content overflows the container. Define column proportions with **TableColumnSizingProvider** and **useColumnGridTemplate**. Set `flex: 0` and `maxWidth` on compact columns (selection, icons) so leftover `fr` space does not stretch them on a wide viewport. `flex: 0` without a pixel `minWidth` or `maxWidth` sizes the track to content (`max-content`) instead of collapsing. `maxWidth` on a growing column (`flex > 0`) is a resize ceiling only. Cell copy wraps and the row height follows the tallest cell. Header titles stay on one line and ellipsize when the column is narrower than the name. Pass `truncation` on **Text** in a body cell only when that column must stay single-line. Resizing a column persists every column as a pixel track at the widths on screen, so siblings are not stretched or shrunk to fit the container. Call **useResetTableColumnWidths** to restore every column to its template.
55
58
  - Layout is left-to-right only; right-to-left document direction is not supported yet.