@uxelle/skills 0.2.1-beta.0 → 0.2.3

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 (53) hide show
  1. package/README.md +3 -5
  2. package/dist/index.js +106 -96
  3. package/index.json +106 -96
  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/Icon.md +4 -4
  11. package/skills/uxelle-components/Image.md +10 -3
  12. package/skills/uxelle-components/MultiSelect.md +3 -2
  13. package/skills/uxelle-components/NavigationSide.md +3 -3
  14. package/skills/uxelle-components/NavigationSideItem.md +4 -4
  15. package/skills/uxelle-components/NavigationSideSubItem.md +3 -3
  16. package/skills/uxelle-components/SKILL.md +9 -2
  17. package/skills/uxelle-components/Select.md +2 -1
  18. package/skills/uxelle-components/StatTile.md +13 -42
  19. package/skills/uxelle-components/Table.md +7 -4
  20. package/skills/uxelle-components/getting-started.md +85 -0
  21. package/skills/uxelle-design-harness/SKILL.md +44 -20
  22. package/skills/uxelle-design-harness/a2ui.md +31 -2
  23. package/skills/uxelle-design-harness/density.md +138 -0
  24. package/skills/uxelle-design-harness/how-to-accessibility.md +3 -1
  25. package/skills/uxelle-design-harness/how-to-color.md +6 -3
  26. package/skills/uxelle-design-harness/how-to-host.md +8 -21
  27. package/skills/uxelle-design-harness/how-to-page-layout.md +51 -6
  28. package/skills/uxelle-design-harness/principles.md +10 -6
  29. package/skills/uxelle-design-harness/recipe-app-chrome.md +20 -16
  30. package/skills/uxelle-design-harness/recipe-card-grid.md +14 -5
  31. package/skills/uxelle-design-harness/recipe-cta-band.md +16 -6
  32. package/skills/uxelle-design-harness/recipe-dashboard-overview.md +21 -7
  33. package/skills/uxelle-design-harness/recipe-data-table-page.md +30 -137
  34. package/skills/uxelle-design-harness/recipe-feature-section.md +9 -7
  35. package/skills/uxelle-design-harness/recipe-footer.md +7 -4
  36. package/skills/uxelle-design-harness/recipe-form-section.md +2 -2
  37. package/skills/uxelle-design-harness/recipe-hero.md +35 -15
  38. package/skills/uxelle-design-harness/recipe-landing-page.md +27 -4
  39. package/skills/uxelle-design-harness/recipe-logo-wall.md +11 -9
  40. package/skills/uxelle-design-harness/recipe-multi-step-flow.md +5 -3
  41. package/skills/uxelle-design-harness/recipe-page-header.md +14 -4
  42. package/skills/uxelle-design-harness/recipe-page-shell.md +2 -2
  43. package/skills/uxelle-design-harness/recipe-pricing.md +5 -2
  44. package/skills/uxelle-design-harness/recipe-query-bar.md +21 -5
  45. package/skills/uxelle-design-harness/recipe-record-detail.md +5 -2
  46. package/skills/uxelle-design-harness/recipe-settings-page.md +3 -3
  47. package/skills/uxelle-design-harness/recipe-stat-callouts.md +14 -7
  48. package/skills/uxelle-design-harness/recipe-states.md +9 -4
  49. package/skills/uxelle-design-harness/recipe-summary-list.md +5 -3
  50. package/skills/uxelle-design-harness/recipe-template.md +6 -0
  51. package/skills/uxelle-design-harness/recipe-testimonial.md +5 -3
  52. package/skills/uxelle-design-harness/spacing-steps.md +17 -8
  53. 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.3",
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,28 +138,33 @@
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": 3387,
157
+ "hash": "sha256:5aa1009aaf71d2d45d8f57198ee52942d4220d031948357c646b799b19ffd34f"
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",
161
- "size": 2218,
162
- "hash": "sha256:bfde859f04937c40b1ce2f3b386e9b059e3781878b1bb91471e688de605ccf1b"
166
+ "size": 2948,
167
+ "hash": "sha256:c467d672c13c5d52120618d5f932454e5f3a8dbd5f8bdd2e1498b26f676d523d"
163
168
  },
164
169
  {
165
170
  "path": "IconButton.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",
@@ -248,8 +253,8 @@
248
253
  },
249
254
  {
250
255
  "path": "NavigationSide.md",
251
- "size": 5005,
252
- "hash": "sha256:32386fd82517e9d74561b4c05b8a7b0951532fcf1ab80b038fe7bde376b96752"
256
+ "size": 5474,
257
+ "hash": "sha256:ffe9e9a88ade7c6cef99c1953e4e265afce446d616af366fd4b63206517396bf"
253
258
  },
254
259
  {
255
260
  "path": "NavigationSideGroup.md",
@@ -258,13 +263,13 @@
258
263
  },
