@uxelle/skills 0.2.2 → 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.
- package/dist/index.js +25 -25
- package/index.json +25 -25
- package/package.json +1 -1
- package/skills/uxelle-components/Icon.md +4 -4
- package/skills/uxelle-components/NavigationSide.md +3 -3
- package/skills/uxelle-components/NavigationSideItem.md +4 -4
- package/skills/uxelle-components/NavigationSideSubItem.md +3 -3
- package/skills/uxelle-components/SKILL.md +6 -1
- package/skills/uxelle-components/StatTile.md +13 -42
- package/skills/uxelle-components/getting-started.md +38 -7
- package/skills/uxelle-design-harness/a2ui.md +9 -0
- package/skills/uxelle-design-harness/how-to-accessibility.md +1 -1
- package/skills/uxelle-design-harness/how-to-host.md +4 -0
- package/skills/uxelle-design-harness/recipe-dashboard-overview.md +4 -2
- package/skills/uxelle-design-harness/recipe-stat-callouts.md +6 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/manifest.generated.ts
|
|
2
2
|
var manifest = {
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
7
7
|
"name": "uxelle-components",
|
|
@@ -154,8 +154,8 @@ var manifest = {
|
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
"path": "getting-started.md",
|
|
157
|
-
"size":
|
|
158
|
-
"hash": "sha256:
|
|
157
|
+
"size": 3387,
|
|
158
|
+
"hash": "sha256:5aa1009aaf71d2d45d8f57198ee52942d4220d031948357c646b799b19ffd34f"
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
161
|
"path": "Hero.md",
|
|
@@ -164,8 +164,8 @@ var manifest = {
|
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
"path": "Icon.md",
|
|
167
|
-
"size":
|
|
168
|
-
"hash": "sha256:
|
|
167
|
+
"size": 2948,
|
|
168
|
+
"hash": "sha256:c467d672c13c5d52120618d5f932454e5f3a8dbd5f8bdd2e1498b26f676d523d"
|
|
169
169
|
},
|
|
170
170
|
{
|
|
171
171
|
"path": "IconButton.md",
|
|
@@ -254,8 +254,8 @@ var manifest = {
|
|
|
254
254
|
},
|
|
255
255
|
{
|
|
256
256
|
"path": "NavigationSide.md",
|
|
257
|
-
"size":
|
|
258
|
-
"hash": "sha256:
|
|
257
|
+
"size": 5474,
|
|
258
|
+
"hash": "sha256:ffe9e9a88ade7c6cef99c1953e4e265afce446d616af366fd4b63206517396bf"
|
|
259
259
|
},
|
|
260
260
|
{
|
|
261
261
|
"path": "NavigationSideGroup.md",
|
|
@@ -264,13 +264,13 @@ var manifest = {
|
|
|
264
264
|
},
|
|
265
265
|
{
|
|
266
266
|
"path": "NavigationSideItem.md",
|
|
267
|
-
"size":
|
|
268
|
-
"hash": "sha256:
|
|
267
|
+
"size": 6595,
|
|
268
|
+
"hash": "sha256:3e7f51a9eabb5bf144022064b14416cebbc4d7d9eb87ee9c82299c5ecbb50e34"
|
|
269
269
|
},
|
|
270
270
|
{
|
|
271
271
|
"path": "NavigationSideSubItem.md",
|
|
272
|
-
"size":
|
|
273
|
-
"hash": "sha256:
|
|
272
|
+
"size": 2649,
|
|
273
|
+
"hash": "sha256:3edf70cb4a3cb43abd112cbae73d83385481f004d8e48513ab455596388d221e"
|
|
274
274
|
},
|
|
275
275
|
{
|
|
276
276
|
"path": "NavLink.md",
|
|
@@ -344,8 +344,8 @@ var manifest = {
|
|
|
344
344
|
},
|
|
345
345
|
{
|
|
346
346
|
"path": "SKILL.md",
|
|
347
|
-
"size":
|
|
348
|
-
"hash": "sha256:
|
|
347
|
+
"size": 14816,
|
|
348
|
+
"hash": "sha256:a15ed6eb6c149096d9cb6376ee47e17700cbf36ed498edd176232ff87f78d94b"
|
|
349
349
|
},
|
|
350
350
|
{
|
|
351
351
|
"path": "Spinner.md",
|
|
@@ -354,8 +354,8 @@ var manifest = {
|
|
|
354
354
|
},
|
|
355
355
|
{
|
|
356
356
|
"path": "StatTile.md",
|
|
357
|
-
"size":
|
|
358
|
-
"hash": "sha256:
|
|
357
|
+
"size": 8042,
|
|
358
|
+
"hash": "sha256:76a99c8ea47082659e625c59030d0cef527bd19d8d6cabd635e71016be13754d"
|
|
359
359
|
},
|
|
360
360
|
{
|
|
361
361
|
"path": "Stepper.md",
|
|
@@ -415,8 +415,8 @@ var manifest = {
|
|
|
415
415
|
"files": [
|
|
416
416
|
{
|
|
417
417
|
"path": "a2ui.md",
|
|
418
|
-
"size":
|
|
419
|
-
"hash": "sha256:
|
|
418
|
+
"size": 5279,
|
|
419
|
+
"hash": "sha256:9ebad576e8878251c6ce2210a7cab70066b30d04f0b38e1963b5eeb9f5c820e3"
|
|
420
420
|
},
|
|
421
421
|
{
|
|
422
422
|
"path": "density.md",
|
|
@@ -425,8 +425,8 @@ var manifest = {
|
|
|
425
425
|
},
|
|
426
426
|
{
|
|
427
427
|
"path": "how-to-accessibility.md",
|
|
428
|
-
"size":
|
|
429
|
-
"hash": "sha256:
|
|
428
|
+
"size": 3732,
|
|
429
|
+
"hash": "sha256:c66c97e67182cb444fb9ff6f1b02db8da663f928a79bf31517008b9dc3f7a82e"
|
|
430
430
|
},
|
|
431
431
|
{
|
|
432
432
|
"path": "how-to-color.md",
|
|
@@ -435,8 +435,8 @@ var manifest = {
|
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
437
|
"path": "how-to-host.md",
|
|
438
|
-
"size":
|
|
439
|
-
"hash": "sha256:
|
|
438
|
+
"size": 2856,
|
|
439
|
+
"hash": "sha256:05187f27fb791bc18c613354635d5d68a044454c166dfce0925116adca3a6cba"
|
|
440
440
|
},
|
|
441
441
|
{
|
|
442
442
|
"path": "how-to-page-layout.md",
|
|
@@ -465,8 +465,8 @@ var manifest = {
|
|
|
465
465
|
},
|
|
466
466
|
{
|
|
467
467
|
"path": "recipe-dashboard-overview.md",
|
|
468
|
-
"size":
|
|
469
|
-
"hash": "sha256:
|
|
468
|
+
"size": 4857,
|
|
469
|
+
"hash": "sha256:4fe4573d6eb09730c1737875c835ca9b939cd3d8e8587ecae09ba7331b2ff8d7"
|
|
470
470
|
},
|
|
471
471
|
{
|
|
472
472
|
"path": "recipe-data-table-page.md",
|
|
@@ -540,8 +540,8 @@ var manifest = {
|
|
|
540
540
|
},
|
|
541
541
|
{
|
|
542
542
|
"path": "recipe-stat-callouts.md",
|
|
543
|
-
"size":
|
|
544
|
-
"hash": "sha256:
|
|
543
|
+
"size": 4207,
|
|
544
|
+
"hash": "sha256:ef84f56f302f623b990dff4e5051256642a41cf2dabab0e102ddf030bff4f61c"
|
|
545
545
|
},
|
|
546
546
|
{
|
|
547
547
|
"path": "recipe-states.md",
|
package/index.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"name": "uxelle-components",
|
|
@@ -153,8 +153,8 @@
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"path": "getting-started.md",
|
|
156
|
-
"size":
|
|
157
|
-
"hash": "sha256:
|
|
156
|
+
"size": 3387,
|
|
157
|
+
"hash": "sha256:5aa1009aaf71d2d45d8f57198ee52942d4220d031948357c646b799b19ffd34f"
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
"path": "Hero.md",
|
|
@@ -163,8 +163,8 @@
|
|
|
163
163
|
},
|
|
164
164
|
{
|
|
165
165
|
"path": "Icon.md",
|
|
166
|
-
"size":
|
|
167
|
-
"hash": "sha256:
|
|
166
|
+
"size": 2948,
|
|
167
|
+
"hash": "sha256:c467d672c13c5d52120618d5f932454e5f3a8dbd5f8bdd2e1498b26f676d523d"
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
170
|
"path": "IconButton.md",
|
|
@@ -253,8 +253,8 @@
|
|
|
253
253
|
},
|
|
254
254
|
{
|
|
255
255
|
"path": "NavigationSide.md",
|
|
256
|
-
"size":
|
|
257
|
-
"hash": "sha256:
|
|
256
|
+
"size": 5474,
|
|
257
|
+
"hash": "sha256:ffe9e9a88ade7c6cef99c1953e4e265afce446d616af366fd4b63206517396bf"
|
|
258
258
|
},
|
|
259
259
|
{
|
|
260
260
|
"path": "NavigationSideGroup.md",
|
|
@@ -263,13 +263,13 @@
|
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
"path": "NavigationSideItem.md",
|
|
266
|
-
"size":
|
|
267
|
-
"hash": "sha256:
|
|
266
|
+
"size": 6595,
|
|
267
|
+
"hash": "sha256:3e7f51a9eabb5bf144022064b14416cebbc4d7d9eb87ee9c82299c5ecbb50e34"
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
270
|
"path": "NavigationSideSubItem.md",
|
|
271
|
-
"size":
|
|
272
|
-
"hash": "sha256:
|
|
271
|
+
"size": 2649,
|
|
272
|
+
"hash": "sha256:3edf70cb4a3cb43abd112cbae73d83385481f004d8e48513ab455596388d221e"
|
|
273
273
|
},
|
|
274
274
|
{
|
|
275
275
|
"path": "NavLink.md",
|
|
@@ -343,8 +343,8 @@
|
|
|
343
343
|
},
|
|
344
344
|
{
|
|
345
345
|
"path": "SKILL.md",
|
|
346
|
-
"size":
|
|
347
|
-
"hash": "sha256:
|
|
346
|
+
"size": 14816,
|
|
347
|
+
"hash": "sha256:a15ed6eb6c149096d9cb6376ee47e17700cbf36ed498edd176232ff87f78d94b"
|
|
348
348
|
},
|
|
349
349
|
{
|
|
350
350
|
"path": "Spinner.md",
|
|
@@ -353,8 +353,8 @@
|
|
|
353
353
|
},
|
|
354
354
|
{
|
|
355
355
|
"path": "StatTile.md",
|
|
356
|
-
"size":
|
|
357
|
-
"hash": "sha256:
|
|
356
|
+
"size": 8042,
|
|
357
|
+
"hash": "sha256:76a99c8ea47082659e625c59030d0cef527bd19d8d6cabd635e71016be13754d"
|
|
358
358
|
},
|
|
359
359
|
{
|
|
360
360
|
"path": "Stepper.md",
|
|
@@ -414,8 +414,8 @@
|
|
|
414
414
|
"files": [
|
|
415
415
|
{
|
|
416
416
|
"path": "a2ui.md",
|
|
417
|
-
"size":
|
|
418
|
-
"hash": "sha256:
|
|
417
|
+
"size": 5279,
|
|
418
|
+
"hash": "sha256:9ebad576e8878251c6ce2210a7cab70066b30d04f0b38e1963b5eeb9f5c820e3"
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
421
|
"path": "density.md",
|
|
@@ -424,8 +424,8 @@
|
|
|
424
424
|
},
|
|
425
425
|
{
|
|
426
426
|
"path": "how-to-accessibility.md",
|
|
427
|
-
"size":
|
|
428
|
-
"hash": "sha256:
|
|
427
|
+
"size": 3732,
|
|
428
|
+
"hash": "sha256:c66c97e67182cb444fb9ff6f1b02db8da663f928a79bf31517008b9dc3f7a82e"
|
|
429
429
|
},
|
|
430
430
|
{
|
|
431
431
|
"path": "how-to-color.md",
|
|
@@ -434,8 +434,8 @@
|
|
|
434
434
|
},
|
|
435
435
|
{
|
|
436
436
|
"path": "how-to-host.md",
|
|
437
|
-
"size":
|
|
438
|
-
"hash": "sha256:
|
|
437
|
+
"size": 2856,
|
|
438
|
+
"hash": "sha256:05187f27fb791bc18c613354635d5d68a044454c166dfce0925116adca3a6cba"
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
441
|
"path": "how-to-page-layout.md",
|
|
@@ -464,8 +464,8 @@
|
|
|
464
464
|
},
|
|
465
465
|
{
|
|
466
466
|
"path": "recipe-dashboard-overview.md",
|
|
467
|
-
"size":
|
|
468
|
-
"hash": "sha256:
|
|
467
|
+
"size": 4857,
|
|
468
|
+
"hash": "sha256:4fe4573d6eb09730c1737875c835ca9b939cd3d8e8587ecae09ba7331b2ff8d7"
|
|
469
469
|
},
|
|
470
470
|
{
|
|
471
471
|
"path": "recipe-data-table-page.md",
|
|
@@ -539,8 +539,8 @@
|
|
|
539
539
|
},
|
|
540
540
|
{
|
|
541
541
|
"path": "recipe-stat-callouts.md",
|
|
542
|
-
"size":
|
|
543
|
-
"hash": "sha256:
|
|
542
|
+
"size": 4207,
|
|
543
|
+
"hash": "sha256:ef84f56f302f623b990dff4e5051256642a41cf2dabab0e102ddf030bff4f61c"
|
|
544
544
|
},
|
|
545
545
|
{
|
|
546
546
|
"path": "recipe-states.md",
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Import: `import { Icon } from "@uxelle/components";`
|
|
4
4
|
|
|
5
|
-
|
|
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
|
|
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
|
|
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
|
-
-
|
|
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.
|
|
@@ -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.
|
|
@@ -17,10 +17,10 @@ Destination row for a vertical side navigation rail. Shows a leading icon, label
|
|
|
17
17
|
| trailingSlotContent | `ReactNode` | `undefined` | Content for the trailing region, typically a `LabelBadge`, short text, or a decorative icon. Rendered only when `trailingSlot` is true, and it must stay non-interactive because it sits inside the row's own link or button. |
|
|
18
18
|
| subNavigationItemsSlot | `ReactNode` | `undefined` | Nested `NavigationSideSubItem` rows revealed when `accordion` is true; takes precedence over `children`. On the collapsed rail they are re-rendered as a `List` of `ListItem`s inside the flyout. |
|
|
19
19
|
| children | `ReactNode` | `undefined` | Nested `NavigationSideSubItem` rows revealed when `accordion` is true, used when `subNavigationItemsSlot` is omitted. Not the row label — that is `label`. On the collapsed rail they become a `List` of `ListItem`s in the flyout. |
|
|
20
|
-
| activated | `boolean` | `false` | Marks this row as the current page: filled surface plus a leading indicator bar. Destination rows also get `aria-current="page"`; accordion parents do not, so set it on the matching child instead. |
|
|
20
|
+
| activated | `boolean` | `false` | Marks this row as the current page: filled surface plus a leading indicator bar. Destination rows also get `aria-current="page"`; accordion parents do not, so set it on the matching child instead. When the rail is collapsed, an accordion parent also shows this selected appearance if any nested `NavigationSideSubItem` is activated (pass the sub item directly, not wrapped in a custom component). |
|
|
21
21
|
| navCollapsed | `boolean` | `false` | Icon-only rail layout: hides the label, the trailing slot, and the inline accordion panel, and shows the label in a tooltip on hover and focus. Inherited from the enclosing `NavigationSideGroup` when omitted. |
|
|
22
22
|
| accordion | `boolean` | `false` | Turns the row into an expandable parent with a trailing chevron that reveals its nested rows. The control is always a button, so `href` is ignored. |
|
|
23
|
-
| open | `boolean` | `undefined` | Controlled expanded state of the accordion panel (or of the collapsed-rail flyout). Pass with `onOpenChange`; omit to use `defaultOpen` instead. |
|
|
23
|
+
| open | `boolean` | `undefined` | Controlled expanded state of the accordion panel (or of the collapsed-rail flyout). Pass with `onOpenChange`; omit to use `defaultOpen` instead. Collapsing the rail hides an open nested list even if this stays true; pass `true` again (or let the user open the flyout) to show it while collapsed. |
|
|
24
24
|
| defaultOpen | `boolean` | `false` | Whether the accordion panel starts expanded when `open` is omitted. |
|
|
25
25
|
| onOpenChange | `(open: boolean) => void` | `undefined` | Called with the next expanded state each time the accordion parent toggles. |
|
|
26
26
|
| notificationBadge | `boolean` | `false` | Overlays an unread dot on the leading icon. The dot itself is decorative; the state is folded into the control name as `"{label}, notifications"`. |
|
|
@@ -48,8 +48,8 @@ Destination row for a vertical side navigation rail. Shows a leading icon, label
|
|
|
48
48
|
- Do not use as a top or header nav link (`NavLink`). Nested accordion destinations use `NavigationSideSubItem`.
|
|
49
49
|
- Compose inside `NavigationSideGroup` (a `<nav>` list). This row is a list item; other HTML attributes (`aria-*`, `data-*`, `id`) go to the interactive control, and `className` is on the row wrapper.
|
|
50
50
|
- Renders as an anchor when `href` is set; otherwise a button. Accordion parents are **not** destinations: `href` is ignored and the control is always a button. Put a section landing page in a `NavigationSideSubItem` child instead.
|
|
51
|
-
- Set `activated` for the current page — fill and leading indicator. Destinations also set `aria-current="page"`; accordion parents do not. When a child is the current page, set `activated` on that child, not only on the parent.
|
|
52
|
-
- Set `accordion` for a parent that reveals `subNavigationItemsSlot` (or `children`): `NavigationSideSubItem` rows (`href` for destinations). Omit `open` for uncontrolled (`defaultOpen` + `onOpenChange`). The trigger is a button with `aria-expanded` / `aria-controls`; the nested list animates open and closed (inert and `aria-hidden` when collapsed). When `navCollapsed` is also true, those rows open in a disclosure flyout (`Menu` `pattern="disclosure"`, `direction="Right Top"`) as a `List` of interactive `ListItem`s. Keyboard: Enter/Space toggles; Tab moves through destinations; Tab-out and Escape close and return focus to the trigger.
|
|
51
|
+
- Set `activated` for the current page — fill and leading indicator. Destinations also set `aria-current="page"`; accordion parents do not. When a child is the current page, set `activated` on that child, not only on the parent. Collapsing the rail still shows the selected appearance on that accordion parent so the section remains visible on the icon-only rail.
|
|
52
|
+
- Set `accordion` for a parent that reveals `subNavigationItemsSlot` (or `children`): `NavigationSideSubItem` rows (`href` for destinations). Omit `open` for uncontrolled (`defaultOpen` + `onOpenChange`). The trigger is a button with `aria-expanded` / `aria-controls`; the nested list animates open and closed (inert and `aria-hidden` when collapsed). Collapsing the rail hides any open nested list (and moves keyboard focus to the parent if a nested row had it). Expanding restores that open state unless the flyout was dismissed while collapsed. Opening a disclosure flyout from the collapsed parent is still available. When `navCollapsed` is also true, those rows open in a disclosure flyout (`Menu` `pattern="disclosure"`, `direction="Right Top"`) as a `List` of interactive `ListItem`s. Keyboard: Enter/Space toggles; Tab moves through destinations; Tab-out and Escape close and return focus to the trigger.
|
|
53
53
|
- The leading icon is always shown. Group collapsed layout with `NavigationSideGroup` (`collapsed`) or set `navCollapsed`.
|
|
54
54
|
- When `navCollapsed`, the visible label is hidden; pass `label` (or `aria-label`) for the accessible name. A tooltip shows the label on hover and focus.
|
|
55
55
|
- When `notificationBadge` is true, the dot stays decorative; unread state is included in the control name (`"{label}, notifications"`). Override with `aria-label` when you need a different name.
|
|
@@ -14,7 +14,7 @@ Nested destination row under an accordion side-nav parent.
|
|
|
14
14
|
| leadingIcon | `boolean` | `true` | Renders the leading icon before the label. Set `false` for text-only nested rows, which is the usual look under an accordion parent. |
|
|
15
15
|
| leadingIconName | `string` | `"outbound"` | Material Symbol name for the leading icon. Ignored when `leadingIcon` is false. |
|
|
16
16
|
| iconVariant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Fill style for the leading icon: `sharpUnfilled` for the outline glyph, `sharpFilled` for the solid one. |
|
|
17
|
-
| activated | `boolean` | `false` | Marks this row as the current page: filled surface, leading indicator bar, and `aria-current="page"`. Set it here rather than on the accordion parent. |
|
|
17
|
+
| activated | `boolean` | `false` | Marks this row as the current page: filled surface, leading indicator bar, and `aria-current="page"`. Set it here rather than on the accordion parent. When the rail is collapsed, that parent also shows the selected appearance. |
|
|
18
18
|
| href | `string` | `undefined` | Destination URL, which renders the row as an anchor instead of a button. Omit for a button that only reports clicks through `onClick`. |
|
|
19
19
|
| className | `string` | `—` | |
|
|
20
20
|
|
|
@@ -34,6 +34,6 @@ Nested destination row under an accordion side-nav parent.
|
|
|
34
34
|
|
|
35
35
|
- Use as a child of an accordion `NavigationSideItem`, not as a top-level rail row (`NavigationSideItem`). Compose inside `NavigationSideGroup` so this row is a list item in the side `nav`.
|
|
36
36
|
- Renders as an anchor when `href` is set; otherwise a button. `className` is on the row wrapper; other HTML attributes (`aria-*`, `data-*`, `id`) go to the interactive control.
|
|
37
|
-
- Set `activated` for the current page — fill, leading indicator, and `aria-current="page"`.
|
|
37
|
+
- Set `activated` for the current page — fill, leading indicator, and `aria-current="page"`. When the rail is collapsed, the accordion parent also shows the selected appearance so the section remains visible on the icon-only rail.
|
|
38
38
|
- Set `leadingIcon={false}` to hide the icon.
|
|
39
|
-
- When the parent accordion is collapsed (`navCollapsed`), this row is presented as a `ListItem` in the disclosure flyout (a list of links, not a menu).
|
|
39
|
+
- When the parent accordion is collapsed (`navCollapsed`), this row is presented as a `ListItem` in the disclosure flyout (a list of links, not a menu). Collapsing the rail hides an open nested list; the parent can still open the flyout.
|
|
@@ -221,7 +221,12 @@ Use `List` + `ListItem` for menus and lists. Prefer `centerText` / `bottomText`
|
|
|
221
221
|
Prefer **`ListControls`** when each row has title/description plus an embedded trailing control (settings and exclusive choices). Page layout: harness [recipe-settings-page.md](../uxelle-design-harness/recipe-settings-page.md). Set **`controlType`** to **`switch`**, **`checkbox`**, or **`radio`**. Same selection roles as **`RadioGroup`** / **`CheckboxGroup`** for checkbox/radio, list layout instead of stacked form options. Use **`interactive`** **`ListItem`** rows with **`embedded`** Switch / Checkbox / Radio in **`trailing`**. Set **`dense`** on **`ListControls`** (or per **`ListItem`**) for compact row padding.
|
|
222
222
|
|
|
223
223
|
### Icon variants
|
|
224
|
-
Icons use `sharpFilled` or `sharpUnfilled`. Default is `sharpUnfilled`.
|
|
224
|
+
Icons use `sharpFilled` or `sharpUnfilled`. Default is `sharpUnfilled`. GPF chrome
|
|
225
|
+
names always resolve from `@uxelle/components`. Any other Material Symbol requires
|
|
226
|
+
`import "@uxelle/icons/register"` in the host (`@uxelle/a2ui` already does this).
|
|
227
|
+
Unknown names render no glyph (empty span, production-silent) — a visual-only miss
|
|
228
|
+
that a11y tests will not catch on icon-only buttons that already have `aria-label`.
|
|
229
|
+
Type product names with `UxelleIconName` from `@uxelle/icons`.
|
|
225
230
|
|
|
226
231
|
### Theme tokens
|
|
227
232
|
Generated app CSS uses `--uxl-color-switcher-*` and layout/page-chrome tokens. Do not use `--uxl-component-*` in app CSS (those tokens belong inside components). Focus rings on catalog controls already use `--uxl-color-switcher-interactive-icon`.
|
|
@@ -10,11 +10,11 @@ Card-styled readout for a headline figure with a label, optional qualifier, info
|
|
|
10
10
|
|
|
11
11
|
| Prop | Type | Default | Description |
|
|
12
12
|
|------|------|---------|-------------|
|
|
13
|
-
| order | `"labelFirst" \| "valueFirst"` | `"labelFirst"
|
|
14
|
-
| label | `ReactNode` | `—` | Label in the label row. Occupies remaining width beside the info control.
|
|
15
|
-
| value | `ReactNode` | `—` | Headline figure in the value row.
|
|
13
|
+
| order | `"labelFirst" \| "valueFirst"` | `"labelFirst"` | Vertical order of the label row and the value row. |
|
|
14
|
+
| label | `ReactNode` | `—` | Label in the label row. Occupies remaining width beside the info control and stays on one line: overflow ellipsizes. Hover or focus a truncated label to read the full name in a tooltip. A string (or number) is wrapped in **Text** with `type="Body Medium"`; pass a `Text` node for a different type (truncation is still applied). When you pass a `Text` or other `ReactNode` you own its accessibility: use meaningful text (not color or icon alone) and keep it non-interactive so it can name the group. |
|
|
15
|
+
| value | `ReactNode` | `—` | Headline figure in the value row. A string (or number) is wrapped in **Text** with `type="Display Small"` as `<p>`; pass a `Text` node for a different type. A `Text` keeps its `type` and is rendered as `<p>` so a grid of StatTiles does not become a heading outline. Any other `ReactNode` is allowed; make sure the figure reads as text and is not conveyed through color or an icon alone (WCAG 1.4.1). |
|
|
16
16
|
| qualifier | `boolean` | `true` | When true, allows the qualifier to render when content is present. |
|
|
17
|
-
| qualifierContent | `ReactNode` | `—` | Qualifier beside the value.
|
|
17
|
+
| qualifierContent | `ReactNode` | `—` | Qualifier beside the value. A string (or number) is wrapped in **Text** with `type="Body Medium"`; pass a `Text` node for a different type. Only rendered when `qualifier` is true and content is present. When you pass a `Text` or other `ReactNode`, ensure it reads as text; do not rely on color alone to distinguish comparison periods. |
|
|
18
18
|
| tooltipSlot | `boolean` | `true` | When true, allows the tooltip slot to render when content is present. |
|
|
19
19
|
| tooltipContent | `ReactNode` | `—` | Info control at the end of the label row (typically `Tooltip` wrapping `IconButton`). Only rendered when `tooltipSlot` is true and content is present. Icon-only triggers within this slot must carry an accessible name via `aria-label` on the interactive element (e.g. `<IconButton aria-label="More information" />`). |
|
|
20
20
|
| trailingSlot | `boolean` | `false` | When true, allows the trailing region to render when content is present. The slot accepts any content. |
|
|
@@ -70,7 +70,7 @@ Card-styled readout for a headline figure with a label, optional qualifier, info
|
|
|
70
70
|
// ReactNode override — caller owns accessibility (semantic element, text)
|
|
71
71
|
<StatTile
|
|
72
72
|
label={<Text type="Body Medium" width={false}>Fill rate</Text>}
|
|
73
|
-
value={<Text type="Display
|
|
73
|
+
value={<Text type="Display Small" as="p">94%</Text>}
|
|
74
74
|
/>
|
|
75
75
|
```
|
|
76
76
|
|
|
@@ -78,7 +78,7 @@ Card-styled readout for a headline figure with a label, optional qualifier, info
|
|
|
78
78
|
// Polling dashboard — aria-live on the value announces only the change
|
|
79
79
|
<StatTile
|
|
80
80
|
label="Active sessions"
|
|
81
|
-
value={<Text type="Display
|
|
81
|
+
value={<Text type="Display Small" as="p" aria-live="polite">{count}</Text>}
|
|
82
82
|
/>
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -111,40 +111,11 @@ Card-styled readout for a headline figure with a label, optional qualifier, info
|
|
|
111
111
|
|
|
112
112
|
## Notes
|
|
113
113
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
- a `
|
|
117
|
-
-
|
|
118
|
-
- `Text` passed as `value` is rendered as `<p>`.
|
|
119
|
-
- Pass a library `Tooltip` (typically wrapping `IconButton`) through
|
|
120
|
-
- `tooltipContent`. Toggle regions with `qualifier`, `tooltipSlot`, and
|
|
121
|
-
- `trailingSlot`; empty content is not rendered. `trailingSlotContent` is an
|
|
122
|
-
- open slot — any content is allowed. Surface, elevation, radius, and
|
|
123
|
-
- padding come from `Card`. StatTile is a standalone tile: place it next to
|
|
124
|
-
- other StatTiles in a grid. Do not wrap it in `Card`. A figure inside a chart
|
|
125
|
-
- card or table cell is a different surface — compose `Text` there.
|
|
126
|
-
- **Accessibility.** The root is a `role="group"` region. It is named
|
|
127
|
-
- automatically from `label` (via `aria-labelledby`), so the group is announced
|
|
128
|
-
- with context in both orders — including `"valueFirst"`, where the value
|
|
129
|
-
- precedes the label in the DOM. Supply your own `aria-label` or
|
|
130
|
-
- `aria-labelledby` to override the derived name; this is **required** when
|
|
131
|
-
- there is no `label` (e.g. `aria-label="Median first response time, 1 day 12
|
|
132
|
-
- hours"`) so the figure is not announced without context. In development,
|
|
133
|
-
- StatTile warns when content is present but the group has no name. The trailing
|
|
134
|
-
- slot is open, so its accessibility is the caller's responsibility — see
|
|
135
|
-
- `trailingSlotContent`.
|
|
136
|
-
- **Navigation.** Do not put `onClick` on StatTile — the root is a named group,
|
|
137
|
-
- not a control, and a wrapped link would nest interactives when a tooltip is
|
|
138
|
-
- present. Put the destination in `trailingSlotContent` as a `Link` or
|
|
139
|
-
- `IconButton`.
|
|
114
|
+
- `label`, `value`, and `qualifierContent` each accept a string (or number) or a **Text** node. A string is wrapped in that region's default `Text` type — no wrapper needed. Pass a `Text` when you need a different `type` or a live region. A `Text` passed as `value` keeps its `type` and is rendered as `<p>`. The label always truncates to one line so a row of tiles stays scannable; hover or focus a truncated label to read the full name (`Text` Body Small). This overflow tooltip is separate from `tooltipContent` (the info control).
|
|
115
|
+
- Pass a library `Tooltip` (typically wrapping `IconButton`) through `tooltipContent`. Toggle regions with `qualifier`, `tooltipSlot`, and `trailingSlot`; empty content is not rendered. `trailingSlotContent` is an open slot — any content is allowed. Surface, elevation, radius, and padding come from `Card`. StatTile is a standalone tile: place it next to other StatTiles in a grid. Do not wrap it in `Card`. A figure inside a chart card or table cell is a different surface — compose `Text` there.
|
|
116
|
+
- **Accessibility.** The root is a `role="group"` region. It is named automatically from `label` (via `aria-labelledby`), so the group is announced with context in both orders — including `"valueFirst"`, where the value precedes the label in the DOM. Supply your own `aria-label` or `aria-labelledby` to override the derived name; this is **required** when there is no `label` (e.g. `aria-label="Median first response time, 1 day 12 hours"`) so the figure is not announced without context. In development, StatTile warns when content is present but the group has no name. The trailing slot is open, so its accessibility is the caller's responsibility — see `trailingSlotContent`.
|
|
117
|
+
- **Navigation.** Do not put `onClick` on StatTile — the root is a named group, not a control, and a wrapped link would nest interactives when a tooltip is present. Put the destination in `trailingSlotContent` as a `Link` or `IconButton`.
|
|
140
118
|
- Set `order` to `"valueFirst"` to put the value row above the label row.
|
|
141
|
-
- The root fills its parent by default (`fullWidth`). Set `fullWidth={false}`
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
- (full-width rectangle) inside `SkeletonGroup`. Do not pass a skeleton as
|
|
145
|
-
- `value`.
|
|
146
|
-
- For polling dashboards where the value updates in place, prefer putting
|
|
147
|
-
- `aria-live="polite"` on the **value** node so only the changing figure is
|
|
148
|
-
- announced (a root-level `aria-live` also works but re-announces the whole
|
|
149
|
-
- group). When using a `string` `value`, wrap it yourself to place the live
|
|
150
|
-
- region precisely.
|
|
119
|
+
- The root fills its parent by default (`fullWidth`). Set `fullWidth={false}` to hug contents. Long value and qualifier copy wrap inside the tile; the label ellipsizes instead of wrapping.
|
|
120
|
+
- While data is loading, replace the tile with a `Skeleton` sized to the card (full-width rectangle) inside `SkeletonGroup`. Do not pass a skeleton as `value`.
|
|
121
|
+
- For polling dashboards where the value updates in place, prefer putting `aria-live="polite"` on the **value** node so only the changing figure is announced (a root-level `aria-live` also works but re-announces the whole group). When using a `string` `value`, wrap it yourself to place the live region precisely.
|
|
@@ -12,10 +12,11 @@ Peer dependencies: React 18 or 19.
|
|
|
12
12
|
npm install @uxelle/components @uxelle/themes
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Import the two stylesheets:
|
|
16
|
+
|
|
15
17
|
```tsx
|
|
16
|
-
import "@uxelle/components/
|
|
17
|
-
import "@uxelle/
|
|
18
|
-
import "@uxelle/themes/themes/open-source/open-source.css";
|
|
18
|
+
import "@uxelle/components/base.css";
|
|
19
|
+
import "@uxelle/themes/open-source.css";
|
|
19
20
|
|
|
20
21
|
import { Button } from "@uxelle/components";
|
|
21
22
|
|
|
@@ -24,22 +25,52 @@ function App() {
|
|
|
24
25
|
}
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
Then set the theme attributes on `<html>`:
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<html data-open-source="light" data-color-switcher="default"></html>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Both attributes are required. Every `--uxl-*` token is declared under
|
|
35
|
+
`[data-open-source="light"]` or `[data-open-source="dark"]`, so components render
|
|
36
|
+
unstyled without them. See [Themes](#themes) to switch modes at runtime.
|
|
37
|
+
|
|
38
|
+
`base.css` is the single component stylesheet. `@uxelle/components/styles.css`
|
|
39
|
+
(global baseline) and `@uxelle/components/index.css` (component rules)
|
|
40
|
+
stay exported if you need to load them separately.
|
|
28
41
|
|
|
29
42
|
### Next.js / SSR
|
|
30
43
|
|
|
31
|
-
- Import
|
|
44
|
+
- Import both stylesheets in `app/layout.tsx` (or a top-level provider). JS side effects will not style App Router.
|
|
32
45
|
- Published `@uxelle/components` JS is prefixed with `"use client"`. Importing any component places that file in the client graph.
|
|
33
46
|
- Pass `mobile={true}` or `mobile={false}` on `NavigationSide` so server and client markup match. Omit `mobile` only in client-only surfaces.
|
|
34
47
|
|
|
35
48
|
Optional: for an agent-driven UI surface, also install `@uxelle/a2ui`.
|
|
36
49
|
|
|
50
|
+
### Icons
|
|
51
|
+
|
|
52
|
+
`@uxelle/components` ships GPF chrome glyphs (`close`, `chevron_*`, `check`, and other names the library itself uses). For any other Material Symbol Sharp name, install `@uxelle/icons` and register once before the first `Icon` render:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install @uxelle/icons
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import "@uxelle/icons/register";
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`@uxelle/a2ui` registers the full catalog when you import it. Unknown names render no glyph (an empty span). Development warns; production is silent, so an icon-only control with `aria-label` can still pass a11y tests while showing nothing. Register `@uxelle/icons` before the first render, or type names with `UxelleIconName` from `@uxelle/icons`.
|
|
63
|
+
|
|
37
64
|
## Themes
|
|
38
65
|
|
|
39
|
-
Theme CSS is published as `@uxelle/themes` and generated from design tokens.
|
|
66
|
+
Theme CSS is published as `@uxelle/themes` and generated from design tokens. Quick Start covers the import and the two required attributes; this section covers changing them.
|
|
67
|
+
|
|
68
|
+
- `data-open-source` — `"light"` or `"dark"`
|
|
69
|
+
- `data-color-switcher` — `"default"`, `"default-subtle"`, `"success"`, `"warning"`, `"danger"`, or `"info"`
|
|
70
|
+
|
|
71
|
+
To drive both from React instead of hardcoding them, wrap the app with `UXelleThemeProvider`, which sets the attributes on `document.documentElement`:
|
|
40
72
|
|
|
41
73
|
```tsx
|
|
42
|
-
import "@uxelle/themes/themes/open-source/open-source.css";
|
|
43
74
|
import { UXelleThemeProvider } from "@uxelle/themes/react";
|
|
44
75
|
|
|
45
76
|
function AppShell({ children }: { children: React.ReactNode }) {
|
|
@@ -13,6 +13,10 @@ Hosts inject `uxelleCatalogSchema` (and optionally a recipe's messages) into the
|
|
|
13
13
|
agent prompt and render the result. Do not open package source to "discover" props —
|
|
14
14
|
use the catalog schema the host provides.
|
|
15
15
|
|
|
16
|
+
Importing `@uxelle/a2ui` registers the full Material Symbols Sharp catalog. React
|
|
17
|
+
hosts that do not use A2UI must `import "@uxelle/icons/register"` themselves if
|
|
18
|
+
generated UI uses icon names beyond GPF chrome.
|
|
19
|
+
|
|
16
20
|
## Hard constraints
|
|
17
21
|
|
|
18
22
|
- **Catalog adapters only.** No raw HTML, no custom components.
|
|
@@ -70,6 +74,11 @@ chips; a chip wider than its container ellipsizes so dismiss stays visible.
|
|
|
70
74
|
Exclusive `A2uiChoiceChip` selection is one checked value in host state (toggles,
|
|
71
75
|
not radios). Use `A2uiRadioGroup` or `A2uiSegmentedControl` for radio semantics.
|
|
72
76
|
|
|
77
|
+
`A2uiStatTile` labels stay on one line and ellipsize; hover or focus a truncated
|
|
78
|
+
label to read the full name. Pass `label` as a string — do not wrap it in
|
|
79
|
+
`A2uiText` or set truncation. Value and qualifier copy wrap. The overflow tooltip
|
|
80
|
+
is automatic and separate from `tooltipContent`.
|
|
81
|
+
|
|
73
82
|
Known gaps — substitute rather than invent:
|
|
74
83
|
|
|
75
84
|
| React | A2UI |
|
|
@@ -26,7 +26,7 @@ This file covers **composition**: landmarks, heading ranks, names, and live regi
|
|
|
26
26
|
- `aria-describedby` — extra help, not the name (`fieldDescription`, instructions).
|
|
27
27
|
- `aria-hidden="true"` — decorative / redundant graphics (default `Icon`).
|
|
28
28
|
- `aria-live="polite"` — status that appears without moving focus. `assertive` only for urgent interruptions.
|
|
29
|
-
- `aria-current="page"` — current item in nav (`NavLink`, or `activated` on `NavigationSideItem` / `NavigationSideSubItem` destinations — not accordion parents).
|
|
29
|
+
- `aria-current="page"` — current item in nav (`NavLink`, or `activated` on `NavigationSideItem` / `NavigationSideSubItem` destinations — not accordion parents). When the side rail is collapsed, an accordion parent of an activated nested row still shows the selected appearance so the current section remains visible on the icon-only rail.
|
|
30
30
|
- `aria-expanded` — only on a real disclosure control, not on every section.
|
|
31
31
|
- `aria-pressed` — toggle buttons (`IconButton` `activated`); `Switch` uses `checked` instead.
|
|
32
32
|
|
|
@@ -14,6 +14,10 @@ Load component and theme CSS as in
|
|
|
14
14
|
[getting-started.md](../uxelle-components/getting-started.md). Do not set
|
|
15
15
|
`font-family` in app CSS — `Text` uses theme tokens.
|
|
16
16
|
|
|
17
|
+
If generated UI uses Material Symbol names beyond GPF chrome (`home`, `mail`,
|
|
18
|
+
`campaign`, …), add `import "@uxelle/icons/register"` once at the app entry.
|
|
19
|
+
`@uxelle/a2ui` already registers the full catalog.
|
|
20
|
+
|
|
17
21
|
On `<html>`:
|
|
18
22
|
|
|
19
23
|
- Theme mode (host-owned): `data-open-source="light" | "dark"` (other themes use
|
|
@@ -32,7 +32,8 @@ sections
|
|
|
32
32
|
|
|
33
33
|
KPI and card grids reflow with `auto-fit` / `minmax` (no JS); the header stacks and
|
|
34
34
|
its actions go `fullWidth` below tablet; the primary `Table` scrolls horizontally
|
|
35
|
-
when narrow.
|
|
35
|
+
when narrow. StatTile labels ellipsize on one line so a KPI row stays scannable.
|
|
36
|
+
See [how-to-page-layout.md](how-to-page-layout.md#responsiveness).
|
|
36
37
|
|
|
37
38
|
## Spacing
|
|
38
39
|
|
|
@@ -49,7 +50,8 @@ KPIs rather than a dense monitoring surface — but pick one mode and hold it.
|
|
|
49
50
|
## A11y
|
|
50
51
|
|
|
51
52
|
One `main`, one `h1`. Name each region (KPIs `aria-label="Key metrics"`, the primary
|
|
52
|
-
surface by its heading). KPI deltas pair color with a sign or word.
|
|
53
|
+
surface by its heading). KPI deltas pair color with a sign or word. Truncated KPI
|
|
54
|
+
labels keep the full name on the group; hover or focus reveals it. Loading and empty
|
|
53
55
|
for the primary surface follow [states](recipe-states.md). See
|
|
54
56
|
[how-to-accessibility.md](how-to-accessibility.md).
|
|
55
57
|
|
|
@@ -24,6 +24,8 @@ A small set of headline numbers — revenue, active users, uptime, "10k+ teams."
|
|
|
24
24
|
- Do not put `onClick` on StatTile — put a `Link` or `IconButton` in
|
|
25
25
|
`trailingSlotContent`.
|
|
26
26
|
- Do not signal a delta with color alone — pair it with a sign or word.
|
|
27
|
+
- Do not wrap StatTile labels yourself. The label stays on one line and
|
|
28
|
+
ellipsizes; hover or focus a truncated label to read the full name.
|
|
27
29
|
|
|
28
30
|
## Regions
|
|
29
31
|
|
|
@@ -50,10 +52,10 @@ band on a `spacious` page it adds breathing with the **Band** step (`large-15`)
|
|
|
50
52
|
## A11y
|
|
51
53
|
|
|
52
54
|
Each figure and its label read together. StatTile names the group from `label`
|
|
53
|
-
automatically (including `valueFirst`)
|
|
54
|
-
|
|
55
|
-
keep the meaning in text, not
|
|
56
|
-
[how-to-accessibility.md](how-to-accessibility.md).
|
|
55
|
+
automatically (including `valueFirst`), including when the visible label is
|
|
56
|
+
ellipsized. If there is no label, set `aria-label` that combines the figure and
|
|
57
|
+
its meaning. If the trailing slot holds a delta, keep the meaning in text, not
|
|
58
|
+
color alone. See [how-to-accessibility.md](how-to-accessibility.md).
|
|
57
59
|
|
|
58
60
|
## Color
|
|
59
61
|
|