@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
@@ -18,6 +18,11 @@ Controls that filter, facet, search, or export the rows/cards currently in view.
18
18
  ## When not
19
19
 
20
20
  - Page-level actions (create, import, delete) belong to the [page-header](recipe-page-header.md).
21
+ - **Export here is view-scoped only.** This bar exports what the filters and search
22
+ currently leave on screen, so label it for that ("Export view"). Exporting the
23
+ *whole dataset* ignores this bar's controls and is a page action —
24
+ [page-header](recipe-page-header.md). Never put both on one page: pick the
25
+ scope the user actually needs.
21
26
  - Data tabs that swap which rows are shown sit above the query bar, first in the
22
27
  `Table` `topSlot` — not on this row.
23
28
  - No filter *fields* on the bar: a filter *trigger* opens a right `Sheet`.
@@ -33,14 +38,25 @@ row **below**.
33
38
  ## Responsive
34
39
 
35
40
  The bar stays a row of controls. When very tight, let the search field take the
36
- full line above the filter/export cluster; the applied `FilterChipGroup` wraps.
41
+ full line above the filter/export cluster; the applied `FilterChipGroup` wraps
42
+ whole chips. A chip wider than the row ellipsizes so dismiss stays visible.
37
43
  Keep the filter and export buttons together (`flexShrink={0}`).
38
44
 
45
+ Chip labels are component-owned: pass `label` on `ChoiceChip` / `FilterChip` — do
46
+ not wrap `Text`. Unchecked choice chips use Condensed; checked use Condensed Alt.
47
+ Filter chips use Condensed. Exclusive `ChoiceChip` selection is one checked value
48
+ in app state (`role="group"`); use `RadioGroup` or `SegmentedControl` for radio
49
+ semantics.
50
+
39
51
  ## Spacing
40
52
 
41
- `small-4` gap within and between the two clusters; the applied-chips row is
42
- `small-4` below. This whole stack lives in the table's `topSlot` at `small-4`, not
43
- the page-section gap ([spacing-steps.md](spacing-steps.md)).
53
+ The **Control** step throughout — within and between the two clusters, and for the
54
+ applied-chips row below. This whole stack lives in the table's `topSlot` at the
55
+ **Control** step, never the **Section** gap ([spacing-steps.md](spacing-steps.md)).
56
+
57
+ As a piece, it inherits the host experience's density mode: `micro-3` on a
58
+ `compact` data-table page (its usual home), `small-4` under `standard`
59
+ ([density.md](density.md)).
44
60
 
45
61
  ## A11y
46
62
 
@@ -92,7 +108,7 @@ See [how-to-accessibility.md](how-to-accessibility.md).
92
108
  />
93
109
  </Layout>
94
110
  <Layout flexShrink={0}>
95
- <Button emphasis="low"><Text type="Button" width>Export all</Text></Button>
111
+ <Button emphasis="low"><Text type="Button" width>Export view</Text></Button>
96
112
  </Layout>
97
113
  </Layout>
98
114
  </Layout>