259
264
  {
260
265
  "path": "NavigationSideItem.md",
261
- "size": 5839,
262
- "hash": "sha256:a57473d0c207155e48e34e495a9a8b195357442871132c04e3a51b0130044cc9"
266
+ "size": 6595,
267
+ "hash": "sha256:3e7f51a9eabb5bf144022064b14416cebbc4d7d9eb87ee9c82299c5ecbb50e34"
263
268
  },
264
269
  {
265
270
  "path": "NavigationSideSubItem.md",
266
- "size": 2350,
267
- "hash": "sha256:f3da7ff70aac2a0568ff6831efd18bd2849d459f88ba41a76006432a33245b02"
271
+ "size": 2649,
272
+ "hash": "sha256:3edf70cb4a3cb43abd112cbae73d83385481f004d8e48513ab455596388d221e"
268
273
  },
269
274
  {
270
275
  "path": "NavLink.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": 14816,
347
+ "hash": "sha256:a15ed6eb6c149096d9cb6376ee47e17700cbf36ed498edd176232ff87f78d94b"
343
348
  },
344
349
  {
345
350
  "path": "Spinner.md",
@@ -348,8 +353,8 @@
348
353
  },
349
354
  {
350
355
  "path": "StatTile.md",
351
- "size": 7820,
352
- "hash": "sha256:e9330341336d46ab38724a17e76548d8cd4081b06b1a483bfea6be642718ea9e"
356
+ "size": 8042,
357
+ "hash": "sha256:76a99c8ea47082659e625c59030d0cef527bd19d8d6cabd635e71016be13754d"
353
358
  },
