@uni-design-system/uni-mcp 10.2.1 → 10.4.0

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.
@@ -7,16 +7,16 @@ import { z } from "zod";
7
7
  // src/data/uni-index.json
8
8
  var uni_index_default = {
9
9
  meta: {
10
- version: "10.2.1",
11
- builtAt: "2026-09-01T22:40:17.762Z",
10
+ version: "10.4.0",
11
+ builtAt: "2026-09-04T18:00:08.990Z",
12
12
  frameworks: [
13
13
  "angular"
14
14
  ],
15
15
  counts: {
16
16
  components: 84,
17
- tokens: 454,
17
+ tokens: 458,
18
18
  themes: 2,
19
- examples: 225
19
+ examples: 229
20
20
  }
21
21
  },
22
22
  components: [
@@ -27,7 +27,7 @@ var uni_index_default = {
27
27
  summary: "",
28
28
  description: "",
29
29
  category: "feedback",
30
- version: "10.2.1",
30
+ version: "10.4.0",
31
31
  bindings: {
32
32
  angular: {
33
33
  importPath: "@uni-design-system/uni-angular",
@@ -117,7 +117,7 @@ var uni_index_default = {
117
117
  summary: "Horizontal application bar: project leading controls (menu button, logo) with the `leading` attribute, actions with `trailing` (pushed to the far edge), and either pass `title` or project custom center content.",
118
118
  description: "Horizontal application bar: project leading controls (menu button, logo) with the `leading` attribute, actions with `trailing` (pushed to the far edge), and either pass `title` or project custom center content. Surface, divider, height, typography and spacing all resolve from `appBar` tokens. Place it inside your page's `<header>` landmark.",
119
119
  category: "components",
120
- version: "10.2.1",
120
+ version: "10.4.0",
121
121
  bindings: {
122
122
  angular: {
123
123
  importPath: "@uni-design-system/uni-angular",
@@ -190,7 +190,7 @@ var uni_index_default = {
190
190
  summary: "Identity avatar with a graceful fallback chain: image \u2192 initials from `name` \u2192 themed symbol.",
191
191
  description: "Identity avatar with a graceful fallback chain: image \u2192 initials from `name` \u2192 themed symbol. Coloring, radius, typeface and sizes all resolve from `avatar` theme tokens; `variant` picks the container palette.",
192
192
  category: "components",
193
- version: "10.2.1",
193
+ version: "10.4.0",
194
194
  bindings: {
195
195
  angular: {
196
196
  importPath: "@uni-design-system/uni-angular",
@@ -285,7 +285,7 @@ var uni_index_default = {
285
285
  summary: "Overlapping stack of avatars.",
286
286
  description: "Overlapping stack of avatars. `max` collapses the overflow into a themed \u201C+N\u201D chip (itself a `uni-avatar`). Overlap and separator ring resolve from `avatarGroup` theme tokens.",
287
287
  category: "components",
288
- version: "10.2.1",
288
+ version: "10.4.0",
289
289
  bindings: {
290
290
  angular: {
291
291
  importPath: "@uni-design-system/uni-angular",
@@ -334,7 +334,7 @@ var uni_index_default = {
334
334
  summary: "",
335
335
  description: "",
336
336
  category: "primitives",
337
- version: "10.2.1",
337
+ version: "10.4.0",
338
338
  bindings: {
339
339
  angular: {
340
340
  importPath: "@uni-design-system/uni-angular",
@@ -415,7 +415,7 @@ var uni_index_default = {
415
415
  summary: "",
416
416
  description: "",
417
417
  category: "feedback",
418
- version: "10.2.1",
418
+ version: "10.4.0",
419
419
  bindings: {
420
420
  angular: {
421
421
  importPath: "@uni-design-system/uni-angular",
@@ -512,7 +512,7 @@ var uni_index_default = {
512
512
  summary: "",
513
513
  description: "",
514
514
  category: "directives",
515
- version: "10.2.1",
515
+ version: "10.4.0",
516
516
  bindings: {
517
517
  angular: {
518
518
  importPath: "@uni-design-system/uni-angular",
@@ -536,7 +536,7 @@ var uni_index_default = {
536
536
  summary: 'The base layout primitive, applied as an attribute to any element so semantics stay yours: `<main box-layout [grow]="1" padding="md">`.',
537
537
  description: 'The base layout primitive, applied as an attribute to any element so semantics stay yours: `<main box-layout [grow]="1" padding="md">`. It is a directive, so it composes freely \u2014 with another layout attribute (`<div stack-layout uni-text="body-1-long">`) and with a component\'s own host element (`<uni-card box-layout padding="lg">`); Angular merges the host `class` bindings rather than letting one win. Sizing convention (height/width/min/max/inset): a **number is px and needs a binding** \u2014 `[height]="420"`; a **plain attribute is a CSS length string** \u2014 `height="420px"`. Spacing/radius/color inputs take theme tokens.',
538
538
  category: "layout",
539
- version: "10.2.1",
539
+ version: "10.4.0",
540
540
  bindings: {
541
541
  angular: {
542
542
  importPath: "@uni-design-system/uni-angular",
@@ -942,7 +942,7 @@ var uni_index_default = {
942
942
  summary: 'WAI-ARIA breadcrumb: a `nav` landmark wrapping an ordered list; the last item is the current page (`aria-current="page"`), separators are decorative.',
943
943
  description: 'WAI-ARIA breadcrumb: a `nav` landmark wrapping an ordered list; the last item is the current page (`aria-current="page"`), separators are decorative. Items with `href` render as real links; without one they render as link-styled buttons emitting `itemClicked` \u2014 wire that to your router.',
944
944
  category: "components",
945
- version: "10.2.1",
945
+ version: "10.4.0",
946
946
  bindings: {
947
947
  angular: {
948
948
  importPath: "@uni-design-system/uni-angular",
@@ -1027,7 +1027,7 @@ var uni_index_default = {
1027
1027
  summary: "",
1028
1028
  description: "",
1029
1029
  category: "primitives",
1030
- version: "10.2.1",
1030
+ version: "10.4.0",
1031
1031
  bindings: {
1032
1032
  angular: {
1033
1033
  importPath: "@uni-design-system/uni-angular",
@@ -1186,7 +1186,7 @@ var uni_index_default = {
1186
1186
  summary: "",
1187
1187
  description: "",
1188
1188
  category: "primitives",
1189
- version: "10.2.1",
1189
+ version: "10.4.0",
1190
1190
  bindings: {
1191
1191
  angular: {
1192
1192
  importPath: "@uni-design-system/uni-angular",
@@ -1218,7 +1218,7 @@ var uni_index_default = {
1218
1218
  summary: "Inline month calendar: single-date or start\u2013end range selection, day markers (availability dots), min/max fences and disabled dates.",
1219
1219
  description: "Inline month calendar: single-date or start\u2013end range selection, day markers (availability dots), min/max fences and disabled dates. One tab stop with a roving-tabindex `role=\"grid\"`; every day is a real button named with its full date. Values are plain ISO strings (`'YYYY-MM-DD'`), never `Date` objects, so bindings are timezone-free and serializable. Selection and today colours come from the theme's `primary` role pair; geometry and glyphs come from the `calendar` theme entry.",
1220
1220
  category: "forms",
1221
- version: "10.2.1",
1221
+ version: "10.4.0",
1222
1222
  bindings: {
1223
1223
  angular: {
1224
1224
  importPath: "@uni-design-system/uni-angular",
@@ -1452,7 +1452,7 @@ var uni_index_default = {
1452
1452
  summary: "Anchored coach-mark panel that dims the page and cuts a spotlight hole around its target.",
1453
1453
  description: 'Anchored coach-mark panel that dims the page and cuts a spotlight hole around its target. Both the scrim and the panel are `popover="manual"` elements shown in order, so they stack deterministically in the top layer above every app z-index, and every scrim piece is CSS-anchor-positioned to the target \u2014 the hole tracks scroll/resize/layout with zero listeners. The panel is a non-modal `role="dialog"` (deliberately no `aria-modal`): focus moves into it on open, Tab runs a "duet loop" over the panel\'s focusables plus the spotlit target while it stays interactive, and on close focus returns to the pre-open element \u2014 unless the user moved into the target, where it stays. Storage-free by rule: `key` and the `dismissed` output are the "don\'t show again" hooks; persistence is the app\'s business (e.g. cdk local-storage).',
1454
1454
  category: "components",
1455
- version: "10.2.1",
1455
+ version: "10.4.0",
1456
1456
  bindings: {
1457
1457
  angular: {
1458
1458
  importPath: "@uni-design-system/uni-angular",
@@ -1672,7 +1672,7 @@ var uni_index_default = {
1672
1672
  summary: "",
1673
1673
  description: "",
1674
1674
  category: "layout",
1675
- version: "10.2.1",
1675
+ version: "10.4.0",
1676
1676
  bindings: {
1677
1677
  angular: {
1678
1678
  importPath: "@uni-design-system/uni-angular",
@@ -1734,7 +1734,7 @@ var uni_index_default = {
1734
1734
  summary: "",
1735
1735
  description: "",
1736
1736
  category: "layout",
1737
- version: "10.2.1",
1737
+ version: "10.4.0",
1738
1738
  bindings: {
1739
1739
  angular: {
1740
1740
  importPath: "@uni-design-system/uni-angular",
@@ -1775,7 +1775,7 @@ var uni_index_default = {
1775
1775
  summary: "",
1776
1776
  description: "",
1777
1777
  category: "layout",
1778
- version: "10.2.1",
1778
+ version: "10.4.0",
1779
1779
  bindings: {
1780
1780
  angular: {
1781
1781
  importPath: "@uni-design-system/uni-angular",
@@ -1832,7 +1832,7 @@ var uni_index_default = {
1832
1832
  summary: "",
1833
1833
  description: "",
1834
1834
  category: "layout",
1835
- version: "10.2.1",
1835
+ version: "10.4.0",
1836
1836
  bindings: {
1837
1837
  angular: {
1838
1838
  importPath: "@uni-design-system/uni-angular",
@@ -1887,7 +1887,7 @@ var uni_index_default = {
1887
1887
  summary: "",
1888
1888
  description: "",
1889
1889
  category: "forms",
1890
- version: "10.2.1",
1890
+ version: "10.4.0",
1891
1891
  bindings: {
1892
1892
  angular: {
1893
1893
  importPath: "@uni-design-system/uni-angular",
@@ -2063,7 +2063,7 @@ var uni_index_default = {
2063
2063
  summary: "Form-bound, closed-set, single-select autocomplete: `FormValueControl<T | null>` over object `Options<T>`, type-to-filter, commit-on-select.",
2064
2064
  description: "Form-bound, closed-set, single-select autocomplete: `FormValueControl<T | null>` over object `Options<T>`, type-to-filter, commit-on-select. Typing produces a draft \u2014 a filter, never a value; the value changes only when an option commits, `clear()` runs, or the model is written from outside. Select semantics, not search: a real label, a chevron, no magnifier, nothing submits. For short lists with no need to type, prefer `uni-select` \u2014 the value contract is identical, so swapping is a template-only change.",
2065
2065
  category: "forms",
2066
- version: "10.2.1",
2066
+ version: "10.4.0",
2067
2067
  bindings: {
2068
2068
  angular: {
2069
2069
  importPath: "@uni-design-system/uni-angular",
@@ -2342,7 +2342,7 @@ emptyText="No countries found"
2342
2342
  summary: "",
2343
2343
  description: "",
2344
2344
  category: "feedback",
2345
- version: "10.2.1",
2345
+ version: "10.4.0",
2346
2346
  bindings: {
2347
2347
  angular: {
2348
2348
  importPath: "@uni-design-system/uni-angular",
@@ -2389,7 +2389,7 @@ emptyText="No countries found"
2389
2389
  summary: "",
2390
2390
  description: "",
2391
2391
  category: "forms",
2392
- version: "10.2.1",
2392
+ version: "10.4.0",
2393
2393
  bindings: {
2394
2394
  angular: {
2395
2395
  importPath: "@uni-design-system/uni-angular",
@@ -2488,7 +2488,7 @@ emptyText="No countries found"
2488
2488
  summary: "",
2489
2489
  description: "",
2490
2490
  category: "data",
2491
- version: "10.2.1",
2491
+ version: "10.4.0",
2492
2492
  bindings: {
2493
2493
  angular: {
2494
2494
  importPath: "@uni-design-system/uni-angular",
@@ -2728,7 +2728,7 @@ emptyText="No countries found"
2728
2728
  summary: "Date field with free-typed parsing and a popup calendar.",
2729
2729
  description: "Date field with free-typed parsing and a popup calendar. Type `aug 20`, `8/20/2026` or `2026-08-20`, or pick from the grid \u2014 the form gets the same canonical `'YYYY-MM-DD'` string either way. Parsing is `Intl`-driven (locale digit order and month names, never hardcoded); unreadable text stays in the field, flagged, with a `rejected` event. The popup is a native popover hosting the same `uni-calendar` an app could render inline.",
2730
2730
  category: "forms",
2731
- version: "10.2.1",
2731
+ version: "10.4.0",
2732
2732
  bindings: {
2733
2733
  angular: {
2734
2734
  importPath: "@uni-design-system/uni-angular",
@@ -2952,7 +2952,7 @@ emptyText="No countries found"
2952
2952
  summary: "One field for a date and a time: a thin composer seating a uni-date-input and a uni-time-input in one input-box chrome under one label, yielding one combined `'YYYY-MM-DDTHH:mm'` value.",
2953
2953
  description: "One field for a date and a time: a thin composer seating a uni-date-input and a uni-time-input in one input-box chrome under one label, yielding one combined `'YYYY-MM-DDTHH:mm'` value. The value emits only when both parts are set \u2014 a time without a day is not an answer \u2014 and clearing the date clears it. With `slotsFor`, the time part stays disabled until a day is chosen and offers exactly that day's slots: the scheduling flow in one attribute. Two honest tab stops (it is two questions); apps needing a different arrangement compose the primitives directly.",
2954
2954
  category: "forms",
2955
- version: "10.2.1",
2955
+ version: "10.4.0",
2956
2956
  bindings: {
2957
2957
  angular: {
2958
2958
  importPath: "@uni-design-system/uni-angular",
@@ -3138,7 +3138,7 @@ emptyText="No countries found"
3138
3138
  summary: "Text input that emits `change` only after the user pauses typing.",
3139
3139
  description: "Text input that emits `change` only after the user pauses typing. Wears the shared input chrome (themed color, border, typeface, focus ring) via `uni-input-box`; project adornments with the `pre-input` / `post-input` slots, matching `uni-input`'s convention. The ARIA passthrough inputs let a wrapping composite (e.g. SearchInput's combobox) annotate the real input element.",
3140
3140
  category: "forms",
3141
- version: "10.2.1",
3141
+ version: "10.4.0",
3142
3142
  bindings: {
3143
3143
  angular: {
3144
3144
  importPath: "@uni-design-system/uni-angular",
@@ -3283,10 +3283,10 @@ emptyText="No countries found"
3283
3283
  id: "dialog",
3284
3284
  name: "Dialog",
3285
3285
  status: "stable",
3286
- summary: "",
3287
- description: "",
3286
+ summary: "Modal dialog on the native `<dialog>` element, laid out as three rows: an optional `[dialog-header]`, the projected body, an optional `[dialog-buttons]`.",
3287
+ description: "Modal dialog on the native `<dialog>` element, laid out as three rows: an optional `[dialog-header]`, the projected body, an optional `[dialog-buttons]`. **The surface is never the scroll container.** It is a flex column that is `overflow: clip` on both axes; the header and buttons pin while only the body row scrolls. Unlike the drawer, which is deliberately viewport-tall, the dialog stays content-sized: it has no `height`, and grows until it hits `calc(100dvh - 2 x inset)` \u2014 the point at which the body starts to scroll. The theme's `padding` insets all three rows (which is what makes the default header read as a pill floating inside the surface); `bodyPadding` pads the scrolling row alone.",
3288
3288
  category: "feedback",
3289
- version: "10.2.1",
3289
+ version: "10.4.0",
3290
3290
  bindings: {
3291
3291
  angular: {
3292
3292
  importPath: "@uni-design-system/uni-angular",
@@ -3351,11 +3351,68 @@ emptyText="No countries found"
3351
3351
  {
3352
3352
  title: "Primary",
3353
3353
  framework: "angular",
3354
- code: '<!-- Storybook story: Primary -->\n<button text-button (click)="dialog.open()">Open Dialog</button>\n<dialog uni-dialog #dialog>\n <header uni-dialog-header color="primary">Sample Dialog</header>\n <div center-layout [width]="300" [height]="200">\n <span uni-text>Dialog</span>\n </div>\n <footer dialog-buttons></footer>\n</dialog>\n<!-- args:\n{}\n-->'
3354
+ code: '<!-- Storybook story: Primary -->\n<button text-button (click)="dialog.open()">Open Dialog</button>\n<dialog uni-dialog #dialog>\n <header dialog-header color="primary">Sample Dialog</header>\n <div center-layout [width]="300" [height]="200">\n <span uni-text>Dialog</span>\n </div>\n <footer dialog-buttons></footer>\n</dialog>\n<!-- args:\n{}\n-->'
3355
+ },
3356
+ {
3357
+ title: "Long Content",
3358
+ framework: "angular",
3359
+ code: `<!-- Storybook story: Long Content -->
3360
+ <div box-layout padding="md">
3361
+ <span uni-text="body-1-long" display="block">
3362
+ The dialog opens over this. Close it and reopen from the button.
3363
+ </span>
3364
+ <button text-button variant="primary" size="md" (click)="show = true">Open dialog</button>
3365
+ </div>
3366
+ <dialog uni-dialog [(show)]="show">
3367
+ <header dialog-header>Edit line item</header>
3368
+ <div stack-layout gap="md" padding="md">
3369
+ <uni-input label="SKU" placeholder="WS-00000" />
3370
+ <!-- Long enough to overflow at any plausible viewport: the point of
3371
+ the story is that this scrolls while the rows above and below it
3372
+ do not. -->
3373
+ @for (n of attributes; track n) {
3374
+ <uni-input [label]="'Attribute ' + n" placeholder="Value" />
3375
+ }
3376
+ </div>
3377
+ <footer dialog-buttons confirmButtonText="Save" cancelButtonText="Cancel"></footer>
3378
+ </dialog>`
3379
+ },
3380
+ {
3381
+ title: "Shrink To Content",
3382
+ framework: "angular",
3383
+ code: '<!-- Storybook story: Shrink To Content -->\n<div box-layout padding="md">\n<button text-button variant="primary" size="md" (click)="show = true">Open dialog</button>\n</div>\n<dialog uni-dialog [(show)]="show">\n<header dialog-header>Discard changes?</header>\n<div box-layout padding="md">\n <span uni-text="body-1-long">Your edits to this line item will be lost.</span>\n</div>\n<footer dialog-buttons confirmButtonText="Discard" cancelButtonText="Keep editing"></footer>\n</dialog>'
3384
+ },
3385
+ {
3386
+ title: "Without Header",
3387
+ framework: "angular",
3388
+ code: '<!-- Storybook story: Without Header -->\n<button text-button variant="primary" (click)="show = true">Open dialog</button>\n<dialog uni-dialog [(show)]="show" ariaLabel="Keyboard shortcuts" [defaultCloseButton]="true">\n<div box-layout padding="lg" [width]="320">\n <span uni-text="body-1-long" display="block">\n Press <strong>Escape</strong> to close, or use the button in the corner.\n With no header to be labelled by, the dialog announces its\n <code>ariaLabel</code> instead.\n </span>\n</div>\n</dialog>'
3389
+ },
3390
+ {
3391
+ title: "Controlled",
3392
+ framework: "angular",
3393
+ code: `<!-- Storybook story: Controlled -->
3394
+ <div stack-layout gap="md" padding="md" alignItems="flex-start">
3395
+ <button text-button variant="primary" (click)="show = true">Open dialog</button>
3396
+ <span uni-text="body-2">Dialog reports: {{ lastEvent }}</span>
3397
+ </div>
3398
+ <dialog
3399
+ uni-dialog
3400
+ [(show)]="show"
3401
+ (showing)="lastEvent = $event ? 'open' : 'closed'"
3402
+ >
3403
+ <header dialog-header>Controlled dialog</header>
3404
+ <div box-layout padding="md" [width]="320">
3405
+ <span uni-text="body-1-long" display="block">
3406
+ Confirm and Cancel both close it, and so do Escape and a backdrop
3407
+ click \u2014 every route keeps <code>show</code> in sync.
3408
+ </span>
3409
+ </div>
3410
+ <footer dialog-buttons confirmButtonText="Save" cancelButtonText="Cancel"></footer>
3411
+ </dialog>`
3355
3412
  }
3356
3413
  ],
3357
3414
  guidelines: {
3358
- whenToUse: "Enhanced modal dialog that extends the native HTML `<dialog>` element with built-in animations, composition components, and accessibility features.\n### Features\n- **Native HTML Dialog**: Built on the standard dialog element with full semantic support\n- **Smooth Animations**: Automatic fade transitions for open/close states\n- **Composition Components**: Optional `DialogHeader` and `DialogButtons` for consistent layouts\n- **Programmatic Control**: Open/close methods plus show property binding\n- **Backdrop Handling**: Click-outside-to-close with customizable behavior\n- **Accessibility**: Full keyboard navigation, focus trapping, and screen reader support",
3415
+ whenToUse: "Enhanced modal dialog that extends the native HTML `<dialog>` element with built-in animations, composition components, and accessibility features.\n### Features\n- **Native HTML Dialog**: Built on the standard dialog element with full semantic support\n- **Three-row layout**: Pinned header and action row with a scrolling body, on a surface that stays content-sized\n- **Smooth Animations**: Automatic fade transitions for open/close states\n- **Composition Components**: Optional `DialogHeader` and `DialogButtons` for consistent layouts\n- **Programmatic Control**: Open/close methods plus show property binding\n- **Backdrop Handling**: Click-outside-to-close with customizable behavior\n- **Accessibility**: Full keyboard navigation, focus trapping, and screen reader support",
3359
3416
  dos: [],
3360
3417
  donts: [],
3361
3418
  accessibility: [
@@ -3369,8 +3426,10 @@ emptyText="No countries found"
3369
3426
  "dialog.behavior.color",
3370
3427
  "dialog.behavior.border",
3371
3428
  "dialog.behavior.padding",
3429
+ "dialog.behavior.inset",
3372
3430
  "dialog.behavior.elevation",
3373
- "dialog.behavior.backdrop"
3431
+ "dialog.behavior.backdrop",
3432
+ "dialog.behavior.motion"
3374
3433
  ]
3375
3434
  },
3376
3435
  {
@@ -3380,7 +3439,7 @@ emptyText="No countries found"
3380
3439
  summary: "",
3381
3440
  description: "",
3382
3441
  category: "feedback",
3383
- version: "10.2.1",
3442
+ version: "10.4.0",
3384
3443
  bindings: {
3385
3444
  angular: {
3386
3445
  importPath: "@uni-design-system/uni-angular",
@@ -3484,11 +3543,11 @@ emptyText="No countries found"
3484
3543
  summary: "",
3485
3544
  description: "",
3486
3545
  category: "feedback",
3487
- version: "10.2.1",
3546
+ version: "10.4.0",
3488
3547
  bindings: {
3489
3548
  angular: {
3490
3549
  importPath: "@uni-design-system/uni-angular",
3491
- selectorOrTag: "[uni-dialog-header]",
3550
+ selectorOrTag: "[uni-dialog-header], [dialog-header]",
3492
3551
  api: [
3493
3552
  {
3494
3553
  name: "variant",
@@ -3525,7 +3584,7 @@ emptyText="No countries found"
3525
3584
  summary: "",
3526
3585
  description: "",
3527
3586
  category: "layout",
3528
- version: "10.2.1",
3587
+ version: "10.4.0",
3529
3588
  bindings: {
3530
3589
  angular: {
3531
3590
  importPath: "@uni-design-system/uni-angular",
@@ -3581,7 +3640,7 @@ emptyText="No countries found"
3581
3640
  summary: "",
3582
3641
  description: "",
3583
3642
  category: "directives",
3584
- version: "10.2.1",
3643
+ version: "10.4.0",
3585
3644
  bindings: {
3586
3645
  angular: {
3587
3646
  importPath: "@uni-design-system/uni-angular",
@@ -3613,7 +3672,7 @@ emptyText="No countries found"
3613
3672
  summary: "Drawer with two modes sharing one three-row layout: - `side` \u2014 an in-flow `<aside>` that pushes content (dashboard sidenav); opening/closing animates its width, and the divider border primitive separates it from the page.",
3614
3673
  description: "Drawer with two modes sharing one three-row layout: - `side` \u2014 an in-flow `<aside>` that pushes content (dashboard sidenav); opening/closing animates its width, and the divider border primitive separates it from the page. - `over` \u2014 a native `<dialog>` in the top layer: focus trap, Escape and scrim backdrop come from the platform (same machinery as `uni-dialog`), sliding in from its edge. **The panel is never the scroll container.** It is a flex column of three rows \u2014 an optional `[uni-drawer-header]`, the projected body, an optional `[uni-drawer-buttons]` \u2014 and only the body scrolls. The panel itself is `overflow: clip` on both axes. That is what lets a header and a save bar pin while a long form scrolls between them, and it is why the theme's `padding` option lands on the body row rather than the panel: padding on a scrolling box scrolls away with its content. Surface, width, divider, elevation, padding, backdrop, scrim and background all resolve from `drawer` theme tokens.",
3615
3674
  category: "components",
3616
- version: "10.2.1",
3675
+ version: "10.4.0",
3617
3676
  bindings: {
3618
3677
  angular: {
3619
3678
  importPath: "@uni-design-system/uni-angular",
@@ -3793,7 +3852,8 @@ initialFocus="input"
3793
3852
  "drawer.behavior.padding",
3794
3853
  "drawer.behavior.backdrop",
3795
3854
  "drawer.behavior.scrim",
3796
- "drawer.behavior.background"
3855
+ "drawer.behavior.background",
3856
+ "drawer.behavior.motion"
3797
3857
  ]
3798
3858
  },
3799
3859
  {
@@ -3803,7 +3863,7 @@ initialFocus="input"
3803
3863
  summary: "The drawer's pinned footer action row \u2014 the save bar of an editor panel.",
3804
3864
  description: "The drawer's pinned footer action row \u2014 the save bar of an editor panel. Sits outside the scrolling body, so the actions stay reachable however long the form is. Mirrors `[dialog-buttons]`; the difference is posture, which lives in the `drawerButtons` theme options rather than here.",
3805
3865
  category: "primitives",
3806
- version: "10.2.1",
3866
+ version: "10.4.0",
3807
3867
  bindings: {
3808
3868
  angular: {
3809
3869
  importPath: "@uni-design-system/uni-angular",
@@ -3900,7 +3960,7 @@ initialFocus="input"
3900
3960
  summary: "The drawer's pinned header row: a title, and optionally a close button.",
3901
3961
  description: "The drawer's pinned header row: a title, and optionally a close button. Sits outside the scrolling body, so it stays put while the form beneath it moves. Reached either by projecting it \u2014 `<div uni-drawer-header>` \u2014 or implicitly, by giving `uni-drawer` a `headline`, in which case the drawer renders one of these itself.",
3902
3962
  category: "components",
3903
- version: "10.2.1",
3963
+ version: "10.4.0",
3904
3964
  bindings: {
3905
3965
  angular: {
3906
3966
  importPath: "@uni-design-system/uni-angular",
@@ -3948,7 +4008,7 @@ initialFocus="input"
3948
4008
  summary: "",
3949
4009
  description: "",
3950
4010
  category: "components",
3951
- version: "10.2.1",
4011
+ version: "10.4.0",
3952
4012
  bindings: {
3953
4013
  angular: {
3954
4014
  importPath: "@uni-design-system/uni-angular",
@@ -4082,7 +4142,7 @@ initialFocus="input"
4082
4142
  summary: "",
4083
4143
  description: "",
4084
4144
  category: "layout",
4085
- version: "10.2.1",
4145
+ version: "10.4.0",
4086
4146
  bindings: {
4087
4147
  angular: {
4088
4148
  importPath: "@uni-design-system/uni-angular",
@@ -4186,7 +4246,7 @@ initialFocus="input"
4186
4246
  summary: "",
4187
4247
  description: "",
4188
4248
  category: "layout",
4189
- version: "10.2.1",
4249
+ version: "10.4.0",
4190
4250
  bindings: {
4191
4251
  angular: {
4192
4252
  importPath: "@uni-design-system/uni-angular",
@@ -4257,7 +4317,7 @@ initialFocus="input"
4257
4317
  summary: "Trigger for a {@link UniExpandComponent} region.",
4258
4318
  description: "Trigger for a {@link UniExpandComponent} region. Two shapes, chosen by whether `label` is set: - **Icon only** (default) \u2014 the bare chevron, sized for a Card Header. - **Labelled** \u2014 chevron plus a label and optional muted sublabel, as a single full-width button. Most real disclosures need a name for the section, and building that row by hand is the thing this saves; it also makes the label the button's accessible name rather than adjacent text.",
4259
4319
  category: "layout",
4260
- version: "10.2.1",
4320
+ version: "10.4.0",
4261
4321
  bindings: {
4262
4322
  angular: {
4263
4323
  importPath: "@uni-design-system/uni-angular",
@@ -4342,7 +4402,7 @@ initialFocus="input"
4342
4402
  summary: "",
4343
4403
  description: "",
4344
4404
  category: "forms",
4345
- version: "10.2.1",
4405
+ version: "10.4.0",
4346
4406
  bindings: {
4347
4407
  angular: {
4348
4408
  importPath: "@uni-design-system/uni-angular",
@@ -4500,7 +4560,7 @@ initialFocus="input"
4500
4560
  summary: "",
4501
4561
  description: "",
4502
4562
  category: "layout",
4503
- version: "10.2.1",
4563
+ version: "10.4.0",
4504
4564
  bindings: {
4505
4565
  angular: {
4506
4566
  importPath: "@uni-design-system/uni-angular",
@@ -4597,7 +4657,7 @@ initialFocus="input"
4597
4657
  summary: "",
4598
4658
  description: "",
4599
4659
  category: "layout",
4600
- version: "10.2.1",
4660
+ version: "10.4.0",
4601
4661
  bindings: {
4602
4662
  angular: {
4603
4663
  importPath: "@uni-design-system/uni-angular",
@@ -4629,7 +4689,7 @@ initialFocus="input"
4629
4689
  summary: "",
4630
4690
  description: "",
4631
4691
  category: "primitives",
4632
- version: "10.2.1",
4692
+ version: "10.4.0",
4633
4693
  bindings: {
4634
4694
  angular: {
4635
4695
  importPath: "@uni-design-system/uni-angular",
@@ -4689,7 +4749,7 @@ initialFocus="input"
4689
4749
  summary: "",
4690
4750
  description: "",
4691
4751
  category: "primitives",
4692
- version: "10.2.1",
4752
+ version: "10.4.0",
4693
4753
  bindings: {
4694
4754
  angular: {
4695
4755
  importPath: "@uni-design-system/uni-angular",
@@ -4792,7 +4852,7 @@ initialFocus="input"
4792
4852
  summary: "",
4793
4853
  description: "",
4794
4854
  category: "forms",
4795
- version: "10.2.1",
4855
+ version: "10.4.0",
4796
4856
  bindings: {
4797
4857
  angular: {
4798
4858
  importPath: "@uni-design-system/uni-angular",
@@ -5070,7 +5130,7 @@ initialFocus="input"
5070
5130
  summary: "",
5071
5131
  description: "",
5072
5132
  category: "forms",
5073
- version: "10.2.1",
5133
+ version: "10.4.0",
5074
5134
  bindings: {
5075
5135
  angular: {
5076
5136
  importPath: "@uni-design-system/uni-angular",
@@ -5191,7 +5251,7 @@ initialFocus="input"
5191
5251
  summary: "",
5192
5252
  description: "",
5193
5253
  category: "components",
5194
- version: "10.2.1",
5254
+ version: "10.4.0",
5195
5255
  bindings: {
5196
5256
  angular: {
5197
5257
  importPath: "@uni-design-system/uni-angular",
@@ -5261,7 +5321,7 @@ initialFocus="input"
5261
5321
  summary: "",
5262
5322
  description: "",
5263
5323
  category: "layout",
5264
- version: "10.2.1",
5324
+ version: "10.4.0",
5265
5325
  bindings: {
5266
5326
  angular: {
5267
5327
  importPath: "@uni-design-system/uni-angular",
@@ -5365,7 +5425,7 @@ initialFocus="input"
5365
5425
  summary: "",
5366
5426
  description: "",
5367
5427
  category: "layout",
5368
- version: "10.2.1",
5428
+ version: "10.4.0",
5369
5429
  bindings: {
5370
5430
  angular: {
5371
5431
  importPath: "@uni-design-system/uni-angular",
@@ -5447,7 +5507,7 @@ initialFocus="input"
5447
5507
  summary: "",
5448
5508
  description: "",
5449
5509
  category: "forms",
5450
- version: "10.2.1",
5510
+ version: "10.4.0",
5451
5511
  bindings: {
5452
5512
  angular: {
5453
5513
  importPath: "@uni-design-system/uni-angular",
@@ -5541,7 +5601,7 @@ initialFocus="input"
5541
5601
  summary: "",
5542
5602
  description: "",
5543
5603
  category: "forms",
5544
- version: "10.2.1",
5604
+ version: "10.4.0",
5545
5605
  bindings: {
5546
5606
  angular: {
5547
5607
  importPath: "@uni-design-system/uni-angular",
@@ -5713,7 +5773,7 @@ initialFocus="input"
5713
5773
  summary: "",
5714
5774
  description: "",
5715
5775
  category: "feedback",
5716
- version: "10.2.1",
5776
+ version: "10.4.0",
5717
5777
  bindings: {
5718
5778
  angular: {
5719
5779
  importPath: "@uni-design-system/uni-angular",
@@ -5973,7 +6033,7 @@ initialFocus="input"
5973
6033
  summary: "",
5974
6034
  description: "",
5975
6035
  category: "feedback",
5976
- version: "10.2.1",
6036
+ version: "10.4.0",
5977
6037
  bindings: {
5978
6038
  angular: {
5979
6039
  importPath: "@uni-design-system/uni-angular",
@@ -5997,7 +6057,7 @@ initialFocus="input"
5997
6057
  summary: "Numeric field with locale-aware parsing, `Intl` formatting on commit, prefix/suffix adornments and steppers that hold to repeat.",
5998
6058
  description: 'Numeric field with locale-aware parsing, `Intl` formatting on commit, prefix/suffix adornments and steppers that hold to repeat. Not `<input type="number">`, and the first reason is a data-loss bug: per the HTML value sanitization algorithm, a number input whose text is not a valid floating-point number reports `value === \'\'`. Type `12,50` as most of Europe does, or paste `1,234.56` from a spreadsheet, and the app reads an empty field. This is `type="text"` with `role="spinbutton"`, which is the only way to keep the user\'s malformed text on screen and tell them about it. Chrome comes from `uni-input-box`, so error, disabled and focus states match every other field. All arithmetic runs on the cdk\'s exact decimal helpers.',
5999
6059
  category: "forms",
6000
- version: "10.2.1",
6060
+ version: "10.4.0",
6001
6061
  bindings: {
6002
6062
  angular: {
6003
6063
  importPath: "@uni-design-system/uni-angular",
@@ -6416,7 +6476,7 @@ initialFocus="input"
6416
6476
  summary: "Two linked numeric fields in one chrome, with one `{ start, end }` value \u2014 price filters, thresholds, tolerances.",
6417
6477
  description: "Two linked numeric fields in one chrome, with one `{ start, end }` value \u2014 price filters, thresholds, tolerances. `start`/`end` deliberately match `UniDateRange`, so the library has one range vocabulary, and they avoid colliding with the `min`/`max` **inputs**, which mean the fence rather than the value. It owns its commit path rather than nesting two `uni-number-input`s, because the two behaviours the spec asks for need *different* bounds: a stepper must be fenced at the other end, while a typed commit must reach the parent un-clamped so a backwards range can be swapped instead of destroyed. A child field applies one bound pair to both. The arithmetic, parsing and formatting are still the cdk's, shared with every other numeric control.",
6418
6478
  category: "forms",
6419
- version: "10.2.1",
6479
+ version: "10.4.0",
6420
6480
  bindings: {
6421
6481
  angular: {
6422
6482
  importPath: "@uni-design-system/uni-angular",
@@ -6698,7 +6758,7 @@ initialFocus="input"
6698
6758
  summary: "",
6699
6759
  description: "",
6700
6760
  category: "data",
6701
- version: "10.2.1",
6761
+ version: "10.4.0",
6702
6762
  bindings: {
6703
6763
  angular: {
6704
6764
  importPath: "@uni-design-system/uni-angular",
@@ -6799,7 +6859,7 @@ initialFocus="input"
6799
6859
  summary: "Anchored, top-layer panel on the native `popover` element \u2014 the browser owns positioning (CSS anchor positioning), stacking, and, in rich mode, light dismissal.",
6800
6860
  description: 'Anchored, top-layer panel on the native `popover` element \u2014 the browser owns positioning (CSS anchor positioning), stacking, and, in rich mode, light dismissal. Two modes share one implementation: - `rich` (default): a click-toggled disclosure. The projected `[trigger]` carries `aria-expanded`/`aria-controls`; with no trigger content the app drives `open` and no element claims controller ARIA. Focus stays on the trigger (APG disclosure) unless the panel marks an `[autofocus]` field, and returns to the trigger on close. - `tooltip`: hover/focus-triggered, `role="tooltip"` + `aria-describedby`, WCAG 1.4.13 dismissable/hoverable/persistent. Content must not contain focusable elements. Anchoring and control are separate: `anchor` re-anchors the panel to any element (or id) while the trigger keeps the disclosure semantics.',
6801
6861
  category: "layout",
6802
- version: "10.2.1",
6862
+ version: "10.4.0",
6803
6863
  bindings: {
6804
6864
  angular: {
6805
6865
  importPath: "@uni-design-system/uni-angular",
@@ -6991,7 +7051,7 @@ initialFocus="input"
6991
7051
  summary: "",
6992
7052
  description: "",
6993
7053
  category: "feedback",
6994
- version: "10.2.1",
7054
+ version: "10.4.0",
6995
7055
  bindings: {
6996
7056
  angular: {
6997
7057
  importPath: "@uni-design-system/uni-angular",
@@ -7055,7 +7115,7 @@ initialFocus="input"
7055
7115
  summary: "",
7056
7116
  description: "",
7057
7117
  category: "feedback",
7058
- version: "10.2.1",
7118
+ version: "10.4.0",
7059
7119
  bindings: {
7060
7120
  angular: {
7061
7121
  importPath: "@uni-design-system/uni-angular",
@@ -7127,7 +7187,7 @@ initialFocus="input"
7127
7187
  summary: "`\u2212 3 +` for cart lines, table cells and seat counts: the numeric core with no field chrome, no label and no room for either.",
7128
7188
  description: '`\u2212 3 +` for cart lines, table cells and seat counts: the numeric core with no field chrome, no label and no room for either. A separate component rather than a `chrome="bare"` flag on `uni-number-input`, because this control is defined by what it does *not* have \u2014 presets, affixes, expressions, four stepper layouts \u2014 and eight inputs are easier to write correctly than forty with a list of which ones to leave alone. The arithmetic, parsing and hold-to-repeat are the cdk\'s, shared with the field, so `1,200` and the keyboard map behave identically in both. The middle stays a real input by default: typing `12` beats tapping `+` eleven times. `editable=false` is for read-mostly tables.',
7129
7189
  category: "forms",
7130
- version: "10.2.1",
7190
+ version: "10.4.0",
7131
7191
  bindings: {
7132
7192
  angular: {
7133
7193
  importPath: "@uni-design-system/uni-angular",
@@ -7323,7 +7383,7 @@ initialFocus="input"
7323
7383
  summary: "",
7324
7384
  description: "",
7325
7385
  category: "forms",
7326
- version: "10.2.1",
7386
+ version: "10.4.0",
7327
7387
  bindings: {
7328
7388
  angular: {
7329
7389
  importPath: "@uni-design-system/uni-angular",
@@ -7514,7 +7574,7 @@ initialFocus="input"
7514
7574
  summary: "",
7515
7575
  description: "",
7516
7576
  category: "directives",
7517
- version: "10.2.1",
7577
+ version: "10.4.0",
7518
7578
  bindings: {
7519
7579
  angular: {
7520
7580
  importPath: "@uni-design-system/uni-angular",
@@ -7538,7 +7598,7 @@ initialFocus="input"
7538
7598
  summary: "",
7539
7599
  description: "",
7540
7600
  category: "layout",
7541
- version: "10.2.1",
7601
+ version: "10.4.0",
7542
7602
  bindings: {
7543
7603
  angular: {
7544
7604
  importPath: "@uni-design-system/uni-angular",
@@ -7593,7 +7653,7 @@ initialFocus="input"
7593
7653
  summary: "Native scroll area with theme-driven scrollbar styling.",
7594
7654
  description: "Native scroll area with theme-driven scrollbar styling. Scrollbars are styled entirely through Emotion-generated CSS: `::-webkit-scrollbar` rules cover Chromium/Safari, with a `scrollbar-width`/`scrollbar-color` fallback for Firefox.",
7595
7655
  category: "layout",
7596
- version: "10.2.1",
7656
+ version: "10.4.0",
7597
7657
  bindings: {
7598
7658
  angular: {
7599
7659
  importPath: "@uni-design-system/uni-angular",
@@ -7740,7 +7800,7 @@ initialFocus="input"
7740
7800
  summary: "Generic search field: shared input chrome with a leading magnifier, a clear button while there's a query, Enter to submit, and optional type-ahead \u2014 pass `suggestions` (refresh them from `change`) and the field becomes an ARIA combobox with a keyboard-navigable listbox.",
7741
7801
  description: "Generic search field: shared input chrome with a leading magnifier, a clear button while there's a query, Enter to submit, and optional type-ahead \u2014 pass `suggestions` (refresh them from `change`) and the field becomes an ARIA combobox with a keyboard-navigable listbox. Escape closes the list first, then clears the query.",
7742
7802
  category: "forms",
7743
- version: "10.2.1",
7803
+ version: "10.4.0",
7744
7804
  bindings: {
7745
7805
  angular: {
7746
7806
  importPath: "@uni-design-system/uni-angular",
@@ -7867,7 +7927,7 @@ initialFocus="input"
7867
7927
  summary: "",
7868
7928
  description: "",
7869
7929
  category: "forms",
7870
- version: "10.2.1",
7930
+ version: "10.4.0",
7871
7931
  bindings: {
7872
7932
  angular: {
7873
7933
  importPath: "@uni-design-system/uni-angular",
@@ -8033,7 +8093,7 @@ initialFocus="input"
8033
8093
  summary: "Loading placeholder painted with surface tokens.",
8034
8094
  description: "Loading placeholder painted with surface tokens. `text` renders one or more lines (the last line shortened, as real text would be), `rect` and `circle` render fixed shapes. The shimmer only animates when the user allows motion; it degrades to static blocks under `prefers-reduced-motion`. Color and radius are theme options with per-instance overrides, because one app routinely needs several: skeletons on a card and on the page background want different tints, and a pill placeholder wants a different corner than the text bars beside it.",
8035
8095
  category: "components",
8036
- version: "10.2.1",
8096
+ version: "10.4.0",
8037
8097
  bindings: {
8038
8098
  angular: {
8039
8099
  importPath: "@uni-design-system/uni-angular",
@@ -8184,7 +8244,7 @@ initialFocus="input"
8184
8244
  summary: "Bounded numeric input by pointer, for values where the *position* is the information: volume, opacity, weightings, price filters.",
8185
8245
  description: "Bounded numeric input by pointer, for values where the *position* is the information: volume, opacity, weightings, price filters. Custom thumbs rather than `<input type=\"range\">`, which the previous version used: one native range input cannot carry two thumbs, marks or a tooltip, and a second component for the range case would mean two keyboard maps to keep in step. The step model and the keyboard map are the cdk's, shared with the numeric fields, so nothing new is learned moving between them. All arithmetic on values runs through the cdk's exact decimal helpers \u2014 stepping `0.1` never yields `0.30000000000000004`. Only pointer *positions* use floats, and they are snapped to the grid before becoming a value.",
8186
8246
  category: "forms",
8187
- version: "10.2.1",
8247
+ version: "10.4.0",
8188
8248
  bindings: {
8189
8249
  angular: {
8190
8250
  importPath: "@uni-design-system/uni-angular",
@@ -8451,7 +8511,7 @@ initialFocus="input"
8451
8511
  summary: "",
8452
8512
  description: "",
8453
8513
  category: "feedback",
8454
- version: "10.2.1",
8514
+ version: "10.4.0",
8455
8515
  bindings: {
8456
8516
  angular: {
8457
8517
  importPath: "@uni-design-system/uni-angular",
@@ -8563,7 +8623,7 @@ initialFocus="input"
8563
8623
  summary: "",
8564
8624
  description: "",
8565
8625
  category: "data",
8566
- version: "10.2.1",
8626
+ version: "10.4.0",
8567
8627
  bindings: {
8568
8628
  angular: {
8569
8629
  importPath: "@uni-design-system/uni-angular",
@@ -8622,7 +8682,7 @@ initialFocus="input"
8622
8682
  summary: "",
8623
8683
  description: "",
8624
8684
  category: "layout",
8625
- version: "10.2.1",
8685
+ version: "10.4.0",
8626
8686
  bindings: {
8627
8687
  angular: {
8628
8688
  importPath: "@uni-design-system/uni-angular",
@@ -8677,7 +8737,7 @@ initialFocus="input"
8677
8737
  summary: 'KPI stat tile: muted label, large value (numbers auto-compact: 48234 \u2192 "48.2K"), an optional delta whose ink is decided by *direction \xD7 whether up is good* (never direction alone \u2014 churn going down is good news), and an optional decorative sparkline.',
8678
8738
  description: 'KPI stat tile: muted label, large value (numbers auto-compact: 48234 \u2192 "48.2K"), an optional delta whose ink is decided by *direction \xD7 whether up is good* (never direction alone \u2014 churn going down is good news), and an optional decorative sparkline. Frame, typography and inks are all `stat` theme tokens.',
8679
8739
  category: "components",
8680
- version: "10.2.1",
8740
+ version: "10.4.0",
8681
8741
  bindings: {
8682
8742
  angular: {
8683
8743
  importPath: "@uni-design-system/uni-angular",
@@ -8795,7 +8855,7 @@ initialFocus="input"
8795
8855
  summary: "",
8796
8856
  description: "",
8797
8857
  category: "primitives",
8798
- version: "10.2.1",
8858
+ version: "10.4.0",
8799
8859
  bindings: {
8800
8860
  angular: {
8801
8861
  importPath: "@uni-design-system/uni-angular",
@@ -8884,7 +8944,7 @@ initialFocus="input"
8884
8944
  summary: "One tab inside `uni-tabs`: a label for the tablist plus projected panel content.",
8885
8945
  description: "One tab inside `uni-tabs`: a label for the tablist plus projected panel content. Content is captured in a template and only instantiated while the tab is selected, so inactive panels cost nothing.",
8886
8946
  category: "components",
8887
- version: "10.2.1",
8947
+ version: "10.4.0",
8888
8948
  bindings: {
8889
8949
  angular: {
8890
8950
  importPath: "@uni-design-system/uni-angular",
@@ -8924,7 +8984,7 @@ initialFocus="input"
8924
8984
  summary: "WAI-ARIA tabs: roving tabindex, automatic activation (arrow keys move focus and select), Home/End, disabled tabs skipped.",
8925
8985
  description: "WAI-ARIA tabs: roving tabindex, automatic activation (arrow keys move focus and select), Home/End, disabled tabs skipped. Only the selected panel is instantiated. All styling resolves from `tabs` theme option tokens.",
8926
8986
  category: "components",
8927
- version: "10.2.1",
8987
+ version: "10.4.0",
8928
8988
  bindings: {
8929
8989
  angular: {
8930
8990
  importPath: "@uni-design-system/uni-angular",
@@ -9004,7 +9064,7 @@ initialFocus="input"
9004
9064
  summary: "Compact chip for categories, states, filters and tokens.",
9005
9065
  description: "Compact chip for categories, states, filters and tokens. Two orthogonal style axes: `variant` picks the colour role and `tone` picks the archetype (soft / solid / outline). Both live in the theme's `tag` entry, so a theme restyles every chip in the app without touching markup. Structurally a chip is **body + trailing action as siblings**, never nested buttons: an interactive chip whose body is a `<button>` cannot contain the remove `<button>` (invalid HTML, and the inner control becomes unreachable for keyboard users). Both stay independently operable.",
9006
9066
  category: "data",
9007
- version: "10.2.1",
9067
+ version: "10.4.0",
9008
9068
  bindings: {
9009
9069
  angular: {
9010
9070
  importPath: "@uni-design-system/uni-angular",
@@ -9361,7 +9421,7 @@ initialFocus="input"
9361
9421
  summary: "",
9362
9422
  description: "",
9363
9423
  category: "forms",
9364
- version: "10.2.1",
9424
+ version: "10.4.0",
9365
9425
  bindings: {
9366
9426
  angular: {
9367
9427
  importPath: "@uni-design-system/uni-angular",
@@ -9694,7 +9754,7 @@ placeholder="Name or address\u2026"
9694
9754
  summary: "The typography primitive, applied as an attribute to any element so semantics stay yours.",
9695
9755
  description: 'The typography primitive, applied as an attribute to any element so semantics stay yours. The attribute value is the typeface: `<h1 uni-text="display-small">`, `<span uni-text="caption">`, dynamic via `[uni-text]="role()"`. With no value, the typeface is inferred from the host element (h1 \u2192 headline-large, p \u2192 body-1-long, \u2026), falling back to `title-small`; the `typeface` input remains as an explicit override. It is a directive, so it stacks with anything else on the element \u2014 a layout attribute (`<div stack-layout uni-text="title-small">`) or a component\'s own host \u2014 rather than colliding with it.',
9696
9756
  category: "primitives",
9697
- version: "10.2.1",
9757
+ version: "10.4.0",
9698
9758
  bindings: {
9699
9759
  angular: {
9700
9760
  importPath: "@uni-design-system/uni-angular",
@@ -9796,7 +9856,7 @@ placeholder="Name or address\u2026"
9796
9856
  summary: "",
9797
9857
  description: "",
9798
9858
  category: "forms",
9799
- version: "10.2.1",
9859
+ version: "10.4.0",
9800
9860
  bindings: {
9801
9861
  angular: {
9802
9862
  importPath: "@uni-design-system/uni-angular",
@@ -9996,7 +10056,7 @@ placeholder="Name or address\u2026"
9996
10056
  summary: "",
9997
10057
  description: "",
9998
10058
  category: "primitives",
9999
- version: "10.2.1",
10059
+ version: "10.4.0",
10000
10060
  bindings: {
10001
10061
  angular: {
10002
10062
  importPath: "@uni-design-system/uni-angular",
@@ -10026,7 +10086,7 @@ placeholder="Name or address\u2026"
10026
10086
  summary: "Drop-in switcher for the themes registered via `UNI_THEMES`: a select over `ThemeService.themeOptions` that applies the choice through `selectTheme` (so it persists across reloads like any other theme selection).",
10027
10087
  description: "Drop-in switcher for the themes registered via `UNI_THEMES`: a select over `ThemeService.themeOptions` that applies the choice through `selectTheme` (so it persists across reloads like any other theme selection).",
10028
10088
  category: "components",
10029
- version: "10.2.1",
10089
+ version: "10.4.0",
10030
10090
  bindings: {
10031
10091
  angular: {
10032
10092
  importPath: "@uni-design-system/uni-angular",
@@ -10084,7 +10144,7 @@ placeholder="Name or address\u2026"
10084
10144
  summary: "Time field: a combobox over time options \u2014 the same listbox contract as uni-search-input and uni-tag-input.",
10085
10145
  description: "Time field: a combobox over time options \u2014 the same listbox contract as uni-search-input and uni-tag-input. Type `3p`, `930` or `15:00`, or pick `3:00 PM` from the list; the form always gets 24-hour `'HH:mm'` (`hour12` affects display only). The list is assistive, not exhaustive: any parseable time commits, unless `slots` pins the choices (a slot picker) \u2014 then a typed time must match one. Unreadable or unavailable text stays in the field, flagged, with a `rejected` event.",
10086
10146
  category: "forms",
10087
- version: "10.2.1",
10147
+ version: "10.4.0",
10088
10148
  bindings: {
10089
10149
  angular: {
10090
10150
  importPath: "@uni-design-system/uni-angular",
@@ -10292,7 +10352,7 @@ placeholder="Name or address\u2026"
10292
10352
  summary: "",
10293
10353
  description: "",
10294
10354
  category: "forms",
10295
- version: "10.2.1",
10355
+ version: "10.4.0",
10296
10356
  bindings: {
10297
10357
  angular: {
10298
10358
  importPath: "@uni-design-system/uni-angular",
@@ -10515,7 +10575,7 @@ placeholder="Name or address\u2026"
10515
10575
  summary: "",
10516
10576
  description: "",
10517
10577
  category: "feedback",
10518
- version: "10.2.1",
10578
+ version: "10.4.0",
10519
10579
  bindings: {
10520
10580
  angular: {
10521
10581
  importPath: "@uni-design-system/uni-angular",
@@ -10602,7 +10662,7 @@ placeholder="Name or address\u2026"
10602
10662
  summary: 'A thin sequencer over one `uni-callout`: steps spotlight their targets, a footer walks Next/Back with dots-or-fraction progress, and `advanceOn` gates a step behind an interaction with its target (auto-advancing for clicks, unlocking Next otherwise \u2014 announced through one `role="status"` region).',
10603
10663
  description: 'A thin sequencer over one `uni-callout`: steps spotlight their targets, a footer walks Next/Back with dots-or-fraction progress, and `advanceOn` gates a step behind an interaction with its target (auto-advancing for clicks, unlocking Next otherwise \u2014 announced through one `role="status"` region). Escape or the close button skips the tour and reports the step. `active` is a two-way model, so a tour is deep-linkable and inspectable; steps whose declared target cannot be resolved are skipped (with a dev warning) in the direction of travel rather than erroring.',
10604
10664
  category: "components",
10605
- version: "10.2.1",
10665
+ version: "10.4.0",
10606
10666
  bindings: {
10607
10667
  angular: {
10608
10668
  importPath: "@uni-design-system/uni-angular",
@@ -10729,7 +10789,7 @@ placeholder="Name or address\u2026"
10729
10789
  summary: "",
10730
10790
  description: "",
10731
10791
  category: "layout",
10732
- version: "10.2.1",
10792
+ version: "10.4.0",
10733
10793
  bindings: {
10734
10794
  angular: {
10735
10795
  importPath: "@uni-design-system/uni-angular",
@@ -11915,6 +11975,17 @@ placeholder="Name or address\u2026"
11915
11975
  DarkTheme: "0 0 5px rgba(255, 150, 138, 0.55), inset 0 0 5px rgba(255, 150, 138, 0.35)"
11916
11976
  }
11917
11977
  },
11978
+ {
11979
+ id: "backdrop.scrim",
11980
+ value: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
11981
+ type: "backdrop",
11982
+ kind: "style",
11983
+ target: "emotion-css",
11984
+ themeValues: {
11985
+ LightTheme: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
11986
+ DarkTheme: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}'
11987
+ }
11988
+ },
11918
11989
  {
11919
11990
  id: "thickness.thin",
11920
11991
  value: 1,
@@ -12476,14 +12547,14 @@ placeholder="Name or address\u2026"
12476
12547
  },
12477
12548
  {
12478
12549
  id: "drawer.behavior.backdrop",
12479
- value: '{"background":"rgba(0, 0, 0, 0.4)"}',
12480
- type: "object",
12550
+ value: "scrim",
12551
+ type: "string",
12481
12552
  kind: "behavioral",
12482
12553
  target: "component-prop",
12483
12554
  appliesTo: "drawer",
12484
12555
  themeValues: {
12485
- LightTheme: '{"background":"rgba(0, 0, 0, 0.4)"}',
12486
- DarkTheme: '{"background":"rgba(0, 0, 0, 0.4)"}'
12556
+ LightTheme: "scrim",
12557
+ DarkTheme: "scrim"
12487
12558
  }
12488
12559
  },
12489
12560
  {
@@ -12510,6 +12581,18 @@ placeholder="Name or address\u2026"
12510
12581
  DarkTheme: "solid"
12511
12582
  }
12512
12583
  },
12584
+ {
12585
+ id: "drawer.behavior.motion",
12586
+ value: "panel",
12587
+ type: "string",
12588
+ kind: "behavioral",
12589
+ target: "component-prop",
12590
+ appliesTo: "drawer",
12591
+ themeValues: {
12592
+ LightTheme: "panel",
12593
+ DarkTheme: "panel"
12594
+ }
12595
+ },
12513
12596
  {
12514
12597
  id: "drawerHeader.behavior.height",
12515
12598
  value: 56,
@@ -13002,6 +13085,18 @@ placeholder="Name or address\u2026"
13002
13085
  DarkTheme: "sm"
13003
13086
  }
13004
13087
  },
13088
+ {
13089
+ id: "dialog.behavior.inset",
13090
+ value: "lg",
13091
+ type: "string",
13092
+ kind: "behavioral",
13093
+ target: "component-prop",
13094
+ appliesTo: "dialog",
13095
+ themeValues: {
13096
+ LightTheme: "lg",
13097
+ DarkTheme: "lg"
13098
+ }
13099
+ },
13005
13100
  {
13006
13101
  id: "dialog.behavior.elevation",
13007
13102
  value: "dialog",
@@ -13016,14 +13111,26 @@ placeholder="Name or address\u2026"
13016
13111
  },
13017
13112
  {
13018
13113
  id: "dialog.behavior.backdrop",
13019
- value: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
13020
- type: "object",
13114
+ value: "scrim",
13115
+ type: "string",
13021
13116
  kind: "behavioral",
13022
13117
  target: "component-prop",
13023
13118
  appliesTo: "dialog",
13024
13119
  themeValues: {
13025
- LightTheme: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
13026
- DarkTheme: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}'
13120
+ LightTheme: "scrim",
13121
+ DarkTheme: "scrim"
13122
+ }
13123
+ },
13124
+ {
13125
+ id: "dialog.behavior.motion",
13126
+ value: "panel",
13127
+ type: "string",
13128
+ kind: "behavioral",
13129
+ target: "component-prop",
13130
+ appliesTo: "dialog",
13131
+ themeValues: {
13132
+ LightTheme: "panel",
13133
+ DarkTheme: "panel"
13027
13134
  }
13028
13135
  },
13029
13136
  {
@@ -16197,6 +16304,7 @@ placeholder="Name or address\u2026"
16197
16304
  "shadow.menu": "rgba(23, 25, 43, 0.2) 0px 3px 3px -2px, rgba(23, 25, 43, 0.14) 0px 3px 4px 0px, rgba(23, 25, 43, 0.12) 0px 1px 8px 0px",
16198
16305
  "shadow.dialog": "rgba(23, 25, 43, 0.2) 0px 3px 5px -1px, rgba(23, 25, 43, 0.14) 0px 6px 10px 0px, rgba(23, 25, 43, 0.12) 0px 1px 18px 0px",
16199
16306
  "shadow.warn": "0 0 5px rgba(204, 40, 39, 0.5), inset 0 0 5px rgba(204, 40, 39, 0.3)",
16307
+ "backdrop.scrim": '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
16200
16308
  "thickness.thin": 1,
16201
16309
  "thickness.standard": 2,
16202
16310
  "thickness.thick": 4,
@@ -16255,9 +16363,10 @@ placeholder="Name or address\u2026"
16255
16363
  divider: "light",
16256
16364
  elevation: "menu",
16257
16365
  padding: "md",
16258
- backdrop: '{"background":"rgba(0, 0, 0, 0.4)"}',
16366
+ backdrop: "scrim",
16259
16367
  scrim: true,
16260
- background: "solid"
16368
+ background: "solid",
16369
+ motion: "panel"
16261
16370
  },
16262
16371
  drawerHeader: {
16263
16372
  height: 56,
@@ -16315,8 +16424,10 @@ placeholder="Name or address\u2026"
16315
16424
  color: "primary-surface",
16316
16425
  border: "quaternary",
16317
16426
  padding: "sm",
16427
+ inset: "lg",
16318
16428
  elevation: "dialog",
16319
- backdrop: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}'
16429
+ backdrop: "scrim",
16430
+ motion: "panel"
16320
16431
  },
16321
16432
  dialogButtons: {
16322
16433
  gap: "md",
@@ -16763,6 +16874,7 @@ placeholder="Name or address\u2026"
16763
16874
  "shadow.menu": "0px 4px 12px rgba(0, 0, 0, 0.45)",
16764
16875
  "shadow.dialog": "0px 8px 28px rgba(0, 0, 0, 0.55)",
16765
16876
  "shadow.warn": "0 0 5px rgba(255, 150, 138, 0.55), inset 0 0 5px rgba(255, 150, 138, 0.35)",
16877
+ "backdrop.scrim": '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}',
16766
16878
  "thickness.thin": 1,
16767
16879
  "thickness.standard": 2,
16768
16880
  "thickness.thick": 4,
@@ -16821,9 +16933,10 @@ placeholder="Name or address\u2026"
16821
16933
  divider: "light",
16822
16934
  elevation: "menu",
16823
16935
  padding: "md",
16824
- backdrop: '{"background":"rgba(0, 0, 0, 0.4)"}',
16936
+ backdrop: "scrim",
16825
16937
  scrim: true,
16826
- background: "solid"
16938
+ background: "solid",
16939
+ motion: "panel"
16827
16940
  },
16828
16941
  drawerHeader: {
16829
16942
  height: 56,
@@ -16881,8 +16994,10 @@ placeholder="Name or address\u2026"
16881
16994
  color: "primary-surface",
16882
16995
  border: "quaternary",
16883
16996
  padding: "sm",
16997
+ inset: "lg",
16884
16998
  elevation: "dialog",
16885
- backdrop: '{"background":"rgba(255, 255, 255, 0.6)","backdropFilter":"blur(2px)"}'
16999
+ backdrop: "scrim",
17000
+ motion: "panel"
16886
17001
  },
16887
17002
  dialogButtons: {
16888
17003
  gap: "md",
@@ -17225,6 +17340,30 @@ placeholder="Name or address\u2026"
17225
17340
  {
17226
17341
  package: "@uni-design-system/uni-angular",
17227
17342
  releases: [
17343
+ {
17344
+ version: "10.4.0",
17345
+ entries: [
17346
+ {
17347
+ bump: "minor",
17348
+ title: "Give `uni-dialog` the drawer's three-row layout: a pinned `[uni-dialog-header]`, a scrolling body, and pinned `[uni-dialog-buttons]`.",
17349
+ body: "The surface is now a flex column that is `overflow: clip` on both axes, so it is never the scroll container \u2014 previously a long form scrolled the dialog's own title and action buttons off the screen. Unlike the drawer, the dialog declares no height and stays sized by its content, growing until it reaches `calc(100dvh - 2 \xD7 inset)` and only then scrolling its body.\n\nNew theme options: `dialog.inset` (gap from the viewport edge before the body scrolls, default `lg`), `dialog.bodyPadding` (pads the scrolling row alone; `dialog.padding` still insets all three rows), and `divider` on `dialogHeader` / `dialogButtons` for a border between a pinned row and the body \u2014 all off or unchanged by default, so existing dialogs keep their appearance.\n\n`[uni-dialog-header]` gains the shorter `[dialog-header]` alias, matching `[dialog-buttons]`; the long form keeps working. The `defaultCloseButton` now actually floats in the corner \u2014 its `position: absolute` was being lost to the icon button's own class, which left it inline at the top of the surface.\n\nThe drawer's overlay scrim now fades in and out with the panel instead of snapping. Its `::backdrop` had a background and no animation at all, so the dimming appeared and vanished instantly around a panel that took 250ms to slide. A new `drawer.motion` option (default `panel`) times the slide, the scrim's fade and the side panel's width transition together, replacing the hardcoded 250ms literals. The global reduced-motion rule now also reaches `::backdrop`, so both the drawer's and the dialog's scrim honour the preference (WCAG 2.3.3).\n\nDialog and drawer scrims now come from one token. `UniTheme` gains a `backdrops` scale \u2014 open and named like `shadows` and `motion` \u2014 and both components' `backdrop` option points at a name (`'scrim'`) instead of carrying its own CSS. They had drifted: the dialog washed the page white and blurred it while the drawer dimmed it dark, and a theme that dressed the dialog left the drawer on the library default. A raw style object is still accepted on either option, so a theme that states one keeps working.\n\nThe dialog's fade now reads the theme's `motion` token too (new `dialog.motion` option, default `panel`), replacing a hardcoded `350ms ease-in`. It shared the drawer's scrim but not its timing, so the same surface arrived at two speeds; both are now 250ms and a theme retimes them together.",
17350
+ commit: "cb5f08f"
17351
+ }
17352
+ ],
17353
+ dependencyBumps: []
17354
+ },
17355
+ {
17356
+ version: "10.3.0",
17357
+ entries: [
17358
+ {
17359
+ bump: "minor",
17360
+ title: "`uni-button`: the focus ring is themed, and the theme now outranks the reset.",
17361
+ body: "**Five of the twelve variants had no visible keyboard focus ring.** The ring\nresolved the variant _name_ as a colour token \u2014 the pattern 10.2.0 removed from\ncheckbox, radio and toggle, missed on the one component where it costs an\naccessibility failure rather than a wrong colour:\n\n```ts\noutline: `2px solid ${this.theme.colors()[this.variant()]}`;\n```\n\n`ghost` resolves to `transparent`, so its ring was drawn invisibly.\n`light`, `onLight`, `dark` and `onDark` have no colour token at all, so the\ndeclaration became `2px solid undefined` and the parser dropped it \u2014 as would\nany intent a consumer registers. In every case `outline-offset` survived, so\nthe element still shifted on focus and the missing ring went unnoticed. This\nwas live without the registry involved.\n\nThe colour now comes from the variant's theme entry via `variantOptions`, the\nmechanism the selection controls already use, and falls back to the reserved\n`primary` accent rather than to nothing. Each variant keeps the ring colour it\nhad; `ghost` gains a visible one. The ring also routes through the shared\n`focusRingStyle`, so a theme defining `focusRing` primitives restyles the button\nalongside every other control.\n\n**A theme could not give a button a border.** `border`, `outline`, `overflow`\nand `transition` were applied _after_ the theme's styles, so a variant\ndeclaring a border was silently erased and `!important` was the only way\nthrough \u2014 which then spread to every state adjusting that border, since the\nshorthand outranks the longhand.\n\nThe base theme was caught by its own reset: `secondary` is commented \"Hollow\"\nand declares `1px solid`, and has been rendering borderless. **It now renders\nits border** \u2014 the one visible change here for anyone on the default theme.\n\nThose four properties move ahead of the theme's styles, resolving the\n`TODO: Set priority on theme-defined styles` that sat on this line. Structure\nthe component genuinely owns \u2014 `position` for the ripple, the symbol slots \u2014\nstays after, and the reset still applies to every variant that does not\noverride it.\n\n**`uni-icon-button`'s hover moved to the theme too.** It branched on\n`variant() === 'ghost'` to choose between a raised shadow and a translucent\nwash, after the theme's own styles. Being a binary partition, every intent a\nconsumer registered fell into the not-ghost half and was given a lift whether\nor not it suited \u2014 a recessive intent included \u2014 and no theme could correct it.\nBoth themes in this repo declare a ghost hover and had it silently overridden.\n\nBoth treatments now live in `iconButton.variants` beside the colours they belong\nwith. Rendering is unchanged for the variants the theme styles; a variant it\ndoes not style no longer receives a hover it never asked for, and the `disabled`\nvariant loses one it should never have had, since its block is also spread into\n`&:disabled`.\n\n**`uni-icon-button` had no focus indicator at all.** Its structural block cleared\nthe user-agent outline and put nothing back, in every variant \u2014 so the close\naffordance in every dialog and drawer header was unreachable-looking under\nkeyboard navigation. This was not reported; it was found while verifying the\nbutton fix above.\n\nIt now draws the shared ring, with its colour read from the same\n`variantOptions.focusColor` the button uses. The indicator is applied last on\npurpose: its appearance is the theme's, through `focusColor` and the `focusRing`\nprimitives, but whether one exists is not a style a theme should be able to\nswitch off by accident.",
17362
+ commit: "ab1689a"
17363
+ }
17364
+ ],
17365
+ dependencyBumps: []
17366
+ },
17228
17367
  {
17229
17368
  version: "10.2.1",
17230
17369
  entries: [],
@@ -17989,6 +18128,30 @@ placeholder="Name or address\u2026"
17989
18128
  {
17990
18129
  package: "@uni-design-system/uni-core",
17991
18130
  releases: [
18131
+ {
18132
+ version: "10.4.0",
18133
+ entries: [
18134
+ {
18135
+ bump: "minor",
18136
+ title: "Give `uni-dialog` the drawer's three-row layout: a pinned `[uni-dialog-header]`, a scrolling body, and pinned `[uni-dialog-buttons]`.",
18137
+ body: "The surface is now a flex column that is `overflow: clip` on both axes, so it is never the scroll container \u2014 previously a long form scrolled the dialog's own title and action buttons off the screen. Unlike the drawer, the dialog declares no height and stays sized by its content, growing until it reaches `calc(100dvh - 2 \xD7 inset)` and only then scrolling its body.\n\nNew theme options: `dialog.inset` (gap from the viewport edge before the body scrolls, default `lg`), `dialog.bodyPadding` (pads the scrolling row alone; `dialog.padding` still insets all three rows), and `divider` on `dialogHeader` / `dialogButtons` for a border between a pinned row and the body \u2014 all off or unchanged by default, so existing dialogs keep their appearance.\n\n`[uni-dialog-header]` gains the shorter `[dialog-header]` alias, matching `[dialog-buttons]`; the long form keeps working. The `defaultCloseButton` now actually floats in the corner \u2014 its `position: absolute` was being lost to the icon button's own class, which left it inline at the top of the surface.\n\nThe drawer's overlay scrim now fades in and out with the panel instead of snapping. Its `::backdrop` had a background and no animation at all, so the dimming appeared and vanished instantly around a panel that took 250ms to slide. A new `drawer.motion` option (default `panel`) times the slide, the scrim's fade and the side panel's width transition together, replacing the hardcoded 250ms literals. The global reduced-motion rule now also reaches `::backdrop`, so both the drawer's and the dialog's scrim honour the preference (WCAG 2.3.3).\n\nDialog and drawer scrims now come from one token. `UniTheme` gains a `backdrops` scale \u2014 open and named like `shadows` and `motion` \u2014 and both components' `backdrop` option points at a name (`'scrim'`) instead of carrying its own CSS. They had drifted: the dialog washed the page white and blurred it while the drawer dimmed it dark, and a theme that dressed the dialog left the drawer on the library default. A raw style object is still accepted on either option, so a theme that states one keeps working.\n\nThe dialog's fade now reads the theme's `motion` token too (new `dialog.motion` option, default `panel`), replacing a hardcoded `350ms ease-in`. It shared the drawer's scrim but not its timing, so the same surface arrived at two speeds; both are now 250ms and a theme retimes them together.",
18138
+ commit: "cb5f08f"
18139
+ }
18140
+ ],
18141
+ dependencyBumps: []
18142
+ },
18143
+ {
18144
+ version: "10.3.0",
18145
+ entries: [
18146
+ {
18147
+ bump: "minor",
18148
+ title: "`uni-button`: the focus ring is themed, and the theme now outranks the reset.",
18149
+ body: "**Five of the twelve variants had no visible keyboard focus ring.** The ring\nresolved the variant _name_ as a colour token \u2014 the pattern 10.2.0 removed from\ncheckbox, radio and toggle, missed on the one component where it costs an\naccessibility failure rather than a wrong colour:\n\n```ts\noutline: `2px solid ${this.theme.colors()[this.variant()]}`;\n```\n\n`ghost` resolves to `transparent`, so its ring was drawn invisibly.\n`light`, `onLight`, `dark` and `onDark` have no colour token at all, so the\ndeclaration became `2px solid undefined` and the parser dropped it \u2014 as would\nany intent a consumer registers. In every case `outline-offset` survived, so\nthe element still shifted on focus and the missing ring went unnoticed. This\nwas live without the registry involved.\n\nThe colour now comes from the variant's theme entry via `variantOptions`, the\nmechanism the selection controls already use, and falls back to the reserved\n`primary` accent rather than to nothing. Each variant keeps the ring colour it\nhad; `ghost` gains a visible one. The ring also routes through the shared\n`focusRingStyle`, so a theme defining `focusRing` primitives restyles the button\nalongside every other control.\n\n**A theme could not give a button a border.** `border`, `outline`, `overflow`\nand `transition` were applied _after_ the theme's styles, so a variant\ndeclaring a border was silently erased and `!important` was the only way\nthrough \u2014 which then spread to every state adjusting that border, since the\nshorthand outranks the longhand.\n\nThe base theme was caught by its own reset: `secondary` is commented \"Hollow\"\nand declares `1px solid`, and has been rendering borderless. **It now renders\nits border** \u2014 the one visible change here for anyone on the default theme.\n\nThose four properties move ahead of the theme's styles, resolving the\n`TODO: Set priority on theme-defined styles` that sat on this line. Structure\nthe component genuinely owns \u2014 `position` for the ripple, the symbol slots \u2014\nstays after, and the reset still applies to every variant that does not\noverride it.\n\n**`uni-icon-button`'s hover moved to the theme too.** It branched on\n`variant() === 'ghost'` to choose between a raised shadow and a translucent\nwash, after the theme's own styles. Being a binary partition, every intent a\nconsumer registered fell into the not-ghost half and was given a lift whether\nor not it suited \u2014 a recessive intent included \u2014 and no theme could correct it.\nBoth themes in this repo declare a ghost hover and had it silently overridden.\n\nBoth treatments now live in `iconButton.variants` beside the colours they belong\nwith. Rendering is unchanged for the variants the theme styles; a variant it\ndoes not style no longer receives a hover it never asked for, and the `disabled`\nvariant loses one it should never have had, since its block is also spread into\n`&:disabled`.\n\n**`uni-icon-button` had no focus indicator at all.** Its structural block cleared\nthe user-agent outline and put nothing back, in every variant \u2014 so the close\naffordance in every dialog and drawer header was unreachable-looking under\nkeyboard navigation. This was not reported; it was found while verifying the\nbutton fix above.\n\nIt now draws the shared ring, with its colour read from the same\n`variantOptions.focusColor` the button uses. The indicator is applied last on\npurpose: its appearance is the theme's, through `focusColor` and the `focusRing`\nprimitives, but whether one exists is not a style a theme should be able to\nswitch off by accident.",
18150
+ commit: "ab1689a"
18151
+ }
18152
+ ],
18153
+ dependencyBumps: []
18154
+ },
17992
18155
  {
17993
18156
  version: "10.2.1",
17994
18157
  entries: [],
@@ -18525,6 +18688,16 @@ placeholder="Name or address\u2026"
18525
18688
  {
18526
18689
  package: "@uni-design-system/uni-react",
18527
18690
  releases: [
18691
+ {
18692
+ version: "10.4.0",
18693
+ entries: [],
18694
+ dependencyBumps: []
18695
+ },
18696
+ {
18697
+ version: "10.3.0",
18698
+ entries: [],
18699
+ dependencyBumps: []
18700
+ },
18528
18701
  {
18529
18702
  version: "10.2.1",
18530
18703
  entries: [],
@@ -18768,6 +18941,16 @@ placeholder="Name or address\u2026"
18768
18941
  {
18769
18942
  package: "@uni-design-system/uni-mcp",
18770
18943
  releases: [
18944
+ {
18945
+ version: "10.4.0",
18946
+ entries: [],
18947
+ dependencyBumps: []
18948
+ },
18949
+ {
18950
+ version: "10.3.0",
18951
+ entries: [],
18952
+ dependencyBumps: []
18953
+ },
18771
18954
  {
18772
18955
  version: "10.2.1",
18773
18956
  entries: [
@@ -20032,6 +20215,10 @@ var BaseMotion = {
20032
20215
  easing: "ease"
20033
20216
  }
20034
20217
  };
20218
+ var BaseBackdrops = { scrim: {
20219
+ background: "rgba(255, 255, 255, 0.6)",
20220
+ backdropFilter: "blur(2px)"
20221
+ } };
20035
20222
  var BaseRadii = {
20036
20223
  none: "none",
20037
20224
  xxs: "4px",
@@ -20106,9 +20293,10 @@ var buildComponents = (c) => ({
20106
20293
  divider: "light",
20107
20294
  elevation: "menu",
20108
20295
  padding: "md",
20109
- backdrop: { background: "rgba(0, 0, 0, 0.4)" },
20296
+ backdrop: "scrim",
20110
20297
  scrim: true,
20111
- background: "solid"
20298
+ background: "solid",
20299
+ motion: "panel"
20112
20300
  } },
20113
20301
  drawerHeader: { options: {
20114
20302
  color: void 0,
@@ -20223,17 +20411,18 @@ var buildComponents = (c) => ({
20223
20411
  color: "primary-surface",
20224
20412
  border: "quaternary",
20225
20413
  padding: "sm",
20414
+ bodyPadding: void 0,
20415
+ inset: "lg",
20226
20416
  elevation: "dialog",
20227
- backdrop: {
20228
- background: "rgba(255, 255, 255, 0.6)",
20229
- backdropFilter: "blur(2px)"
20230
- }
20417
+ backdrop: "scrim",
20418
+ motion: "panel"
20231
20419
  } },
20232
20420
  dialogButtons: { options: {
20233
20421
  gap: "md",
20234
20422
  padding: "md",
20235
20423
  paddingBottom: "lg",
20236
20424
  justifyContent: "center",
20425
+ divider: void 0,
20237
20426
  confirmButtonVariant: "primary",
20238
20427
  cancelButtonVariant: "warn",
20239
20428
  buttonSize: "lg",
@@ -20246,6 +20435,7 @@ var buildComponents = (c) => ({
20246
20435
  height: 48,
20247
20436
  textRole: "title-large",
20248
20437
  textAlign: "center",
20438
+ divider: void 0,
20249
20439
  closeButtonIcon: "close",
20250
20440
  closeButtonSize: "md"
20251
20441
  } },
@@ -20542,6 +20732,15 @@ var buildComponents = (c) => ({
20542
20732
  cursor: "pointer",
20543
20733
  transition: "all 0.28s ease"
20544
20734
  },
20735
+ variantOptions: {
20736
+ primary: { focusColor: "primary" },
20737
+ secondary: { focusColor: "secondary" },
20738
+ tertiary: { focusColor: "tertiary" },
20739
+ warn: { focusColor: "warn" },
20740
+ success: { focusColor: "success" },
20741
+ disabled: { focusColor: "disabled" },
20742
+ ghost: { focusColor: "primary" }
20743
+ },
20545
20744
  variants: {
20546
20745
  ghost: {
20547
20746
  backgroundColor: "transparent",
@@ -20613,30 +20812,45 @@ var buildComponents = (c) => ({
20613
20812
  },
20614
20813
  iconButton: {
20615
20814
  options: { borderRadius: "max" },
20815
+ variantOptions: {
20816
+ primary: { focusColor: "primary" },
20817
+ secondary: { focusColor: "secondary" },
20818
+ tertiary: { focusColor: "tertiary" },
20819
+ warn: { focusColor: "warn" },
20820
+ success: { focusColor: "success" },
20821
+ disabled: { focusColor: "disabled" },
20822
+ ghost: { focusColor: "primary" }
20823
+ },
20616
20824
  variants: {
20617
20825
  ghost: {
20618
20826
  backgroundColor: "transparent",
20619
- color: "currentcolor"
20827
+ color: "currentcolor",
20828
+ "&:hover": { backgroundColor: "rgba(0,0,0,0.1)" }
20620
20829
  },
20621
20830
  primary: {
20622
20831
  backgroundColor: c.primary,
20623
- color: c["on-primary"]
20832
+ color: c["on-primary"],
20833
+ "&:hover": { boxShadow: BaseShadows.raised }
20624
20834
  },
20625
20835
  secondary: {
20626
20836
  backgroundColor: c.secondary,
20627
- color: c["on-secondary"]
20837
+ color: c["on-secondary"],
20838
+ "&:hover": { boxShadow: BaseShadows.raised }
20628
20839
  },
20629
20840
  tertiary: {
20630
20841
  backgroundColor: c.tertiary,
20631
- color: c["on-tertiary"]
20842
+ color: c["on-tertiary"],
20843
+ "&:hover": { boxShadow: BaseShadows.raised }
20632
20844
  },
20633
20845
  warn: {
20634
20846
  backgroundColor: c.warn,
20635
- color: c["on-warn"]
20847
+ color: c["on-warn"],
20848
+ "&:hover": { boxShadow: BaseShadows.raised }
20636
20849
  },
20637
20850
  success: {
20638
20851
  backgroundColor: c.success,
20639
- color: c["on-success"]
20852
+ color: c["on-success"],
20853
+ "&:hover": { boxShadow: BaseShadows.raised }
20640
20854
  },
20641
20855
  disabled: {
20642
20856
  backgroundColor: "transparent !important",
@@ -20892,7 +21106,7 @@ var deepMerge = (base, override) => {
20892
21106
  for (const [key, value] of Object.entries(override)) out[key] = isRecord$1(value) && isRecord$1(out[key]) ? deepMerge(out[key], value) : value;
20893
21107
  return out;
20894
21108
  };
20895
- var createTheme = ({ id, name, colors, icons = {}, radii = BaseRadii, shadows = BaseShadows, motion, typography, borders, thicknesses, spacing, components }) => ({
21109
+ var createTheme = ({ id, name, colors, icons = {}, radii = BaseRadii, shadows = BaseShadows, motion, backdrops, typography, borders, thicknesses, spacing, components }) => ({
20896
21110
  id,
20897
21111
  name,
20898
21112
  colors,
@@ -20908,6 +21122,10 @@ var createTheme = ({ id, name, colors, icons = {}, radii = BaseRadii, shadows =
20908
21122
  ...BaseMotion,
20909
21123
  ...motion
20910
21124
  },
21125
+ backdrops: {
21126
+ ...BaseBackdrops,
21127
+ ...backdrops
21128
+ },
20911
21129
  thicknesses: {
20912
21130
  ...BaseThicknesses,
20913
21131
  ...thicknesses
@@ -21938,7 +22156,7 @@ function createUniServer() {
21938
22156
  "list-tokens",
21939
22157
  {
21940
22158
  title: "List design tokens",
21941
- description: "Inventory of Uni design tokens. Filter by `type` (color, spacing, radius, shadow, border, thickness, typography, ...), `kind` (style|behavioral), or `theme`.",
22159
+ description: "Inventory of Uni design tokens. Filter by `type` (color, spacing, radius, shadow, border, backdrop, thickness, typography, ...), `kind` (style|behavioral), or `theme`.",
21942
22160
  inputSchema: {
21943
22161
  type: z.string().optional(),
21944
22162
  kind: z.enum(["style", "behavioral"]).optional(),
@@ -22258,4 +22476,4 @@ export {
22258
22476
  buildStoredTheme,
22259
22477
  createUniServer
22260
22478
  };
22261
- //# sourceMappingURL=chunk-JMAG4RA3.js.map
22479
+ //# sourceMappingURL=chunk-QZ5TESCY.js.map