@@ -37,8 +37,11 @@ scrolls when the labels overflow. See [how-to-page-layout.md](how-to-page-layout
37
37
 
38
38
  ## Spacing
39
39
 
40
- `medium-12` between page sections; `--uxl-breakpoints-gutter` between the main and
41
- aside columns; summary rows `small-4` ([spacing-steps.md](spacing-steps.md)).
40
+ **Density: `standard`**; step to `compact` when the record is a dense diagnostic
41
+ view (many fields scanned side by side) rather than a read-and-act page
42
+ ([density.md](density.md)). **Section** gap between page sections (`medium-12`);
43
+ **Control** for summary rows (`small-4`); `--uxl-breakpoints-gutter` between the
44
+ main and aside columns in every mode ([spacing-steps.md](spacing-steps.md)).
42
45
 
43
46
  ## A11y
44
47
 
@@ -38,7 +38,7 @@ Standalone fields (email, language, phone, about) stay in the section stack at `
38
38
 
39
39
  ## Spacing
40
40
 
41
- Page column: [how-to-page-layout.md](how-to-page-layout.md). Section gap: `medium-12`. Lockup internals: `micro-2`. Form field stack: `medium-8`. Inline related fields: `small-4`. Do not add extra padding around `ListControls`. Form actions: [how-to-page-layout.md](how-to-page-layout.md#action-clusters).
41
+ **Density: `standard`** — settings are read and decided on, so comprehension beats volume; do not compact a preferences page ([density.md](density.md)). Page column: [how-to-page-layout.md](how-to-page-layout.md). **Section** gap `medium-12`. **Tight** lockup internals `micro-2`. **Group** form field stack `medium-8`. **Control** inline related fields `small-4`. Do not add extra padding around `ListControls` — its row rhythm is component-owned. Form actions: [how-to-page-layout.md](how-to-page-layout.md#action-clusters).
42
42
 
43
43
  ## A11y
44
44
 
@@ -65,7 +65,7 @@ Import from `@uxelle/components`. Pass `bottomText` (or `""`) so the catalog dem
65
65
  <Lockup
66
66
  topSlot={false}
67
67
  title={
68
- <Text type="Display Extra Small" as="h1" width={false}>
68
+ <Text type="Display Small" as="h1" width={false}>
69
69
  Settings
70
70
  </Text>
71
71
  }
@@ -163,7 +163,7 @@ Import from `@uxelle/components`. Pass `bottomText` (or `""`) so the catalog dem
163
163
  </Layout>
164
164
  ```
165
165
 
166
- If the host already renders `<main>` and the page column (skip-link target), omit `as="main"` and extra `p` on this stack — still set `maxWidth="600px"` on the settings column (or on the host column when this is the only page in view).
166
+ If chrome already renders `<main>` (the skip-link target), omit `as="main"` — but still render this column yourself, `p` and `maxWidth="600px"` included. Chrome supplies only the scrollport, never a column, so there is nothing to avoid duplicating ([how-to-page-layout.md](how-to-page-layout.md#who-owns-the-content-column)).
167
167
 
168
168
  ## A2UI
169
169
 
@@ -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
 
@@ -38,17 +40,22 @@ its track. A row variant can use vertical `Divider`s between cells that simply w
38
40
 
39
41
  ## Spacing
40
42
 
41
- `gap="var(--uxl-breakpoints-gutter)"` between cells. As a marketing band, add
42
- section breathing with `large-13`+ block padding
43
+ `gap="var(--uxl-breakpoints-gutter)"` between cells — the grid gap is
44
+ density-invariant, so KPI tiles align identically in every mode.
45
+
46
+ This piece serves both ends of the density range and inherits the host's mode
47
+ ([density.md](density.md)). As dashboard KPIs on a `compact` page it takes no band
48
+ padding at all and sits at the page's `medium-9` **Section** gap. As a marketing
49
+ band on a `spacious` page it adds breathing with the **Band** step (`large-15`)
43
50
  ([spacing-steps.md](spacing-steps.md)).
44
51
 
45
52
  ## A11y
46
53
 
47
54
  Each figure and its label read together. StatTile names the group from `label`
48
- automatically (including `valueFirst`). If there is no label, set `aria-label`
49
- that combines the figure and its meaning. If the trailing slot holds a delta,
50
- keep the meaning in text, not color alone. See
51
- [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).
52
59
 
53
60
  ## Color
54
61
 
@@ -69,7 +76,7 @@ Plain figures (marketing proof band):
69
76
  gap="var(--uxl-breakpoints-gutter)"
70
77
  aria-label="By the numbers"
71
78
  >
72
- <Layout display="flex" flexDirection="column" gap="var(--uxl-theme-layout-spacing-micro-2)">
79
+ <Layout display="flex" flexDirection="column" gap="var(--uxl-theme-layout-spacing-micro-3)">
73
80
  <Text type="Display Medium" as="p" width={false}>10k+</Text>
74
81
  <Text type="Body Small" width={false}>Teams onboarded</Text>
75
82
  </Layout>
@@ -19,8 +19,10 @@ Any region backed by data or an async action: lists, tables, cards, forms, panel
19
19
  - Do not blank the whole page for a partial load — scope the state to the region.
20
20
  - Do not signal status with color alone; pair with an icon or words
21
21
  ([how-to-color.md](how-to-color.md)).
22
- - Do not swap a `SkeletonGroup` out of the tree while loading — keep it mounted and
23
- toggle `loading`.
22
+ - Do not swap a `SkeletonGroup` out of the tree while loading. Keep **the group**
23
+ mounted across the whole load and toggle its `loading` prop; swapping its
24
+ *children* between shapes and real content is expected (see the example).
25
+ Unmounting the group loses the load/complete announcement.
24
26
 
25
27
  ## Loading
26
28
 
@@ -68,7 +70,10 @@ where the data would be, plus the action that creates the first item.
68
70
  ## Error
69
71
 
70
72
  A recoverable, in-flow failure uses a non-dismissible `danger` `Banner` with a retry
71
- action.
73
+ action. The single action passes no `direction` — row is the `ButtonGroup` default
74
+ and one child looks the same either way. Add a second text button (a Dismiss beside
75
+ Try again) and the cluster takes the tablet switch like any other
76
+ ([how-to-page-layout.md](how-to-page-layout.md#action-clusters)).
72
77
 
73
78
  ```tsx
74
79
  <Banner
@@ -77,7 +82,7 @@ action.
77
82
  alert
78
83
  leadingSlotContent={<Icon iconName="error" variant="sharpUnfilled" aria-hidden />}
79
84
  actionsSlotContent={
80
- <ButtonGroup direction="row" aria-label="Error actions">
85
+ <ButtonGroup aria-label="Error actions">
81
86
  <Button emphasis="medium" onClick={retry}>
82
87
  <Text type="Button" width>Try again</Text>
83
88
  </Button>
@@ -33,9 +33,11 @@ long, stack each pair (label above value) below tablet by switching
33
33
 
34
34
  ## Spacing
35
35
 
36
- Row/column `gap` = `var(--uxl-theme-layout-spacing-small-4)`. Reset the browser
37
- `dd` indent with `margin: 0`. Group inside a section at the page rhythm
38
- ([spacing-steps.md](spacing-steps.md)).
36
+ Row/column `gap` = the **Control** step
37
+ (`var(--uxl-theme-layout-spacing-small-4)` under `standard`, `micro-3` under
38
+ `compact` — a key/value summary is a common dense surface). Reset the browser `dd`
39
+ indent with `margin: 0`. Group inside a section at the page rhythm
40
+ ([spacing-steps.md](spacing-steps.md), [density.md](density.md)).
39
41
 
40
42
  ## A11y
41
43
 
@@ -32,6 +32,12 @@ narration.
32
32
  ([how-to-page-layout.md](how-to-page-layout.md#responsiveness)).
33
33
  5. **Spacing** — stacks use `var(--uxl-theme-layout-spacing-*)` (or `0`); page
34
34
  chrome uses the breakpoint tokens ([spacing-steps.md](spacing-steps.md)).
35
+ Name spacing by **role** (Flush / Tight / Control / Group / Section / Band), not
36
+ by a bare step. An **experience** declares its default **density mode**
37
+ (`compact` | `standard` | `spacious`) and why; a **piece** says it inherits the
38
+ host's mode and gives the resolution for the modes it realistically appears in.
39
+ Call out anything density-invariant (component-owned padding, grid gutters)
40
+ ([density.md](density.md)).
35
41
  6. **A11y** — landmarks, heading ranks, names, live regions
36
42
  ([how-to-accessibility.md](how-to-accessibility.md)).
37
43
  7. **Color** — include when the recipe uses palettes or brand bands: set
@@ -32,8 +32,10 @@ A single testimonial is a centered, measure-capped block. A set reflows with
32
32
 
33
33
  ## Spacing
34
34
 
35
- `small-4` between the quote and attribution; `--uxl-breakpoints-gutter` between cards
36
- in a grid; `large-13`+ block padding as a band ([spacing-steps.md](spacing-steps.md)).
35
+ **Control** step between the quote and its attribution (`small-6` on the `spacious`
36
+ marketing page, `small-4` under `standard`); `--uxl-breakpoints-gutter` between
37
+ cards in a grid in every mode; the **Band** step (`large-15`) as a band
38
+ ([density.md](density.md), [spacing-steps.md](spacing-steps.md)).
37
39
 
38
40
  ## A11y
39
41
 
@@ -54,7 +56,7 @@ associated. A customer `Logo` is decorative when the name is in text
54
56
  </Text>
55
57
  </blockquote>
56
58
  <figcaption>
57
- <Layout display="flex" flexDirection="column" gap="var(--uxl-theme-layout-spacing-micro-2)">
59
+ <Layout display="flex" flexDirection="column" gap="var(--uxl-theme-layout-spacing-micro-3)">
58
60
  <Text type="Body Small Alt" width={false}>Dana Lee</Text>
59
61
  <Text type="Condensed" width={false}>VP Operations, Northwind</Text>
60
62
  </Layout>
@@ -18,16 +18,24 @@ number"). The size band must match the index, so `medium-10` exists but
18
18
 
19
19
  ## Choosing a step
20
20
 
21
+ Do not pick a step directly. Pick the **role** the space plays, then resolve it
22
+ through the experience's **density mode** — [density.md](density.md).
23
+
21
24
  - **Flush** (line boxes already separate lines, e.g. name over email) -> `0`.
22
- - **Tight stacks / chips** -> `micro-2`.
23
- - **Related controls / field stacks** -> `small-4`. Same-row clusters (search +
25
+ - **Tight** stacks / chips / lockup internals.
26
+ - **Control** — related controls and field stacks. Same-row clusters (search +
24
27
  export, filter + facet) use this gap and stay `nowrap`.
25
- - **Card / section padding** (also the default A2UI gap) -> `medium-8`.
26
- - **Page-section gap** (lockup vs table vs a later block) -> `medium-12`.
27
- - **Hero / extra breathing inside a section** -> `large-13`+.
28
+ - **Group** — bespoke section padding and subgroups (also the default A2UI gap).
29
+ - **Section** — between page sections (lockup vs table vs a later block).
30
+ - **Band** — block padding on a full-bleed band (hero, CTA).
31
+
32
+ The `standard` mode resolves these to `0` / `micro-2` / `small-4` / `medium-8` /
33
+ `medium-12` / `large-13` — the harness baseline. `compact` shifts the column down
34
+ for data-dense product surfaces, `spacious` up for marketing. Resolve the whole
35
+ column from one mode; never tighten a single role in isolation.
28
36
 
29
- Do not use the page-section gap (`medium-12`) between a table's tabs and its grid —
30
- those belong together at `small-4`.
37
+ Do not use the **Section** gap between a table's tabs and its grid — those belong
38
+ together at the **Control** gap.
31
39
 
32
40
  ## Usage
33
41
 
@@ -50,7 +58,8 @@ emit them in new generated UI** — use the indexed tokens.
50
58
  ## Not part of this ramp
51
59
 
52
60
  Page inset, column cap, and column/`fr` gaps are **page chrome**, not ramp steps:
53
- `--uxl-breakpoints-margin` / `-max-container-width` / `-gutter`. See
61
+ `--uxl-breakpoints-margin` / `-max-container-width` / `-gutter`. They are also
62
+ **density-invariant** — they do not change with the mode ([density.md](density.md)). See
54
63
  [how-to-page-layout.md](how-to-page-layout.md) and [tokens.md](tokens.md). One-column
55
64
  reading content (a settings/form page, or a form / FAQ / prose section on a wider
56
65
  page) may cap at the `maxWidth="600px"` reading measure — centered — instead of the
@@ -38,8 +38,10 @@ Never hardcode hex/rgb for themeable UI. Palette selection (`default`,
38
38
  ## Spacing (layout ramp)
39
39
 
40
40
  Stacks on `Layout` / `A2uiLayout` pass `0` or `var(--uxl-theme-layout-spacing-*)`
41
- on `gap` / padding / margin. The full 0-16 ramp and how to choose a step is in
42
- [spacing-steps.md](spacing-steps.md). Set `display="flex"` (or `grid`) when using `gap`.
41
+ on `gap` / padding / margin. The full 0-16 ramp and the spacing **roles** are in
42
+ [spacing-steps.md](spacing-steps.md); which step each role resolves to depends on
43
+ the experience's **density mode** ([density.md](density.md)). Set `display="flex"`
44
+ (or `grid`) when using `gap`.
43
45
 
44
46
  ## Page chrome (React app/page body)
45
47
 
@@ -50,6 +52,13 @@ Usage in [how-to-page-layout.md](how-to-page-layout.md).
50
52
  - `--uxl-breakpoints-margin` — padding around the body
51
53
  - `--uxl-breakpoints-gutter` — gap between columns / `fr` tracks
52
54
 
55
+ `--uxl-breakpoints-padding-<band>-<index>` is the per-breakpoint source the spacing
56
+ ramp aliases (`--uxl-theme-layout-spacing-medium-8` resolves to
57
+ `--uxl-breakpoints-padding-medium-8`). Use the `--uxl-theme-layout-spacing-*` name
58
+ in app and recipe CSS; the `padding` family appears only where a catalog component
59
+ documents its own band padding (e.g. `Footer` —
60
+ [recipe-app-chrome.md](recipe-app-chrome.md)). Same index rule applies.
61
+
53
62
  Breakpoint bounds (read-only, for the rare JS switch) are exposed as
54
63
  `--uxl-theme-layout-{mobile,tablet,desktop,desktop-plus}-screen-width-{min,max}`,
55
64
  and the active band as `--uxl-breakpoints-screen-width-{min,max}`. Reference these
@@ -71,12 +80,44 @@ must, compose a `box-shadow` from levels `1`-`3` at depths `1`-`4`:
71
80
  ## Typography
72
81
 
73
82
  Render copy with the `Text` component (`type="Display Small"`, `Body Medium`,
74
- `Button`, …) and its `as` prop — never set font-size in app CSS. Font-family
75
- variables exist for custom chrome only:
83
+ `Button`, …) and its `as` prop — never set font-size in app CSS. Which `type` a
84
+ heading rank gets depends on the density mode ([density.md](density.md)).
85
+ Font-family variables exist for custom chrome only:
76
86
 
77
87
  - `--uxl-component-text-font-family-display`
78
88
  - `--uxl-component-text-font-family-body`
79
89
 
90
+ ### `width` on `Text`
91
+
92
+ `width` defaults to `true` and makes the text box **hug its content**;
93
+ `width={false}` makes it **span its container**, which is what lets long copy wrap
94
+ and `truncation` clip to a stable width.
95
+
96
+ - **`width={false}`** for anything that wraps or truncates — headings, body copy,
97
+ descriptions, `Lockup` slots, `Dialog` titles and bodies.
98
+ - **`width`** (the default) for a short label inside a control — `type="Button"`
99
+ labels, chips, badges — so the control sizes to its text.
100
+
101
+ Chip labels are **component-owned**. Pass the `label` string on `ChoiceChip` /
102
+ `FilterChip` (and their A2UI adapters) — do not wrap a `Text` node.
103
+
104
+ - **ChoiceChip** — `Condensed` when unchecked, `Condensed Alt` when checked.
105
+ Exclusive single-select is one checked value in app/host state. Keep
106
+ `role="group"`; chips stay `aria-pressed` toggles. Use `RadioGroup` or
107
+ `SegmentedControl` for radio semantics.
108
+ - **FilterChip** — `Condensed`. Labels hug content so `FilterChipGroup` wraps
109
+ whole chips. A chip wider than its container ellipsizes so the dismiss
110
+ control stays visible.
111
+
112
+ ## Inline `style` on the React track
113
+
114
+ React recipes may use inline `style` for what `Layout` props do not express —
115
+ a scrollport (`overflow`, `minHeight`), a `backgroundColor` on a palette region, or
116
+ native `dl` grid tracks — **provided every value is a `--uxl-*` variable**. Inline
117
+ `style` is not a licence to hardcode: no hex, no px, no font-size. The "no
118
+ `className` / `style`" rule is **A2UI-only**, where styling must come from adapter
119
+ props ([a2ui.md](a2ui.md)).
120
+
80
121
  ## Component tokens
81
122
 
82
123
  `--uxl-component-<component>-*` tokens style a specific component from inside that