354
359
  {
355
360
  "path": "Stepper.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": 5279,
418
+ "hash": "sha256:9ebad576e8878251c6ce2210a7cab70066b30d04f0b38e1963b5eeb9f5c820e3"
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": 3732,
428
+ "hash": "sha256:c66c97e67182cb444fb9ff6f1b02db8da663f928a79bf31517008b9dc3f7a82e"
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": 2856,
438
+ "hash": "sha256:05187f27fb791bc18c613354635d5d68a044454c166dfce0925116adca3a6cba"
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": 4857,
468
+ "hash": "sha256:4fe4573d6eb09730c1737875c835ca9b939cd3d8e8587ecae09ba7331b2ff8d7"
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": 4207,
543
+ "hash": "sha256:ef84f56f302f623b990dff4e5051256642a41cf2dabab0e102ddf030bff4f61c"
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.3",
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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Import: `import { Icon } from "@uxelle/components";`
4
4
 
5
- Renders Material Symbols icons.
5
+ Inline Material Symbols Sharp pictogram.
6
6
 
7
7
  ## Props
8
8
 
@@ -10,13 +10,13 @@ Renders Material Symbols icons.
10
10
 
11
11
  | Prop | Type | Default | Description |
12
12
  |------|------|---------|-------------|
13
- | iconName | `string` | `"add"` | Material Symbols ligature name to render, e.g. `home`, `close`, or `settings`. Names outside that set render as literal text. |
13
+ | iconName | `string` | `"add"` | Material Symbols Sharp name to render, e.g. `home`, `close`, or `settings`. GPF chrome names always resolve. Any other name needs `import "@uxelle/icons/register"` (or `registerIcons`) before render. Unknown names render no glyph (an empty span — a visual-only miss that a11y tests will not catch). Type names with `UxelleIconName` from `@uxelle/icons` to catch typos at compile time. |
14
14
  | size | `number` | `24` | Glyph size in pixels, applied as an inline `font-size`. Valid range is 8–128 and out-of-range values warn in development; leaving it at the default emits no inline size, so CSS or a parent token can drive it. |
15
15
  | style | `CSSProperties` | `—` | Inline styles merged onto the icon `span`, applied after the `size`-derived `font-size` — a `fontSize` here therefore overrides `size`. |
16
16
  | "aria-label" | `string` | `""` | Accessible name for an icon that carries meaning. Setting it also suppresses the automatic `aria-hidden`, so the icon becomes visible to assistive technology. |
17
17
  | "aria-hidden" | `"auto" \| "true" \| "false"` | `undefined` | Explicitly includes or excludes the icon from the accessibility tree. Leave it unset for the default: hidden when there is no `aria-label`, exposed once there is one. |
18
18
  | role | `string` | `""` | Role placed on the icon `span`. Pair `img` with `aria-label` when the glyph is meaningful content; leave it unset for decorative icons. |
19
- | variant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Glyph weight: `sharpFilled` renders the solid form through font-variation settings, `sharpUnfilled` the outlined form. |
19
+ | variant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Glyph weight: `sharpFilled` renders the solid SVG, `sharpUnfilled` the outlined form. |
20
20
 
21
21
  <!-- prettier-ignore-end -->
22
22
 
@@ -40,4 +40,4 @@ Renders Material Symbols icons.
40
40
 
41
41
  ## Notes
42
42
 
43
- - Uses the material-symbols sharp font; updates instantly when `iconName` changes. By default, icons are hidden from screen readers (`aria-hidden="true"`) as they are typically decorative. Provide an `aria-label` when the icon conveys meaningful information.
43
+ - Looks up a Sharp SVG from `iconName` and `variant`. `@uxelle/components` ships the GPF chrome set; register the full catalog with `import "@uxelle/icons/register"` or **registerIcons** before the first render. Unknown names render no glyph and warn in development — treat that as an authoring error, not UI copy. Production is silent: an icon-only control with `aria-label` still has an accessible name, so this is a visual-only failure that a11y tests will not catch. Import `@uxelle/icons/register` in the host, or type names with `UxelleIconName` from `@uxelle/icons`. By default, icons are hidden from screen readers (`aria-hidden="true"`) as they are typically decorative. Provide an `aria-label` when the icon conveys meaningful information.
@@ -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.
@@ -10,9 +10,9 @@ App chrome for a vertical side rail, or a compact top bar on small layouts.
10
10
 
11
11
  | Prop | Type | Default | Description |
12
12
  |------|------|---------|-------------|
13
- | expanded | `boolean` | `—` | Controlled rail width: wide labeled rail when true, icon-only rail when false. Pass with `onExpandedChange`; omit to let `defaultExpanded` and the built-in toggle own the width. Ignored when the mobile layout is shown. |
13
+ | expanded | `boolean` | `—` | Controlled rail width: wide labeled rail when true, icon-only rail when false. Pass with `onExpandedChange`; omit to let `defaultExpanded` and the built-in toggle own the width. Ignored when the mobile layout is shown. Collapsing hides open nested destination lists; accordion parents of the current nested page show the selected appearance. |
14
14
  | defaultExpanded | `boolean` | `true` | Whether the rail starts wide and labeled (true) or icon-only (false) when `expanded` is omitted. The built-in toggle owns the width after mount. |
15
- | onExpandedChange | `(expanded: boolean) => void` | `—` | Called with the next width state each time the expand/collapse control is activated. Required to track the width when `expanded` is set. |
15
+ | onExpandedChange | `(expanded: boolean) => void` | `—` | Called with the next width state each time the expand/collapse control is activated. Required to track the width when `expanded` is set. Collapsing hides open nested destination lists on accordion rows. |
16
16
  | mobile | `boolean` | `—` | Top-bar chrome when true; side rail when false. SSR hosts must pass `true` or `false` so server and client markup match. Omit only in client-only surfaces to follow the theme mobile range (`--uxl-theme-layout-mobile-screen-width-max`). The menu opens a right sheet with the same center and bottom slots as the rail. |
17
17
  | logoSlot | `boolean` | `true` | Renders the logo region on the expanded rail and the mobile top bar. Set `false` to leave it empty; the collapsed rail never shows the logo. |
18
18
  | logoSlotContent | `ReactNode` | `undefined` | Content for the logo region, typically a decorative **Logo**. Rendered only when `logoSlot` is true; omit for a neutral placeholder block. |
@@ -45,7 +45,7 @@ Extends `HTMLAttributes` — supports standard HTML attributes.
45
45
  ## Notes
46
46
 
47
47
  - **Rail**: Logo, expand/collapse control, `centerSlotContent` (`NavigationSideGroup` rows), and `bottomSlotContent`. Renders an `<aside>`. Groups remain named `<nav>` landmarks — do not wrap this chrome in another `nav`.
48
- - **Width**: Set `expanded` for the labeled rail and `expanded={false}` for the icon-only rail. Hosts own when to pass those values (tablet-and-up). This component does not hard-code those widths.
48
+ - **Width**: Set `expanded` for the labeled rail and `expanded={false}` for the icon-only rail. Hosts own when to pass those values (tablet-and-up). This component does not hard-code those widths. Collapsing hides any open accordion nested lists (focus moves to the parent if a nested row had it) and shows the selected appearance on an accordion parent when a nested row is the current page. Expanding restores that open state unless the flyout was dismissed while collapsed.
49
49
  - **Mobile**: Pass `mobile` (`true` or `false`) in SSR so the first paint matches hydration. The server snapshot for an omitted `mobile` is always the rail, so a phone viewport would swap to the top bar on the client. Omit `mobile` only in client-only surfaces (for example Storybook) to follow the theme mobile range (`--uxl-theme-layout-mobile-screen-width-max`). When the mobile layout is shown, the menu control opens a right `Sheet` (no visible title, labeled Menu for assistive tech) with the same `centerSlotContent` and `bottomSlotContent` as the rail (labeled rows, not the collapsed icon rail). The logo stays on the top bar. Use `menuOpen` / `onMenuOpenChange` to control the sheet (for example to close it after navigation). `onMenuClick` still fires on the menu control.
50
50
  - **Slots**: Omit a slot to fill demo content. Pass `false` to leave a region empty. `logoSlot={false}` hides the logo on the expanded rail and the mobile bar.
51
51
  - **Bottom slot**: Typical account rows use `List` + `ListItem`. List item text stays on one line during the rail width transition (same as destination labels) so it is revealed horizontally instead of wrapping.