@motifx-community/ui 0.1.0-beta.0 → 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +16 -10
  3. package/dist/components/calendar/Calendar.d.ts +12 -0
  4. package/dist/components/calendar/calendar-props.d.ts +5 -0
  5. package/dist/components/daterangebox/DateRangeBox.d.ts +121 -0
  6. package/dist/components/daterangebox/date-range-box-props.d.ts +35 -0
  7. package/dist/components/daterangebox/date-range-preset.d.ts +6 -0
  8. package/dist/components/daterangebox/date-range.d.ts +2 -0
  9. package/dist/components/daterangebox/index.d.ts +4 -0
  10. package/dist/components/dropdown/DropDown.d.ts +14 -0
  11. package/dist/components/dropdown/drop-down-props.d.ts +5 -0
  12. package/dist/components/fileuploader/FileUploader.d.ts +133 -0
  13. package/dist/components/fileuploader/file-uploader-props.d.ts +46 -0
  14. package/dist/components/fileuploader/files-added-event-args.d.ts +9 -0
  15. package/dist/components/fileuploader/index.d.ts +7 -0
  16. package/dist/components/fileuploader/upload-event-args.d.ts +10 -0
  17. package/dist/components/fileuploader/upload-item.d.ts +12 -0
  18. package/dist/components/fileuploader/upload-mode.d.ts +2 -0
  19. package/dist/components/fileuploader/upload-status.d.ts +2 -0
  20. package/dist/components/loadpanel/LoadPanel.d.ts +70 -0
  21. package/dist/components/loadpanel/index.d.ts +3 -0
  22. package/dist/components/loadpanel/load-panel-props.d.ts +29 -0
  23. package/dist/components/loadpanel/load-panel-target.d.ts +3 -0
  24. package/dist/components/popover/Popover.d.ts +98 -0
  25. package/dist/components/popover/index.d.ts +5 -0
  26. package/dist/components/popover/popover-close-reason.d.ts +2 -0
  27. package/dist/components/popover/popover-closing-event-args.d.ts +8 -0
  28. package/dist/components/popover/popover-props.d.ts +39 -0
  29. package/dist/components/popover/popover-show-on.d.ts +2 -0
  30. package/dist/components/scheduler/view/AgendaView.d.ts +1 -1
  31. package/dist/components/scrollview/ScrollView.d.ts +109 -0
  32. package/dist/components/scrollview/index.d.ts +7 -0
  33. package/dist/components/scrollview/pull-down-event-args.d.ts +9 -0
  34. package/dist/components/scrollview/reach-bottom-event-args.d.ts +9 -0
  35. package/dist/components/scrollview/scroll-event-args.d.ts +7 -0
  36. package/dist/components/scrollview/scroll-view-bars.d.ts +2 -0
  37. package/dist/components/scrollview/scroll-view-direction.d.ts +2 -0
  38. package/dist/components/scrollview/scroll-view-props.d.ts +31 -0
  39. package/dist/components/sortable/Sortable.d.ts +106 -0
  40. package/dist/components/sortable/index.d.ts +5 -0
  41. package/dist/components/sortable/sortable-drag-event-args.d.ts +15 -0
  42. package/dist/components/sortable/sortable-drop-event-args.d.ts +11 -0
  43. package/dist/components/sortable/sortable-orientation.d.ts +2 -0
  44. package/dist/components/sortable/sortable-props.d.ts +34 -0
  45. package/dist/components/stepper/Stepper.d.ts +121 -0
  46. package/dist/components/stepper/Wizard.d.ts +112 -0
  47. package/dist/components/stepper/WizardStep.d.ts +44 -0
  48. package/dist/components/stepper/index.d.ts +13 -0
  49. package/dist/components/stepper/step-changed-event-args.d.ts +11 -0
  50. package/dist/components/stepper/step-changing-event-args.d.ts +18 -0
  51. package/dist/components/stepper/stepper-item.d.ts +20 -0
  52. package/dist/components/stepper/stepper-label-position.d.ts +2 -0
  53. package/dist/components/stepper/stepper-orientation.d.ts +1 -0
  54. package/dist/components/stepper/stepper-props.d.ts +32 -0
  55. package/dist/components/stepper/stepper-status.d.ts +2 -0
  56. package/dist/components/stepper/wizard-finishing-event-args.d.ts +7 -0
  57. package/dist/components/stepper/wizard-props.d.ts +48 -0
  58. package/dist/components/stepper/wizard-step-props.d.ts +32 -0
  59. package/dist/core/flow-home.d.ts +6 -0
  60. package/dist/core/fold-text.d.ts +6 -0
  61. package/dist/core/ui-locale.d.ts +0 -2
  62. package/dist/core/ui-strings.d.ts +43 -0
  63. package/dist/generated/tokens.d.ts +1186 -11
  64. package/dist/index.d.ts +8 -1
  65. package/dist/index.js +22542 -20143
  66. package/dist/index.js.map +1 -1
  67. package/dist/locales/en.json +39 -1
  68. package/dist/locales/tr.json +39 -1
  69. package/dist/parts/data/DataItems.d.ts +5 -0
  70. package/dist/parts/data/KeyedItems.d.ts +2 -0
  71. package/dist/styles.css +1912 -8
  72. package/dist/tokens/index.d.ts +1186 -11
  73. package/dist/tokens/index.js +1186 -11
  74. package/dist/tokens/index.js.map +1 -1
  75. package/dist/tr-B218zMtu.js +1191 -0
  76. package/dist/tr-B218zMtu.js.map +1 -0
  77. package/docs/accordion.md +1 -1
  78. package/docs/actionsheet.md +1 -1
  79. package/docs/avatar.md +1 -1
  80. package/docs/badge.md +1 -1
  81. package/docs/bottomsheet.md +3 -3
  82. package/docs/breadcrumb.md +2 -2
  83. package/docs/button.md +3 -3
  84. package/docs/buttongroup.md +1 -1
  85. package/docs/calendar.md +1 -1
  86. package/docs/card.md +1 -1
  87. package/docs/checkbox.md +3 -3
  88. package/docs/chip.md +1 -1
  89. package/docs/colorbox.md +1 -1
  90. package/docs/combobox.md +1 -1
  91. package/docs/control.md +1 -1
  92. package/docs/datagrid-api.md +3 -3
  93. package/docs/datagrid-bands.md +1 -1
  94. package/docs/datagrid-drag-select.md +1 -1
  95. package/docs/datagrid-drag.md +1 -1
  96. package/docs/datagrid-editing.md +1 -1
  97. package/docs/datagrid-filtering.md +1 -1
  98. package/docs/datagrid-forms.md +1 -1
  99. package/docs/datagrid-grouping.md +1 -1
  100. package/docs/datagrid-layout.md +1 -1
  101. package/docs/datagrid-lookups.md +1 -1
  102. package/docs/datagrid-master-detail.md +1 -1
  103. package/docs/datagrid-scrolling.md +1 -1
  104. package/docs/datagrid-selection.md +1 -1
  105. package/docs/datagrid.md +1 -1
  106. package/docs/datebox.md +3 -3
  107. package/docs/daterangebox.md +192 -0
  108. package/docs/drawer.md +1 -1
  109. package/docs/dropdown.md +13 -7
  110. package/docs/fileuploader.md +201 -0
  111. package/docs/filterbuilder.md +3 -3
  112. package/docs/formlayout.md +1 -1
  113. package/docs/home.md +1 -1
  114. package/docs/keyboard.md +1 -1
  115. package/docs/language.md +229 -0
  116. package/docs/layout.md +3 -3
  117. package/docs/listbox.md +3 -3
  118. package/docs/loadpanel.md +184 -0
  119. package/docs/lookup.md +86 -2
  120. package/docs/menus.md +1 -1
  121. package/docs/numberbox.md +3 -3
  122. package/docs/pagination.md +1 -1
  123. package/docs/popover.md +221 -0
  124. package/docs/progress.md +3 -3
  125. package/docs/radiogroup.md +1 -1
  126. package/docs/rating.md +1 -1
  127. package/docs/scheduler-agenda.md +1 -1
  128. package/docs/scheduler-big-data.md +1 -1
  129. package/docs/scheduler-editing.md +1 -1
  130. package/docs/scheduler-form.md +1 -1
  131. package/docs/scheduler-icalendar.md +1 -1
  132. package/docs/scheduler-mobile.md +1 -1
  133. package/docs/scheduler-recurrence.md +1 -1
  134. package/docs/scheduler-resources.md +1 -1
  135. package/docs/scheduler-timeline.md +1 -1
  136. package/docs/scheduler.md +1 -1
  137. package/docs/scrollview.md +185 -0
  138. package/docs/showcase.md +1 -1
  139. package/docs/skeleton.md +1 -1
  140. package/docs/slider.md +3 -3
  141. package/docs/sortable.md +213 -0
  142. package/docs/stepper.md +238 -0
  143. package/docs/switch.md +1 -1
  144. package/docs/tabdocs-dock.md +1 -1
  145. package/docs/tabdocs-drag.md +1 -1
  146. package/docs/tabdocs-menus.md +1 -1
  147. package/docs/tabdocs-mobile.md +1 -1
  148. package/docs/tabdocs-tabs.md +1 -1
  149. package/docs/tabdocs-windows.md +1 -1
  150. package/docs/tabdocs-workspace.md +1 -1
  151. package/docs/tabdocs.md +1 -1
  152. package/docs/tabs.md +3 -3
  153. package/docs/tagbox.md +3 -3
  154. package/docs/textarea.md +3 -3
  155. package/docs/textbox.md +3 -3
  156. package/docs/toast.md +3 -3
  157. package/docs/tokens.md +357 -122
  158. package/docs/toolbar.md +3 -3
  159. package/docs/tooltip.md +1 -1
  160. package/docs/treeview.md +3 -3
  161. package/docs/window.md +3 -3
  162. package/docs/wizard.md +240 -0
  163. package/llms-full.txt +2518 -245
  164. package/llms.txt +10 -1
  165. package/package.json +10 -4
package/llms-full.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # @motifx-community/ui
2
2
 
3
- > UI components for MotifJS (@motifx/core) on the MotifJS design system. Version 0.1.0-beta.0: a preview, its API may still change before 1.0.
3
+ > UI components for MotifJS (@motifx/core) on the MotifJS design system. Version 0.1.0-beta.2: a preview, its API may still change before 1.0.
4
4
 
5
5
  Built on MotifJS (`@motifx/core`): a component is an object, made in JSX or with `new`, whose every prop takes a value or a function (`Bind<T>`); `x-model` binds a value two-way. The look is the design system’s (`@motifx-community/design-system`): five design languages (`data-identity`), light and dark themes, density.
6
6
 
@@ -18,6 +18,7 @@ Built on MotifJS (`@motifx/core`): a component is an object, made in JSX or with
18
18
 
19
19
  - [Control](docs/control.md): The base of every control in the package. It gives each one the same `text`, `enabled`, `visible` and `tabStop`, and the same focus methods, whether the…
20
20
  - [Keyboard and focus](docs/keyboard.md): The rules every control follows: Tab order, the active control of a container, focus that never falls to `<body>`, `&File` access keys and app-wide shortcuts.
21
+ - [Language](docs/language.md): The texts the controls write, the locale their dates and numbers follow, and the direction: one `uiLocale` for the kit, with a pack per language loaded as…
21
22
 
22
23
  ## Buttons
23
24
 
@@ -32,10 +33,12 @@ Built on MotifJS (`@motifx/core`): a component is an object, made in JSX or with
32
33
  - [TextArea](docs/textarea.md): A text field of several lines: a box that grows with the text or that the user drags bigger, a character counter, a clear button, Ctrl+Enter to send, and…
33
34
  - [NumberBox](docs/numberbox.md): A number field: arrow keys, PageUp / PageDown and spin buttons that repeat while held, bounds, a step without float noise, a format for display (currency,…
34
35
  - [DateBox](docs/datebox.md): A date, a time or both. It is typed in the order of the locale through a mask, or picked from a calendar and a list of times; `min`, `max` and…
36
+ - [DateRangeBox](docs/daterangebox.md): A start and an end date in one field: typed through two masks, or picked on two months side by side, from ready-made ranges, within the dates and the span…
35
37
  - [ColorBox and ColorPicker](docs/colorbox.md): A colour as a field, with a picker in a popup; or the picker on its own. The picker has an area of saturation and brightness, a hue strip, an opacity strip,…
36
38
  - [Calendar](docs/calendar.md): A month of days to pick a date from, with a year and a decade view to get far quickly. It is the picker of DateBox, and it works on its own.
37
39
  - [Slider](docs/slider.md): A value picked on a track by dragging a thumb or with the keys: one number, or a range with two thumbs. Steps, marks with labels, a value bubble, a vertical…
38
40
  - [Rating](docs/rating.md): A row of stars to give a score or to show one, whole or by halves. It is a field: label, help text, rules and `x-model` work as in every field.
41
+ - [FileUploader](docs/fileuploader.md): Files chosen with a button or dropped on the box, listed with their size and what happens to them: uploaded as they come, on a button or from code, with…
39
42
 
40
43
  ## Choice
41
44
 
@@ -50,6 +53,8 @@ Built on MotifJS (`@motifx/core`): a component is an object, made in JSX or with
50
53
 
51
54
  - [ProgressBar and Spinner](docs/progress.md): ProgressBar shows how far some work is, as a line or a circle, or that it runs when that is not known. Spinner says "busy, wait": a turning ring, alone or…
52
55
  - [Tooltip](docs/tooltip.md): A short description shown next to an element: after the pointer rests on it, when it gets keyboard focus, or from code. It can be hovered, Escape hides it,…
56
+ - [Popover](docs/popover.md): Content next to the element it belongs to: a title, a close button, a form, a card. It opens on a press or while the pointer rests on its target, follows…
57
+ - [LoadPanel](docs/loadpanel.md): A “loading” layer over a container or the whole page: a shade, a pane with the kit’s spinner and a message, a Cancel button when the work can be stopped.…
53
58
  - [Toast](docs/toast.md): Short notifications at an edge of the window: four tones, an action such as Undo, a time of their own or none, six positions and a limit on how many show at…
54
59
 
55
60
  ## Display
@@ -65,12 +70,16 @@ Built on MotifJS (`@motifx/core`): a component is an object, made in JSX or with
65
70
  - [Tabs](docs/tabs.md): Tabs show one panel at a time under a strip of tabs: from JSX or from code, closable, with icons and badges, scroll buttons when the tabs do not fit, four…
66
71
  - [Breadcrumb](docs/breadcrumb.md): The way to the current page: each step a link or a button, the current page last. Steps that do not fit go into a menu after the first.
67
72
  - [Pagination](docs/pagination.md): Moving through pages of items: the sizes to choose from, where the page stands, the steps and a button per page around the current one. It turns compact…
73
+ - [Stepper](docs/stepper.md): The steps of a longer task and where the user stands in them: an indicator and a text per step, a line between them, the steps before the current one…
74
+ - [Wizard](docs/wizard.md): A task in steps: a [Stepper](stepper.md) above or beside one page per step, and the Back and Next buttons under them. Next validates the page first; on the…
68
75
  - [Accordion](docs/accordion.md): An accordion opens and closes sections under their headers: one at a time or several, kept open, with icons, three looks and sections built when they are…
69
76
  - [Window and dialog](docs/window.md): A window or a dialog on a native `<dialog>`: one form, shown modeless or modal by whoever shows it. It has a title bar, moves, resizes, minimizes and…
70
77
  - [BottomSheet](docs/bottomsheet.md): A panel that comes up from the bottom of the page or of a container and stops at a few heights: a peek, half, full, as tall as its content, or heights of…
71
78
  - [Drawer](docs/drawer.md): A panel that slides in from an edge of the page or of a container, over the content or pushing it aside. A finger swipes it in from the edge and back again;…
72
79
  - [ActionSheet](docs/actionsheet.md): A list of commands that comes up from the bottom, made of the kit's menu items and large enough for a finger, with a title, a message and a cancel button…
73
80
  - [Layout](docs/layout.md): Containers that place controls: `Stack` (a row or a column), `Grid` (rows and columns), `Panel` (a plain box that can scroll), `GroupBox` (a titled frame),…
81
+ - [ScrollView](docs/scrollview.md): Content that scrolls in a box of its own: the bars shown as told, a pull from the top that asks for what is new, a reach near the end that asks for more.…
82
+ - [Sortable](docs/sortable.md): Items the user puts in order by dragging them, with the pointer or a finger, or with the keys; lists of one group take each other’s items. A drop moves the…
74
83
  - [FormLayout](docs/formlayout.md): Lays out the fields of a data object on a grid. Each field gets an editor — by name, or by the type of its value — bound to the object both ways; groups,…
75
84
 
76
85
  ## Data
@@ -240,7 +249,7 @@ tokens, with examples.
240
249
 
241
250
  # @motifx-community/ui
242
251
 
243
- > Get started · @motifx-community/ui 0.1.0-beta.0
252
+ > Get started · @motifx-community/ui 0.1.0-beta.2
244
253
 
245
254
  Components for MotifJS that work the way desktop UI does — created when needed, shown anywhere, closed and disposed like windows — drawn from the MotifJS design system's tokens.
246
255
 
@@ -298,7 +307,7 @@ The look comes from `@motifx-community/design-system`: its tokens, three themes,
298
307
 
299
308
  # Showcase: an order screen
300
309
 
301
- > Get started · @motifx-community/ui 0.1.0-beta.0
310
+ > Get started · @motifx-community/ui 0.1.0-beta.2
302
311
 
303
312
  An order screen built with the kit, the way a MotifJS app is built: the state and the operations live in a model (`OrderModel`), the page binds to it. The customer list is a data source of 5,000 rows that answers like a server.
304
313
 
@@ -307,7 +316,7 @@ An order screen built with the kit, the way a MotifJS app is built: the state an
307
316
 
308
317
  # Design tokens
309
318
 
310
- > Get started · @motifx-community/ui 0.1.0-beta.0
319
+ > Get started · @motifx-community/ui 0.1.0-beta.2
311
320
 
312
321
  Five layers. The first four — primitives, the design language's own scales, semantic tokens per theme, density — come from `@motifx-community/design-system` and are listed here for reference. The fifth, the component tokens, is this kit's own: a knob per component, each referencing a design-system token, written in `@layer mx.components`. Every design language gives every one of them its own value.
313
322
 
@@ -444,19 +453,19 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
444
453
  | `avatar.avatar.accent.bg` | `--mx-avatar-avatar-accent-bg` | `color.accent.subtle` | `#fbe6de` |
445
454
  | `avatar.avatar.accent.color` | `--mx-avatar-avatar-accent-color` | `color.accent.on-subtle` | `#983318` |
446
455
  | `avatar.avatar.success.bg` | `--mx-avatar-avatar-success-bg` | `color.success.subtle` | `#dff6dd` |
447
- | `avatar.avatar.success.color` | `--mx-avatar-avatar-success-color` | `color.success.fg` | `#0c6a0c` |
456
+ | `avatar.avatar.success.color` | `--mx-avatar-avatar-success-color` | `color.success.fg` | `#006402` |
448
457
  | `avatar.avatar.caution.bg` | `--mx-avatar-avatar-caution-bg` | `color.caution.subtle` | `#fff4ce` |
449
- | `avatar.avatar.caution.color` | `--mx-avatar-avatar-caution-color` | `color.caution.fg` | `#845000` |
458
+ | `avatar.avatar.caution.color` | `--mx-avatar-avatar-caution-color` | `color.caution.fg` | `#754702` |
450
459
  | `avatar.avatar.danger.bg` | `--mx-avatar-avatar-danger-bg` | `color.danger.subtle` | `#fde7e9` |
451
- | `avatar.avatar.danger.color` | `--mx-avatar-avatar-danger-color` | `color.danger.fg` | `#b3261a` |
460
+ | `avatar.avatar.danger.color` | `--mx-avatar-avatar-danger-color` | `color.danger.fg` | `#b03659` |
452
461
  | `avatar.avatar.info.bg` | `--mx-avatar-avatar-info-bg` | `` | `initial` |
453
462
  | `avatar.avatar.info.color` | `--mx-avatar-avatar-info-color` | `` | `initial` |
454
463
  | `avatar.status.radius` | `--mx-avatar-status-radius` | `radius.full` | `9999px` |
455
464
  | `avatar.status.border-width` | `--mx-avatar-status-border-width` | `border.width.2` | `2px` |
456
465
  | `avatar.status.border-color` | `--mx-avatar-status-border-color` | `color.bg.surface` | `#f8f7f3` |
457
- | `avatar.status.online.bg` | `--mx-avatar-status-online-bg` | `color.success.solid` | `#0c6a0c` |
458
- | `avatar.status.away.bg` | `--mx-avatar-status-away-bg` | `color.caution.solid` | `#845000` |
459
- | `avatar.status.busy.bg` | `--mx-avatar-status-busy-bg` | `color.danger.solid` | `#b3261a` |
466
+ | `avatar.status.online.bg` | `--mx-avatar-status-online-bg` | `color.success.solid` | `#006402` |
467
+ | `avatar.status.away.bg` | `--mx-avatar-status-away-bg` | `color.caution.solid` | `#754702` |
468
+ | `avatar.status.busy.bg` | `--mx-avatar-status-busy-bg` | `color.danger.solid` | `#b03659` |
460
469
  | `avatar.status.offline.bg` | `--mx-avatar-status-offline-bg` | `color.fg.tertiary` | `#8c8a82` |
461
470
  | `avatar.status.offline.border-color` | `--mx-avatar-status-offline-border-color` | `` | `initial` |
462
471
  | `avatar.status-icon.online.display` | `--mx-avatar-status-icon-online-display` | `` | `initial` |
@@ -493,11 +502,11 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
493
502
  | `badge.badge.accent.color` | `--mx-badge-badge-accent-color` | `color.accent.on-solid` | `#ffffff` |
494
503
  | `badge.badge.info.bg` | `--mx-badge-badge-info-bg` | `color.info.solid` | `#5e5c55` |
495
504
  | `badge.badge.info.color` | `--mx-badge-badge-info-color` | `color.info.on-solid` | `#e1e0da` |
496
- | `badge.badge.success.bg` | `--mx-badge-badge-success-bg` | `color.success.solid` | `#0c6a0c` |
505
+ | `badge.badge.success.bg` | `--mx-badge-badge-success-bg` | `color.success.solid` | `#006402` |
497
506
  | `badge.badge.success.color` | `--mx-badge-badge-success-color` | `color.success.on-solid` | `#ffffff` |
498
- | `badge.badge.caution.bg` | `--mx-badge-badge-caution-bg` | `color.caution.solid` | `#845000` |
507
+ | `badge.badge.caution.bg` | `--mx-badge-badge-caution-bg` | `color.caution.solid` | `#754702` |
499
508
  | `badge.badge.caution.color` | `--mx-badge-badge-caution-color` | `color.caution.on-solid` | `#ffffff` |
500
- | `badge.badge.danger.bg` | `--mx-badge-badge-danger-bg` | `color.danger.solid` | `#b3261a` |
509
+ | `badge.badge.danger.bg` | `--mx-badge-badge-danger-bg` | `color.danger.solid` | `#b03659` |
501
510
  | `badge.badge.danger.color` | `--mx-badge-badge-danger-color` | `color.danger.on-solid` | `#ffffff` |
502
511
  | `badge.badge.subtle.bg` | `--mx-badge-badge-subtle-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
503
512
  | `badge.badge.subtle.color` | `--mx-badge-badge-subtle-color` | `color.fg.primary` | `#1d1c1a` |
@@ -506,11 +515,11 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
506
515
  | `badge.badge.subtle-info.bg` | `--mx-badge-badge-subtle-info-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
507
516
  | `badge.badge.subtle-info.color` | `--mx-badge-badge-subtle-info-color` | `color.fg.primary` | `#1d1c1a` |
508
517
  | `badge.badge.subtle-success.bg` | `--mx-badge-badge-subtle-success-bg` | `color.success.subtle` | `#dff6dd` |
509
- | `badge.badge.subtle-success.color` | `--mx-badge-badge-subtle-success-color` | `color.success.fg` | `#0c6a0c` |
518
+ | `badge.badge.subtle-success.color` | `--mx-badge-badge-subtle-success-color` | `color.success.fg` | `#006402` |
510
519
  | `badge.badge.subtle-caution.bg` | `--mx-badge-badge-subtle-caution-bg` | `color.caution.subtle` | `#fff4ce` |
511
- | `badge.badge.subtle-caution.color` | `--mx-badge-badge-subtle-caution-color` | `color.caution.fg` | `#845000` |
520
+ | `badge.badge.subtle-caution.color` | `--mx-badge-badge-subtle-caution-color` | `color.caution.fg` | `#754702` |
512
521
  | `badge.badge.subtle-danger.bg` | `--mx-badge-badge-subtle-danger-bg` | `color.danger.subtle` | `#fde7e9` |
513
- | `badge.badge.subtle-danger.color` | `--mx-badge-badge-subtle-danger-color` | `color.danger.fg` | `#b3261a` |
522
+ | `badge.badge.subtle-danger.color` | `--mx-badge-badge-subtle-danger-color` | `color.danger.fg` | `#b03659` |
514
523
  | `badge.badge.outline.bg` | `--mx-badge-badge-outline-bg` | `` | `rgb(0 0 0 / 0)` |
515
524
  | `badge.badge.outline.color` | `--mx-badge-badge-outline-color` | `color.fg.secondary` | `#5e5c55` |
516
525
  | `badge.badge.outline.border-width` | `--mx-badge-badge-outline-border-width` | `border.width.1` | `1px` |
@@ -519,12 +528,12 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
519
528
  | `badge.badge.outline-accent.border-color` | `--mx-badge-badge-outline-accent-border-color` | `color.accent.fg` | `#983318` |
520
529
  | `badge.badge.outline-info.color` | `--mx-badge-badge-outline-info-color` | `color.fg.secondary` | `#5e5c55` |
521
530
  | `badge.badge.outline-info.border-color` | `--mx-badge-badge-outline-info-border-color` | `color.fg.secondary` | `#5e5c55` |
522
- | `badge.badge.outline-success.color` | `--mx-badge-badge-outline-success-color` | `color.success.fg` | `#0c6a0c` |
523
- | `badge.badge.outline-success.border-color` | `--mx-badge-badge-outline-success-border-color` | `color.success.fg` | `#0c6a0c` |
524
- | `badge.badge.outline-caution.color` | `--mx-badge-badge-outline-caution-color` | `color.caution.fg` | `#845000` |
525
- | `badge.badge.outline-caution.border-color` | `--mx-badge-badge-outline-caution-border-color` | `color.caution.fg` | `#845000` |
526
- | `badge.badge.outline-danger.color` | `--mx-badge-badge-outline-danger-color` | `color.danger.fg` | `#b3261a` |
527
- | `badge.badge.outline-danger.border-color` | `--mx-badge-badge-outline-danger-border-color` | `color.danger.fg` | `#b3261a` |
531
+ | `badge.badge.outline-success.color` | `--mx-badge-badge-outline-success-color` | `color.success.fg` | `#006402` |
532
+ | `badge.badge.outline-success.border-color` | `--mx-badge-badge-outline-success-border-color` | `color.success.fg` | `#006402` |
533
+ | `badge.badge.outline-caution.color` | `--mx-badge-badge-outline-caution-color` | `color.caution.fg` | `#754702` |
534
+ | `badge.badge.outline-caution.border-color` | `--mx-badge-badge-outline-caution-border-color` | `color.caution.fg` | `#754702` |
535
+ | `badge.badge.outline-danger.color` | `--mx-badge-badge-outline-danger-color` | `color.danger.fg` | `#b03659` |
536
+ | `badge.badge.outline-danger.border-color` | `--mx-badge-badge-outline-danger-border-color` | `color.danger.fg` | `#b03659` |
528
537
  | `badge.badge.dot.padding-inline` | `--mx-badge-badge-dot-padding-inline` | `space.0` | `0px` |
529
538
  | `breadcrumb.font-size.sm` | `--mx-breadcrumb-font-size-sm` | `font.size.caption` | `0.75rem` |
530
539
  | `breadcrumb.font-size.md` | `--mx-breadcrumb-font-size-md` | `font.size.body` | `0.875rem` |
@@ -602,8 +611,8 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
602
611
  | `button.face.accent.border-color` | `--mx-button-face-accent-border-color` | `color.accent.solid` | `#c24523` |
603
612
  | `button.face.accent.border-bottom-color` | `--mx-button-face-accent-border-bottom-color` | `color.stroke.on-accent-bottom` | `rgb(0 0 0 / 0.4)` |
604
613
  | `button.face.accent.color` | `--mx-button-face-accent-color` | `color.accent.on-solid` | `#ffffff` |
605
- | `button.face.danger.bg` | `--mx-button-face-danger-bg` | `color.danger.solid` | `#b3261a` |
606
- | `button.face.danger.border-color` | `--mx-button-face-danger-border-color` | `color.danger.solid` | `#b3261a` |
614
+ | `button.face.danger.bg` | `--mx-button-face-danger-bg` | `color.danger.solid` | `#b03659` |
615
+ | `button.face.danger.border-color` | `--mx-button-face-danger-border-color` | `color.danger.solid` | `#b03659` |
607
616
  | `button.face.danger.border-bottom-color` | `--mx-button-face-danger-border-bottom-color` | `color.stroke.on-accent-bottom` | `rgb(0 0 0 / 0.4)` |
608
617
  | `button.face.danger.color` | `--mx-button-face-danger-color` | `color.danger.on-solid` | `#ffffff` |
609
618
  | `button.face.outline.bg` | `--mx-button-face-outline-bg` | `` | `rgb(0 0 0 / 0)` |
@@ -612,7 +621,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
612
621
  | `button.face.outline.shadow` | `--mx-button-face-outline-shadow` | `` | `0 0 #0000` |
613
622
  | `button.face.outline.color` | `--mx-button-face-outline-color` | `color.fg.primary` | `#1d1c1a` |
614
623
  | `button.face.outline-accent.color` | `--mx-button-face-outline-accent-color` | `color.accent.fg` | `#983318` |
615
- | `button.face.outline-danger.color` | `--mx-button-face-outline-danger-color` | `color.danger.fg` | `#b3261a` |
624
+ | `button.face.outline-danger.color` | `--mx-button-face-outline-danger-color` | `color.danger.fg` | `#b03659` |
616
625
  | `button.face.ghost.bg` | `--mx-button-face-ghost-bg` | `` | `rgb(0 0 0 / 0)` |
617
626
  | `button.face.ghost.border-bottom-width` | `--mx-button-face-ghost-border-bottom-width` | `border.width.1` | `1px` |
618
627
  | `button.face.ghost.border-color` | `--mx-button-face-ghost-border-color` | `` | `rgb(0 0 0 / 0)` |
@@ -620,7 +629,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
620
629
  | `button.face.ghost.shadow` | `--mx-button-face-ghost-shadow` | `` | `0 0 #0000` |
621
630
  | `button.face.ghost.color` | `--mx-button-face-ghost-color` | `color.fg.primary` | `#1d1c1a` |
622
631
  | `button.face.ghost-accent.color` | `--mx-button-face-ghost-accent-color` | `color.accent.fg` | `#983318` |
623
- | `button.face.ghost-danger.color` | `--mx-button-face-ghost-danger-color` | `color.danger.fg` | `#b3261a` |
632
+ | `button.face.ghost-danger.color` | `--mx-button-face-ghost-danger-color` | `color.danger.fg` | `#b03659` |
624
633
  | `button.face.hover.bg` | `--mx-button-face-hover-bg` | `color.fill.control.secondary` | `#ebeae5` |
625
634
  | `button.face.hover.border-bottom-color` | `--mx-button-face-hover-border-bottom-color` | `color.stroke.control.edge` | `rgb(0 0 0 / 0.3)` |
626
635
  | `button.face.hover.image` | `--mx-button-face-hover-image` | `` | `initial` |
@@ -628,30 +637,30 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
628
637
  | `button.face.accent-hover.bg` | `--mx-button-face-accent-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
629
638
  | `button.face.accent-hover.border-bottom-color` | `--mx-button-face-accent-hover-border-bottom-color` | `color.stroke.on-accent-bottom` | `rgb(0 0 0 / 0.4)` |
630
639
  | `button.face.accent-hover.color` | `--mx-button-face-accent-hover-color` | `color.accent.on-solid` | `#ffffff` |
631
- | `button.face.danger-hover.bg` | `--mx-button-face-danger-hover-bg` | `color.danger.solid-hover` | `#c42b1c` |
640
+ | `button.face.danger-hover.bg` | `--mx-button-face-danger-hover-bg` | `color.danger.solid-hover` | `#c13b61` |
632
641
  | `button.face.danger-hover.border-bottom-color` | `--mx-button-face-danger-hover-border-bottom-color` | `color.stroke.on-accent-bottom` | `rgb(0 0 0 / 0.4)` |
633
642
  | `button.face.danger-hover.color` | `--mx-button-face-danger-hover-color` | `color.danger.on-solid` | `#ffffff` |
634
643
  | `button.face.outline-hover.bg` | `--mx-button-face-outline-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
635
644
  | `button.face.outline-hover.border-color` | `--mx-button-face-outline-hover-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
636
645
  | `button.face.outline-hover.color` | `--mx-button-face-outline-hover-color` | `` | `initial` |
637
646
  | `button.face.outline-accent-hover.color` | `--mx-button-face-outline-accent-hover-color` | `color.accent.fg` | `#983318` |
638
- | `button.face.outline-danger-hover.color` | `--mx-button-face-outline-danger-hover-color` | `color.danger.fg` | `#b3261a` |
647
+ | `button.face.outline-danger-hover.color` | `--mx-button-face-outline-danger-hover-color` | `color.danger.fg` | `#b03659` |
639
648
  | `button.face.ghost-hover.bg` | `--mx-button-face-ghost-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
640
649
  | `button.face.ghost-hover.border-color` | `--mx-button-face-ghost-hover-border-color` | `` | `rgb(0 0 0 / 0)` |
641
650
  | `button.face.ghost-hover.color` | `--mx-button-face-ghost-hover-color` | `` | `initial` |
642
651
  | `button.face.ghost-accent-hover.color` | `--mx-button-face-ghost-accent-hover-color` | `color.accent.fg` | `#983318` |
643
- | `button.face.ghost-danger-hover.color` | `--mx-button-face-ghost-danger-hover-color` | `color.danger.fg` | `#b3261a` |
652
+ | `button.face.ghost-danger-hover.color` | `--mx-button-face-ghost-danger-hover-color` | `color.danger.fg` | `#b03659` |
644
653
  | `button.face.toggled-hover.bg` | `--mx-button-face-toggled-hover-bg` | `color.fill.control.secondary` | `#ebeae5` |
645
654
  | `button.face.accent-toggled-hover.bg` | `--mx-button-face-accent-toggled-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
646
- | `button.face.danger-toggled-hover.bg` | `--mx-button-face-danger-toggled-hover-bg` | `color.danger.solid-hover` | `#c42b1c` |
655
+ | `button.face.danger-toggled-hover.bg` | `--mx-button-face-danger-toggled-hover-bg` | `color.danger.solid-hover` | `#c13b61` |
647
656
  | `button.face.outline-toggled-hover.bg` | `--mx-button-face-outline-toggled-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
648
657
  | `button.face.outline-toggled-hover.color` | `--mx-button-face-outline-toggled-hover-color` | `` | `initial` |
649
658
  | `button.face.outline-accent-toggled-hover.color` | `--mx-button-face-outline-accent-toggled-hover-color` | `color.accent.fg` | `#983318` |
650
- | `button.face.outline-danger-toggled-hover.color` | `--mx-button-face-outline-danger-toggled-hover-color` | `color.danger.fg` | `#b3261a` |
659
+ | `button.face.outline-danger-toggled-hover.color` | `--mx-button-face-outline-danger-toggled-hover-color` | `color.danger.fg` | `#b03659` |
651
660
  | `button.face.ghost-toggled-hover.bg` | `--mx-button-face-ghost-toggled-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
652
661
  | `button.face.ghost-toggled-hover.color` | `--mx-button-face-ghost-toggled-hover-color` | `` | `initial` |
653
662
  | `button.face.ghost-accent-toggled-hover.color` | `--mx-button-face-ghost-accent-toggled-hover-color` | `color.accent.fg` | `#983318` |
654
- | `button.face.ghost-danger-toggled-hover.color` | `--mx-button-face-ghost-danger-toggled-hover-color` | `color.danger.fg` | `#b3261a` |
663
+ | `button.face.ghost-danger-toggled-hover.color` | `--mx-button-face-ghost-danger-toggled-hover-color` | `color.danger.fg` | `#b03659` |
655
664
  | `button.face.pressed.bg` | `--mx-button-face-pressed-bg` | `color.fill.control.tertiary` | `#e1e0da` |
656
665
  | `button.face.pressed.border-bottom-color` | `--mx-button-face-pressed-border-bottom-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
657
666
  | `button.face.pressed.shadow` | `--mx-button-face-pressed-shadow` | `` | `0 0 #0000` |
@@ -660,19 +669,19 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
660
669
  | `button.face.accent-pressed.bg` | `--mx-button-face-accent-pressed-bg` | `color.accent.solid-pressed` | `#a1381c` |
661
670
  | `button.face.accent-pressed.border-bottom-color` | `--mx-button-face-accent-pressed-border-bottom-color` | `color.accent.solid` | `#c24523` |
662
671
  | `button.face.accent-pressed.color` | `--mx-button-face-accent-pressed-color` | `color.accent.on-solid` | `#ffffff` |
663
- | `button.face.danger-pressed.bg` | `--mx-button-face-danger-pressed-bg` | `color.danger.solid-hover` | `#c42b1c` |
664
- | `button.face.danger-pressed.border-bottom-color` | `--mx-button-face-danger-pressed-border-bottom-color` | `color.danger.solid` | `#b3261a` |
672
+ | `button.face.danger-pressed.bg` | `--mx-button-face-danger-pressed-bg` | `color.danger.solid-hover` | `#c13b61` |
673
+ | `button.face.danger-pressed.border-bottom-color` | `--mx-button-face-danger-pressed-border-bottom-color` | `color.danger.solid` | `#b03659` |
665
674
  | `button.face.danger-pressed.color` | `--mx-button-face-danger-pressed-color` | `color.danger.on-solid` | `#ffffff` |
666
675
  | `button.face.outline-pressed.bg` | `--mx-button-face-outline-pressed-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
667
676
  | `button.face.outline-pressed.border-color` | `--mx-button-face-outline-pressed-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
668
677
  | `button.face.outline-pressed.color` | `--mx-button-face-outline-pressed-color` | `` | `initial` |
669
678
  | `button.face.outline-accent-pressed.color` | `--mx-button-face-outline-accent-pressed-color` | `color.accent.fg` | `#983318` |
670
- | `button.face.outline-danger-pressed.color` | `--mx-button-face-outline-danger-pressed-color` | `color.danger.fg` | `#b3261a` |
679
+ | `button.face.outline-danger-pressed.color` | `--mx-button-face-outline-danger-pressed-color` | `color.danger.fg` | `#b03659` |
671
680
  | `button.face.ghost-pressed.bg` | `--mx-button-face-ghost-pressed-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
672
681
  | `button.face.ghost-pressed.border-color` | `--mx-button-face-ghost-pressed-border-color` | `` | `rgb(0 0 0 / 0)` |
673
682
  | `button.face.ghost-pressed.color` | `--mx-button-face-ghost-pressed-color` | `` | `initial` |
674
683
  | `button.face.ghost-accent-pressed.color` | `--mx-button-face-ghost-accent-pressed-color` | `color.accent.fg` | `#983318` |
675
- | `button.face.ghost-danger-pressed.color` | `--mx-button-face-ghost-danger-pressed-color` | `color.danger.fg` | `#b3261a` |
684
+ | `button.face.ghost-danger-pressed.color` | `--mx-button-face-ghost-danger-pressed-color` | `color.danger.fg` | `#b03659` |
676
685
  | `button.face.focus.glow` | `--mx-button-face-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
677
686
  | `button.face.focus.outline-width` | `--mx-button-face-focus-outline-width` | `focus.ring.width` | `2px` |
678
687
  | `button.face.focus.outline-color` | `--mx-button-face-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
@@ -687,19 +696,19 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
687
696
  | `button.face.accent-toggled.bg` | `--mx-button-face-accent-toggled-bg` | `color.accent.solid-pressed` | `#a1381c` |
688
697
  | `button.face.accent-toggled.border-bottom-color` | `--mx-button-face-accent-toggled-border-bottom-color` | `color.accent.solid` | `#c24523` |
689
698
  | `button.face.accent-toggled.color` | `--mx-button-face-accent-toggled-color` | `color.accent.on-solid` | `#ffffff` |
690
- | `button.face.danger-toggled.bg` | `--mx-button-face-danger-toggled-bg` | `color.danger.solid-hover` | `#c42b1c` |
691
- | `button.face.danger-toggled.border-bottom-color` | `--mx-button-face-danger-toggled-border-bottom-color` | `color.danger.solid` | `#b3261a` |
699
+ | `button.face.danger-toggled.bg` | `--mx-button-face-danger-toggled-bg` | `color.danger.solid-hover` | `#c13b61` |
700
+ | `button.face.danger-toggled.border-bottom-color` | `--mx-button-face-danger-toggled-border-bottom-color` | `color.danger.solid` | `#b03659` |
692
701
  | `button.face.danger-toggled.color` | `--mx-button-face-danger-toggled-color` | `color.danger.on-solid` | `#ffffff` |
693
702
  | `button.face.outline-toggled.bg` | `--mx-button-face-outline-toggled-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
694
703
  | `button.face.outline-toggled.border-color` | `--mx-button-face-outline-toggled-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
695
704
  | `button.face.outline-toggled.color` | `--mx-button-face-outline-toggled-color` | `` | `initial` |
696
705
  | `button.face.outline-accent-toggled.color` | `--mx-button-face-outline-accent-toggled-color` | `color.accent.fg` | `#983318` |
697
- | `button.face.outline-danger-toggled.color` | `--mx-button-face-outline-danger-toggled-color` | `color.danger.fg` | `#b3261a` |
706
+ | `button.face.outline-danger-toggled.color` | `--mx-button-face-outline-danger-toggled-color` | `color.danger.fg` | `#b03659` |
698
707
  | `button.face.ghost-toggled.bg` | `--mx-button-face-ghost-toggled-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
699
708
  | `button.face.ghost-toggled.border-color` | `--mx-button-face-ghost-toggled-border-color` | `` | `rgb(0 0 0 / 0)` |
700
709
  | `button.face.ghost-toggled.color` | `--mx-button-face-ghost-toggled-color` | `` | `initial` |
701
710
  | `button.face.ghost-accent-toggled.color` | `--mx-button-face-ghost-accent-toggled-color` | `color.accent.fg` | `#983318` |
702
- | `button.face.ghost-danger-toggled.color` | `--mx-button-face-ghost-danger-toggled-color` | `color.danger.fg` | `#b3261a` |
711
+ | `button.face.ghost-danger-toggled.color` | `--mx-button-face-ghost-danger-toggled-color` | `color.danger.fg` | `#b03659` |
703
712
  | `button.face.disabled.bg` | `--mx-button-face-disabled-bg` | `color.fill.control.disabled` | `#ebeae5` |
704
713
  | `button.face.disabled.border-color` | `--mx-button-face-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
705
714
  | `button.face.disabled.border-bottom-color` | `--mx-button-face-disabled-border-bottom-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
@@ -738,10 +747,10 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
738
747
  | `button.spinner.danger.color` | `--mx-button-spinner-danger-color` | `color.danger.on-solid` | `#ffffff` |
739
748
  | `button.spinner.outline.color` | `--mx-button-spinner-outline-color` | `color.fg.primary` | `#1d1c1a` |
740
749
  | `button.spinner.outline-accent.color` | `--mx-button-spinner-outline-accent-color` | `color.accent.fg` | `#983318` |
741
- | `button.spinner.outline-danger.color` | `--mx-button-spinner-outline-danger-color` | `color.danger.fg` | `#b3261a` |
750
+ | `button.spinner.outline-danger.color` | `--mx-button-spinner-outline-danger-color` | `color.danger.fg` | `#b03659` |
742
751
  | `button.spinner.ghost.color` | `--mx-button-spinner-ghost-color` | `color.fg.primary` | `#1d1c1a` |
743
752
  | `button.spinner.ghost-accent.color` | `--mx-button-spinner-ghost-accent-color` | `color.accent.fg` | `#983318` |
744
- | `button.spinner.ghost-danger.color` | `--mx-button-spinner-ghost-danger-color` | `color.danger.fg` | `#b3261a` |
753
+ | `button.spinner.ghost-danger.color` | `--mx-button-spinner-ghost-danger-color` | `color.danger.fg` | `#b03659` |
745
754
  | `button.divider.width` | `--mx-button-divider-width` | `border.width.1` | `1px` |
746
755
  | `button.divider.bg` | `--mx-button-divider-bg` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
747
756
  | `button.divider.accent.bg` | `--mx-button-divider-accent-bg` | `color.stroke.on-accent-bottom` | `rgb(0 0 0 / 0.4)` |
@@ -797,6 +806,15 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
797
806
  | `calendar.cell.selected.color` | `--mx-calendar-cell-selected-color` | `color.accent.on-solid` | `#ffffff` |
798
807
  | `calendar.cell.selected.shadow` | `--mx-calendar-cell-selected-shadow` | `` | `initial` |
799
808
  | `calendar.cell.selected-hover.bg` | `--mx-calendar-cell-selected-hover-bg` | `color.accent.solid` | `#c24523` |
809
+ | `calendar.cell.range-start.bg` | `--mx-calendar-cell-range-start-bg` | `color.accent.solid` | `#c24523` |
810
+ | `calendar.cell.range-start.color` | `--mx-calendar-cell-range-start-color` | `color.accent.on-solid` | `#ffffff` |
811
+ | `calendar.cell.range-end.bg` | `--mx-calendar-cell-range-end-bg` | `color.accent.solid` | `#c24523` |
812
+ | `calendar.cell.range-end.color` | `--mx-calendar-cell-range-end-color` | `color.accent.on-solid` | `#ffffff` |
813
+ | `calendar.cell.range-single.bg` | `--mx-calendar-cell-range-single-bg` | `color.accent.solid` | `#c24523` |
814
+ | `calendar.cell.range-single.color` | `--mx-calendar-cell-range-single-color` | `color.accent.on-solid` | `#ffffff` |
815
+ | `calendar.cell.range-in.bg` | `--mx-calendar-cell-range-in-bg` | `color.accent.subtle` | `#fbe6de` |
816
+ | `calendar.cell.range-in.color` | `--mx-calendar-cell-range-in-color` | `color.accent.on-subtle` | `#983318` |
817
+ | `calendar.cell.range-in.radius` | `--mx-calendar-cell-range-in-radius` | `radius.none` | `0px` |
800
818
  | `calendar.cell.disabled.color` | `--mx-calendar-cell-disabled-color` | `color.fg.disabled` | `#a2a098` |
801
819
  | `calendar.today.padding-block` | `--mx-calendar-today-padding-block` | `space.1` | `0.25rem` |
802
820
  | `calendar.today.padding-inline` | `--mx-calendar-today-padding-inline` | `space.3` | `0.75rem` |
@@ -906,15 +924,15 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
906
924
  | `checkbox.box.mixed.bg` | `--mx-checkbox-box-mixed-bg` | `color.accent.solid` | `#c24523` |
907
925
  | `checkbox.box.mixed.border-color` | `--mx-checkbox-box-mixed-border-color` | `color.accent.solid` | `#c24523` |
908
926
  | `checkbox.box.mixed.shadow` | `--mx-checkbox-box-mixed-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 rgb(0 0 0 / 0.4)` |
909
- | `checkbox.box.invalid.border-color` | `--mx-checkbox-box-invalid-border-color` | `color.danger.solid` | `#b3261a` |
910
- | `checkbox.box.invalid.shadow` | `--mx-checkbox-box-invalid-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b3261a` |
927
+ | `checkbox.box.invalid.border-color` | `--mx-checkbox-box-invalid-border-color` | `color.danger.solid` | `#b03659` |
928
+ | `checkbox.box.invalid.shadow` | `--mx-checkbox-box-invalid-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b03659` |
911
929
  | `checkbox.box.hover.bg` | `--mx-checkbox-box-hover-bg` | `color.fill.control.secondary` | `#ebeae5` |
912
930
  | `checkbox.box.hover.border-color` | `--mx-checkbox-box-hover-border-color` | `` | `initial` |
913
931
  | `checkbox.box.checked-hover.bg` | `--mx-checkbox-box-checked-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
914
932
  | `checkbox.box.checked-hover.border-color` | `--mx-checkbox-box-checked-hover-border-color` | `` | `initial` |
915
933
  | `checkbox.box.mixed-hover.bg` | `--mx-checkbox-box-mixed-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
916
934
  | `checkbox.box.mixed-hover.border-color` | `--mx-checkbox-box-mixed-hover-border-color` | `` | `initial` |
917
- | `checkbox.box.invalid-hover.border-color` | `--mx-checkbox-box-invalid-hover-border-color` | `color.danger.solid` | `#b3261a` |
935
+ | `checkbox.box.invalid-hover.border-color` | `--mx-checkbox-box-invalid-hover-border-color` | `color.danger.solid` | `#b03659` |
918
936
  | `checkbox.box.pressed.bg` | `--mx-checkbox-box-pressed-bg` | `color.fill.control.tertiary` | `#e1e0da` |
919
937
  | `checkbox.box.pressed.border-color` | `--mx-checkbox-box-pressed-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
920
938
  | `checkbox.box.pressed.shadow` | `--mx-checkbox-box-pressed-shadow` | `` | `0 0 #0000` |
@@ -924,7 +942,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
924
942
  | `checkbox.box.mixed-pressed.bg` | `--mx-checkbox-box-mixed-pressed-bg` | `color.accent.solid-pressed` | `#a1381c` |
925
943
  | `checkbox.box.mixed-pressed.border-color` | `--mx-checkbox-box-mixed-pressed-border-color` | `color.accent.solid` | `#c24523` |
926
944
  | `checkbox.box.mixed-pressed.shadow` | `--mx-checkbox-box-mixed-pressed-shadow` | `` | `0 0 #0000` |
927
- | `checkbox.box.invalid-pressed.border-color` | `--mx-checkbox-box-invalid-pressed-border-color` | `color.danger.solid` | `#b3261a` |
945
+ | `checkbox.box.invalid-pressed.border-color` | `--mx-checkbox-box-invalid-pressed-border-color` | `color.danger.solid` | `#b03659` |
928
946
  | `checkbox.box.focus.outline-width` | `--mx-checkbox-box-focus-outline-width` | `focus.ring.width` | `2px` |
929
947
  | `checkbox.box.focus.outline-color` | `--mx-checkbox-box-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
930
948
  | `checkbox.box.focus.outline-offset` | `--mx-checkbox-box-focus-outline-offset` | `focus.ring.offset` | `1px` |
@@ -939,7 +957,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
939
957
  | `checkbox.box.mixed-pressed-focus.glow` | `--mx-checkbox-box-mixed-pressed-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
940
958
  | `checkbox.box.mixed-pressed-focus.shadow` | `--mx-checkbox-box-mixed-pressed-focus-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 rgb(0 0 0 / 0.4)` |
941
959
  | `checkbox.box.invalid-pressed-focus.glow` | `--mx-checkbox-box-invalid-pressed-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
942
- | `checkbox.box.invalid-pressed-focus.shadow` | `--mx-checkbox-box-invalid-pressed-focus-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b3261a` |
960
+ | `checkbox.box.invalid-pressed-focus.shadow` | `--mx-checkbox-box-invalid-pressed-focus-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b03659` |
943
961
  | `checkbox.box.disabled.bg` | `--mx-checkbox-box-disabled-bg` | `color.fill.control.disabled` | `#ebeae5` |
944
962
  | `checkbox.box.disabled.border-color` | `--mx-checkbox-box-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
945
963
  | `checkbox.box.disabled.shadow` | `--mx-checkbox-box-disabled-shadow` | `` | `0 0 #0000` |
@@ -990,17 +1008,17 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
990
1008
  | `chip.chip.outline-accent.color` | `--mx-chip-chip-outline-accent-color` | `color.accent.fg` | `#983318` |
991
1009
  | `chip.chip.outline-accent.border-color` | `--mx-chip-chip-outline-accent-border-color` | `color.accent.fg` | `#983318` |
992
1010
  | `chip.chip.success.bg` | `--mx-chip-chip-success-bg` | `color.success.subtle` | `#dff6dd` |
993
- | `chip.chip.success.color` | `--mx-chip-chip-success-color` | `color.success.fg` | `#0c6a0c` |
994
- | `chip.chip.outline-success.color` | `--mx-chip-chip-outline-success-color` | `color.success.fg` | `#0c6a0c` |
995
- | `chip.chip.outline-success.border-color` | `--mx-chip-chip-outline-success-border-color` | `color.success.fg` | `#0c6a0c` |
1011
+ | `chip.chip.success.color` | `--mx-chip-chip-success-color` | `color.success.fg` | `#006402` |
1012
+ | `chip.chip.outline-success.color` | `--mx-chip-chip-outline-success-color` | `color.success.fg` | `#006402` |
1013
+ | `chip.chip.outline-success.border-color` | `--mx-chip-chip-outline-success-border-color` | `color.success.fg` | `#006402` |
996
1014
  | `chip.chip.caution.bg` | `--mx-chip-chip-caution-bg` | `color.caution.subtle` | `#fff4ce` |
997
- | `chip.chip.caution.color` | `--mx-chip-chip-caution-color` | `color.caution.fg` | `#845000` |
998
- | `chip.chip.outline-caution.color` | `--mx-chip-chip-outline-caution-color` | `color.caution.fg` | `#845000` |
999
- | `chip.chip.outline-caution.border-color` | `--mx-chip-chip-outline-caution-border-color` | `color.caution.fg` | `#845000` |
1015
+ | `chip.chip.caution.color` | `--mx-chip-chip-caution-color` | `color.caution.fg` | `#754702` |
1016
+ | `chip.chip.outline-caution.color` | `--mx-chip-chip-outline-caution-color` | `color.caution.fg` | `#754702` |
1017
+ | `chip.chip.outline-caution.border-color` | `--mx-chip-chip-outline-caution-border-color` | `color.caution.fg` | `#754702` |
1000
1018
  | `chip.chip.danger.bg` | `--mx-chip-chip-danger-bg` | `color.danger.subtle` | `#fde7e9` |
1001
- | `chip.chip.danger.color` | `--mx-chip-chip-danger-color` | `color.danger.fg` | `#b3261a` |
1002
- | `chip.chip.outline-danger.color` | `--mx-chip-chip-outline-danger-color` | `color.danger.fg` | `#b3261a` |
1003
- | `chip.chip.outline-danger.border-color` | `--mx-chip-chip-outline-danger-border-color` | `color.danger.fg` | `#b3261a` |
1019
+ | `chip.chip.danger.color` | `--mx-chip-chip-danger-color` | `color.danger.fg` | `#b03659` |
1020
+ | `chip.chip.outline-danger.color` | `--mx-chip-chip-outline-danger-color` | `color.danger.fg` | `#b03659` |
1021
+ | `chip.chip.outline-danger.border-color` | `--mx-chip-chip-outline-danger-border-color` | `color.danger.fg` | `#b03659` |
1004
1022
  | `chip.chip.selected.bg` | `--mx-chip-chip-selected-bg` | `color.accent.subtle` | `#fbe6de` |
1005
1023
  | `chip.chip.selected.color` | `--mx-chip-chip-selected-color` | `color.accent.on-subtle` | `#983318` |
1006
1024
  | `chip.chip.selected.border-color` | `--mx-chip-chip-selected-border-color` | `` | `rgb(0 0 0 / 0)` |
@@ -1115,7 +1133,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1115
1133
  | `datagrid.range-anchor-fill` | `--mx-datagrid-range-anchor-fill` | `color.bg.surface` | `#f8f7f3` |
1116
1134
  | `datagrid.row-run-border-color` | `--mx-datagrid-row-run-border-color` | `color.accent.solid` | `#c24523` |
1117
1135
  | `datagrid.row-run-border-width` | `--mx-datagrid-row-run-border-width` | `border.width.2` | `2px` |
1118
- | `datagrid.search-mark-line` | `--mx-datagrid-search-mark-line` | `color.caution.fg` | `#845000` |
1136
+ | `datagrid.search-mark-line` | `--mx-datagrid-search-mark-line` | `color.caution.fg` | `#754702` |
1119
1137
  | `datagrid.search-mark-thickness` | `--mx-datagrid-search-mark-thickness` | `border.width.2` | `2px` |
1120
1138
  | `datagrid.search-mark-offset` | `--mx-datagrid-search-mark-offset` | `border.width.2` | `2px` |
1121
1139
  | `datagrid.filter-text-underline-width` | `--mx-datagrid-filter-text-underline-width` | `border.width.1` | `1px` |
@@ -1281,7 +1299,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1281
1299
  | `datagrid.changed.border-top-color` | `--mx-datagrid-changed-border-top-color` | `color.accent.solid` | `#c24523` |
1282
1300
  | `datagrid.changed.border-color` | `--mx-datagrid-changed-border-color` | `` | `rgb(0 0 0 / 0)` |
1283
1301
  | `datagrid.invalid.border-width` | `--mx-datagrid-invalid-border-width` | `border.width.2` | `2px` |
1284
- | `datagrid.invalid.border-color` | `--mx-datagrid-invalid-border-color` | `color.danger.solid` | `#b3261a` |
1302
+ | `datagrid.invalid.border-color` | `--mx-datagrid-invalid-border-color` | `color.danger.solid` | `#b03659` |
1285
1303
  | `datagrid.placeholder.bg` | `--mx-datagrid-placeholder-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
1286
1304
  | `datagrid.placeholder.radius` | `--mx-datagrid-placeholder-radius` | `radius.sm` | `0.25rem` |
1287
1305
  | `datagrid.header-cell.padding-inline` | `--mx-datagrid-header-cell-padding-inline` | `control.padding.sm` | `0.5rem` |
@@ -1371,11 +1389,11 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1371
1389
  | `datagrid.ghost-rows.bg` | `--mx-datagrid-ghost-rows-bg` | `color.bg.surface` | `#f8f7f3` |
1372
1390
  | `datagrid.status-mark.font-size` | `--mx-datagrid-status-mark-font-size` | `font.size.caption` | `0.75rem` |
1373
1391
  | `datagrid.status-mark.font-weight` | `--mx-datagrid-status-mark-font-weight` | `font.weight.bold` | `700` |
1374
- | `datagrid.status-symbol.new.color` | `--mx-datagrid-status-symbol-new-color` | `color.success.fg` | `#0c6a0c` |
1392
+ | `datagrid.status-symbol.new.color` | `--mx-datagrid-status-symbol-new-color` | `color.success.fg` | `#006402` |
1375
1393
  | `datagrid.status-symbol.changed.color` | `--mx-datagrid-status-symbol-changed-color` | `color.accent.fg` | `#983318` |
1376
1394
  | `datagrid.status-symbol.removed.color` | `--mx-datagrid-status-symbol-removed-color` | `color.fg.secondary` | `#5e5c55` |
1377
1395
  | `datagrid.status-symbol.saving.color` | `--mx-datagrid-status-symbol-saving-color` | `color.accent.fg` | `#983318` |
1378
- | `datagrid.status-symbol.failed.color` | `--mx-datagrid-status-symbol-failed-color` | `color.danger.fg` | `#b3261a` |
1396
+ | `datagrid.status-symbol.failed.color` | `--mx-datagrid-status-symbol-failed-color` | `color.danger.fg` | `#b03659` |
1379
1397
  | `datagrid.check.size` | `--mx-datagrid-check-size` | `` | `0.875rem` |
1380
1398
  | `datagrid.check.bg` | `--mx-datagrid-check-bg` | `color.fill.control.default` | `#f5f4f0` |
1381
1399
  | `datagrid.check.border-width` | `--mx-datagrid-check-border-width` | `border.width.1` | `1px` |
@@ -1426,7 +1444,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1426
1444
  | `datagrid.form.padding` | `--mx-datagrid-form-padding` | `space.3` | `0.75rem` |
1427
1445
  | `datagrid.form.gap` | `--mx-datagrid-form-gap` | `space.3` | `0.75rem` |
1428
1446
  | `datagrid.form.popup.padding` | `--mx-datagrid-form-popup-padding` | `` | `0px` |
1429
- | `datagrid.form-message.color` | `--mx-datagrid-form-message-color` | `color.danger.fg` | `#b3261a` |
1447
+ | `datagrid.form-message.color` | `--mx-datagrid-form-message-color` | `color.danger.fg` | `#b03659` |
1430
1448
  | `datagrid.form-buttons.gap` | `--mx-datagrid-form-buttons-gap` | `space.3` | `0.75rem` |
1431
1449
  | `datagrid.form-label.color` | `--mx-datagrid-form-label-color` | `color.fg.secondary` | `#5e5c55` |
1432
1450
  | `datagrid.form-label.font-size` | `--mx-datagrid-form-label-font-size` | `font.size.caption` | `0.75rem` |
@@ -1440,9 +1458,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1440
1458
  | `datagrid.state.padding-inline` | `--mx-datagrid-state-padding-inline` | `space.3` | `0.75rem` |
1441
1459
  | `datagrid.state.gap` | `--mx-datagrid-state-gap` | `space.2` | `0.5rem` |
1442
1460
  | `datagrid.state.color` | `--mx-datagrid-state-color` | `color.fg.secondary` | `#5e5c55` |
1443
- | `datagrid.state.danger.color` | `--mx-datagrid-state-danger-color` | `color.danger.fg` | `#b3261a` |
1461
+ | `datagrid.state.danger.color` | `--mx-datagrid-state-danger-color` | `color.danger.fg` | `#b03659` |
1444
1462
  | `datagrid.note.gap` | `--mx-datagrid-note-gap` | `space.2` | `0.5rem` |
1445
- | `datagrid.note.danger.color` | `--mx-datagrid-note-danger-color` | `color.danger.fg` | `#b3261a` |
1463
+ | `datagrid.note.danger.color` | `--mx-datagrid-note-danger-color` | `color.danger.fg` | `#b03659` |
1446
1464
  | `datagrid.load-more.margin-bottom` | `--mx-datagrid-load-more-margin-bottom` | `space.2` | `0.5rem` |
1447
1465
  | `datagrid.load-more.padding-block` | `--mx-datagrid-load-more-padding-block` | `space.1` | `0.25rem` |
1448
1466
  | `datagrid.load-more.padding-inline` | `--mx-datagrid-load-more-padding-inline` | `space.3` | `0.75rem` |
@@ -1453,7 +1471,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1453
1471
  | `datagrid.load-more.radius` | `--mx-datagrid-load-more-radius` | `radius.sm` | `0.25rem` |
1454
1472
  | `datagrid.load-more.shadow` | `--mx-datagrid-load-more-shadow` | `elevation.popup` | `0px 8px 16px 0px rgb(0 0 0 / 0.14), 0px 0px 2px 0px rgb(0 0 0 / 0.12)` |
1455
1473
  | `datagrid.load-more.color` | `--mx-datagrid-load-more-color` | `color.fg.secondary` | `#5e5c55` |
1456
- | `datagrid.load-more.failed.color` | `--mx-datagrid-load-more-failed-color` | `color.danger.fg` | `#b3261a` |
1474
+ | `datagrid.load-more.failed.color` | `--mx-datagrid-load-more-failed-color` | `color.danger.fg` | `#b03659` |
1457
1475
  | `datagrid.export-panel.padding` | `--mx-datagrid-export-panel-padding` | `space.3` | `0.75rem` |
1458
1476
  | `datagrid.export-panel.gap` | `--mx-datagrid-export-panel-gap` | `space.3` | `0.75rem` |
1459
1477
  | `datagrid.export-panel.bg` | `--mx-datagrid-export-panel-bg` | `color.bg.surface` | `#f8f7f3` |
@@ -1496,8 +1514,8 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1496
1514
  | `datagrid.page-sizes.margin-end` | `--mx-datagrid-page-sizes-margin-end` | `space.2` | `0.5rem` |
1497
1515
  | `datagrid.page-gap.padding-inline` | `--mx-datagrid-page-gap-padding-inline` | `space.1` | `0.25rem` |
1498
1516
  | `datagrid.page-info.margin-end` | `--mx-datagrid-page-info-margin-end` | `space.2` | `0.5rem` |
1499
- | `datagrid.tip.error.border-color` | `--mx-datagrid-tip-error-border-color` | `color.danger.solid` | `#b3261a` |
1500
- | `datagrid.tip.error.color` | `--mx-datagrid-tip-error-color` | `color.danger.fg` | `#b3261a` |
1517
+ | `datagrid.tip.error.border-color` | `--mx-datagrid-tip-error-border-color` | `color.danger.solid` | `#b03659` |
1518
+ | `datagrid.tip.error.color` | `--mx-datagrid-tip-error-color` | `color.danger.fg` | `#b03659` |
1501
1519
  | `date-box.popup-gap` | `--mx-date-box-popup-gap` | `space.1` | `0.25rem` |
1502
1520
  | `date-box.calendar.container.padding` | `--mx-date-box-calendar-container-padding` | `space.2` | `0.5rem` |
1503
1521
  | `date-box.times.min-width` | `--mx-date-box-times-min-width` | `` | `6rem` |
@@ -1509,6 +1527,22 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1509
1527
  | `date-box.times.beside.padding-start` | `--mx-date-box-times-beside-padding-start` | `space.1` | `0.25rem` |
1510
1528
  | `date-box.times.beside.border-start-width` | `--mx-date-box-times-beside-border-start-width` | `border.width.1` | `1px` |
1511
1529
  | `date-box.times.beside.border-start-color` | `--mx-date-box-times-beside-border-start-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
1530
+ | `date-range-box.popup-gap` | `--mx-date-range-box-popup-gap` | `space.1` | `0.25rem` |
1531
+ | `date-range-box.field.width` | `--mx-date-range-box-field-width` | `` | `20rem` |
1532
+ | `date-range-box.calendar.container.padding` | `--mx-date-range-box-calendar-container-padding` | `space.2` | `0.5rem` |
1533
+ | `date-range-box.separator.icon` | `--mx-date-range-box-separator-icon` | `` | `var(--mx-icon-dash)` |
1534
+ | `date-range-box.separator.bg` | `--mx-date-range-box-separator-bg` | `color.fg.tertiary` | `#8c8a82` |
1535
+ | `date-range-box.separator.size` | `--mx-date-range-box-separator-size` | `` | `1rem` |
1536
+ | `date-range-box.separator.margin-inline` | `--mx-date-range-box-separator-margin-inline` | `space.1` | `0.25rem` |
1537
+ | `date-range-box.presets.min-width` | `--mx-date-range-box-presets-min-width` | `` | `9rem` |
1538
+ | `date-range-box.presets.max-height` | `--mx-date-range-box-presets-max-height` | `` | `18rem` |
1539
+ | `date-range-box.presets.focus.outline-width` | `--mx-date-range-box-presets-focus-outline-width` | `focus.ring.width` | `2px` |
1540
+ | `date-range-box.presets.focus.outline-color` | `--mx-date-range-box-presets-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
1541
+ | `date-range-box.presets.focus.outline-offset` | `--mx-date-range-box-presets-focus-outline-offset` | `` | `calc(-1 * 2px)` |
1542
+ | `date-range-box.presets.focus.glow` | `--mx-date-range-box-presets-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
1543
+ | `date-range-box.presets.beside.padding-start` | `--mx-date-range-box-presets-beside-padding-start` | `space.1` | `0.25rem` |
1544
+ | `date-range-box.presets.beside.border-start-width` | `--mx-date-range-box-presets-beside-border-start-width` | `border.width.1` | `1px` |
1545
+ | `date-range-box.presets.beside.border-start-color` | `--mx-date-range-box-presets-beside-border-start-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
1512
1546
  | `disabled.element.color` | `--mx-disabled-element-color` | `color.fg.disabled` | `#a2a098` |
1513
1547
  | `drawer.font-family` | `--mx-drawer-font-family` | `font.family.sans` | `Archivo, system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif` |
1514
1548
  | `drawer.size` | `--mx-drawer-size` | `` | `20rem` |
@@ -1586,11 +1620,19 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1586
1620
  | `drop-down.search.variant` | `--mx-drop-down-search-variant` | `` | `outline` |
1587
1621
  | `drop-down.search.size` | `--mx-drop-down-search-size` | `` | `sm` |
1588
1622
  | `drop-down.value.placeholder.color` | `--mx-drop-down-value-placeholder-color` | `color.fg.secondary` | `#5e5c55` |
1623
+ | `drop-down.value.missing.color` | `--mx-drop-down-value-missing-color` | `color.fg.secondary` | `#5e5c55` |
1624
+ | `drop-down.value.missing.text-decoration` | `--mx-drop-down-value-missing-text-decoration` | `` | `underline` |
1589
1625
  | `drop-down.chevron.size` | `--mx-drop-down-chevron-size` | `icon.size.sm` | `0.75rem` |
1590
1626
  | `drop-down.chevron.color` | `--mx-drop-down-chevron-color` | `color.fg.secondary` | `#5e5c55` |
1591
1627
  | `drop-down.chevron.icon` | `--mx-drop-down-chevron-icon` | `` | `var(--mx-icon-chevron-down)` |
1592
1628
  | `drop-down.chevron.open.rotate` | `--mx-drop-down-chevron-open-rotate` | `` | `0.5turn` |
1593
1629
  | `drop-down.chevron.disabled.color` | `--mx-drop-down-chevron-disabled-color` | `color.fg.disabled` | `#a2a098` |
1630
+ | `drop-down.spinner.size` | `--mx-drop-down-spinner-size` | `icon.size.sm` | `0.75rem` |
1631
+ | `drop-down.spinner.border-width` | `--mx-drop-down-spinner-border-width` | `border.width.2` | `2px` |
1632
+ | `drop-down.spinner.border-end-color` | `--mx-drop-down-spinner-border-end-color` | `` | `rgb(0 0 0 / 0)` |
1633
+ | `drop-down.spinner.radius` | `--mx-drop-down-spinner-radius` | `radius.full` | `9999px` |
1634
+ | `drop-down.spinner.color` | `--mx-drop-down-spinner-color` | `color.fg.secondary` | `#5e5c55` |
1635
+ | `drop-down.spinner-shape.display` | `--mx-drop-down-spinner-shape-display` | `` | `initial` |
1594
1636
  | `field.width` | `--mx-field-width` | `` | `16rem` |
1595
1637
  | `field.variant` | `--mx-field-variant` | `` | `outline` |
1596
1638
  | `field.label-mode` | `--mx-field-label-mode` | `` | `top` |
@@ -1669,11 +1711,13 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1669
1711
  | `field.box.underline-readonly-invalid-focus.shadow` | `--mx-field-box-underline-readonly-invalid-focus-shadow` | `` | `initial` |
1670
1712
  | `field.box.pressed.bg` | `--mx-field-box-pressed-bg` | `` | `initial` |
1671
1713
  | `field.box.pressed.color` | `--mx-field-box-pressed-color` | `` | `initial` |
1714
+ | `field.box.border-style` | `--mx-field-box-border-style` | `` | `initial` |
1715
+ | `field.box.border-color` | `--mx-field-box-border-color` | `` | `initial` |
1672
1716
  | `field.frame.border-color` | `--mx-field-frame-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
1673
1717
  | `field.frame.focus.border-bottom-color` | `--mx-field-frame-focus-border-bottom-color` | `color.accent.solid` | `#c24523` |
1674
1718
  | `field.frame.focus.border-color` | `--mx-field-frame-focus-border-color` | `` | `initial` |
1675
1719
  | `field.frame.focus.border-width` | `--mx-field-frame-focus-border-width` | `` | `initial` |
1676
- | `field.frame.invalid.border-color` | `--mx-field-frame-invalid-border-color` | `color.danger.solid` | `#b3261a` |
1720
+ | `field.frame.invalid.border-color` | `--mx-field-frame-invalid-border-color` | `color.danger.solid` | `#b03659` |
1677
1721
  | `field.frame.readonly-focus.border-bottom-color` | `--mx-field-frame-readonly-focus-border-bottom-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
1678
1722
  | `field.frame.readonly-focus.border-width` | `--mx-field-frame-readonly-focus-border-width` | `` | `initial` |
1679
1723
  | `field.frame.filled.border-color` | `--mx-field-frame-filled-border-color` | `` | `rgb(0 0 0 / 0)` |
@@ -1681,7 +1725,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1681
1725
  | `field.frame.filled-focus.border-bottom-color` | `--mx-field-frame-filled-focus-border-bottom-color` | `color.accent.solid` | `#c24523` |
1682
1726
  | `field.frame.filled-focus.border-color` | `--mx-field-frame-filled-focus-border-color` | `` | `initial` |
1683
1727
  | `field.frame.filled-focus.border-width` | `--mx-field-frame-filled-focus-border-width` | `` | `initial` |
1684
- | `field.frame.filled-invalid.border-color` | `--mx-field-frame-filled-invalid-border-color` | `color.danger.solid` | `#b3261a` |
1728
+ | `field.frame.filled-invalid.border-color` | `--mx-field-frame-filled-invalid-border-color` | `color.danger.solid` | `#b03659` |
1685
1729
  | `field.frame.filled-readonly-focus.border-bottom-color` | `--mx-field-frame-filled-readonly-focus-border-bottom-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
1686
1730
  | `field.frame.filled-readonly-focus.border-width` | `--mx-field-frame-filled-readonly-focus-border-width` | `` | `initial` |
1687
1731
  | `field.frame.filled-disabled.border-color` | `--mx-field-frame-filled-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
@@ -1689,7 +1733,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1689
1733
  | `field.frame.underline.border-bottom-color` | `--mx-field-frame-underline-border-bottom-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
1690
1734
  | `field.frame.underline-focus.border-bottom-color` | `--mx-field-frame-underline-focus-border-bottom-color` | `color.accent.solid` | `#c24523` |
1691
1735
  | `field.frame.underline-focus.border-width` | `--mx-field-frame-underline-focus-border-width` | `` | `initial` |
1692
- | `field.frame.underline-invalid.border-bottom-color` | `--mx-field-frame-underline-invalid-border-bottom-color` | `color.danger.solid` | `#b3261a` |
1736
+ | `field.frame.underline-invalid.border-bottom-color` | `--mx-field-frame-underline-invalid-border-bottom-color` | `color.danger.solid` | `#b03659` |
1693
1737
  | `field.frame.underline-readonly-focus.border-bottom-color` | `--mx-field-frame-underline-readonly-focus-border-bottom-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
1694
1738
  | `field.frame.underline-readonly-focus.border-width` | `--mx-field-frame-underline-readonly-focus-border-width` | `` | `initial` |
1695
1739
  | `field.frame.underline-disabled.border-color` | `--mx-field-frame-underline-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
@@ -1718,14 +1762,14 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1718
1762
  | `field.frame.display` | `--mx-field-frame-display` | `` | `initial` |
1719
1763
  | `field.indicator.radius` | `--mx-field-indicator-radius` | `` | `calc(0.375rem - 1px)` |
1720
1764
  | `field.indicator.focus.shadow` | `--mx-field-indicator-focus-shadow` | `` | `inset 0 -1px 0 0 #c24523` |
1721
- | `field.indicator.invalid-focus.shadow` | `--mx-field-indicator-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b3261a` |
1765
+ | `field.indicator.invalid-focus.shadow` | `--mx-field-indicator-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b03659` |
1722
1766
  | `field.indicator.readonly-focus.shadow` | `--mx-field-indicator-readonly-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1723
1767
  | `field.indicator.filled-focus.shadow` | `--mx-field-indicator-filled-focus-shadow` | `` | `inset 0 -1px 0 0 #c24523` |
1724
- | `field.indicator.filled-invalid-focus.shadow` | `--mx-field-indicator-filled-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b3261a` |
1768
+ | `field.indicator.filled-invalid-focus.shadow` | `--mx-field-indicator-filled-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b03659` |
1725
1769
  | `field.indicator.filled-readonly-focus.shadow` | `--mx-field-indicator-filled-readonly-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1726
1770
  | `field.indicator.underline.radius` | `--mx-field-indicator-underline-radius` | `` | `0px` |
1727
1771
  | `field.indicator.underline-focus.shadow` | `--mx-field-indicator-underline-focus-shadow` | `` | `inset 0 -1px 0 0 #c24523` |
1728
- | `field.indicator.underline-invalid-focus.shadow` | `--mx-field-indicator-underline-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b3261a` |
1772
+ | `field.indicator.underline-invalid-focus.shadow` | `--mx-field-indicator-underline-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b03659` |
1729
1773
  | `field.indicator.underline-readonly-focus.shadow` | `--mx-field-indicator-underline-readonly-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1730
1774
  | `field.indicator.readonly-invalid-focus.shadow` | `--mx-field-indicator-readonly-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1731
1775
  | `field.indicator.filled-readonly-invalid-focus.shadow` | `--mx-field-indicator-filled-readonly-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
@@ -1741,7 +1785,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1741
1785
  | `field.label.floating-focus.color` | `--mx-field-label-floating-focus-color` | `` | `initial` |
1742
1786
  | `field.label.floating-invalid.color` | `--mx-field-label-floating-invalid-color` | `` | `initial` |
1743
1787
  | `field.required.margin-start` | `--mx-field-required-margin-start` | `space.1` | `0.25rem` |
1744
- | `field.required.color` | `--mx-field-required-color` | `color.danger.fg` | `#b3261a` |
1788
+ | `field.required.color` | `--mx-field-required-color` | `color.danger.fg` | `#b03659` |
1745
1789
  | `field.icon.color` | `--mx-field-icon-color` | `color.fg.secondary` | `#5e5c55` |
1746
1790
  | `field.prefix.color` | `--mx-field-prefix-color` | `color.fg.secondary` | `#5e5c55` |
1747
1791
  | `field.suffix.color` | `--mx-field-suffix-color` | `color.fg.secondary` | `#5e5c55` |
@@ -1766,7 +1810,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1766
1810
  | `field.foot.color` | `--mx-field-foot-color` | `color.fg.secondary` | `#5e5c55` |
1767
1811
  | `field.foot.shown.padding-top` | `--mx-field-foot-shown-padding-top` | `space.1` | `0.25rem` |
1768
1812
  | `field.foot.display` | `--mx-field-foot-display` | `` | `initial` |
1769
- | `field.message.invalid.color` | `--mx-field-message-invalid-color` | `color.danger.fg` | `#b3261a` |
1813
+ | `field.message.invalid.color` | `--mx-field-message-invalid-color` | `color.danger.fg` | `#b03659` |
1770
1814
  | `field.frame-start.focus.border-block-width` | `--mx-field-frame-start-focus-border-block-width` | `` | `initial` |
1771
1815
  | `field.frame-start.focus.border-start-width` | `--mx-field-frame-start-focus-border-start-width` | `` | `initial` |
1772
1816
  | `field.frame-start.invalid-focus.border-block-width` | `--mx-field-frame-start-invalid-focus-border-block-width` | `` | `initial` |
@@ -1787,6 +1831,71 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1787
1831
  | `field.frame-end.readonly-focus.border-end-width` | `--mx-field-frame-end-readonly-focus-border-end-width` | `` | `initial` |
1788
1832
  | `field.frame-end.readonly-invalid-focus.border-block-width` | `--mx-field-frame-end-readonly-invalid-focus-border-block-width` | `` | `initial` |
1789
1833
  | `field.frame-end.readonly-invalid-focus.border-end-width` | `--mx-field-frame-end-readonly-invalid-focus-border-end-width` | `` | `initial` |
1834
+ | `file-uploader.box-gap` | `--mx-file-uploader-box-gap` | `space.3` | `0.75rem` |
1835
+ | `file-uploader.button-gap` | `--mx-file-uploader-button-gap` | `space.2` | `0.5rem` |
1836
+ | `file-uploader.item-gap` | `--mx-file-uploader-item-gap` | `space.2` | `0.5rem` |
1837
+ | `file-uploader.field.width` | `--mx-file-uploader-field-width` | `` | `26rem` |
1838
+ | `file-uploader.field.box.border-style` | `--mx-file-uploader-field-box-border-style` | `` | `dashed` |
1839
+ | `file-uploader.field.box.border-color` | `--mx-file-uploader-field-box-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
1840
+ | `file-uploader.field.box.radius` | `--mx-file-uploader-field-box-radius` | `radius.lg` | `0.625rem` |
1841
+ | `file-uploader.field.box.hover.bg` | `--mx-file-uploader-field-box-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
1842
+ | `file-uploader.field.border-width` | `--mx-file-uploader-field-border-width` | `border.width.1` | `1px` |
1843
+ | `file-uploader.field.padding.sm` | `--mx-file-uploader-field-padding-sm` | `space.2` | `0.5rem` |
1844
+ | `file-uploader.field.padding.md` | `--mx-file-uploader-field-padding-md` | `space.3` | `0.75rem` |
1845
+ | `file-uploader.field.padding.lg` | `--mx-file-uploader-field-padding-lg` | `space.4` | `1rem` |
1846
+ | `file-uploader.action.variant` | `--mx-file-uploader-action-variant` | `` | `ghost` |
1847
+ | `file-uploader.over.bg` | `--mx-file-uploader-over-bg` | `color.accent.subtle` | `#fbe6de` |
1848
+ | `file-uploader.over.border-color` | `--mx-file-uploader-over-border-color` | `color.accent.solid` | `#c24523` |
1849
+ | `file-uploader.select.padding-block` | `--mx-file-uploader-select-padding-block` | `space.1` | `0.25rem` |
1850
+ | `file-uploader.select.padding-inline` | `--mx-file-uploader-select-padding-inline` | `space.3` | `0.75rem` |
1851
+ | `file-uploader.select.radius` | `--mx-file-uploader-select-radius` | `radius.sm` | `0.25rem` |
1852
+ | `file-uploader.select.color` | `--mx-file-uploader-select-color` | `color.fg.primary` | `#1d1c1a` |
1853
+ | `file-uploader.select.font-weight` | `--mx-file-uploader-select-font-weight` | `font.weight.semibold` | `600` |
1854
+ | `file-uploader.select.bg` | `--mx-file-uploader-select-bg` | `color.fill.control.default` | `#f5f4f0` |
1855
+ | `file-uploader.select.border-width` | `--mx-file-uploader-select-border-width` | `border.width.1` | `1px` |
1856
+ | `file-uploader.select.border-color` | `--mx-file-uploader-select-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
1857
+ | `file-uploader.select.hover.bg` | `--mx-file-uploader-select-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
1858
+ | `file-uploader.select.hover.cursor` | `--mx-file-uploader-select-hover-cursor` | `` | `pointer` |
1859
+ | `file-uploader.select.pressed.bg` | `--mx-file-uploader-select-pressed-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
1860
+ | `file-uploader.select.focus.glow` | `--mx-file-uploader-select-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
1861
+ | `file-uploader.select.focus.outline-width` | `--mx-file-uploader-select-focus-outline-width` | `focus.ring.width` | `2px` |
1862
+ | `file-uploader.select.focus.outline-color` | `--mx-file-uploader-select-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
1863
+ | `file-uploader.select.focus.outline-offset` | `--mx-file-uploader-select-focus-outline-offset` | `focus.ring.offset` | `1px` |
1864
+ | `file-uploader.select.disabled.color` | `--mx-file-uploader-select-disabled-color` | `color.fg.disabled` | `#a2a098` |
1865
+ | `file-uploader.select.disabled.border-color` | `--mx-file-uploader-select-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
1866
+ | `file-uploader.upload.padding-block` | `--mx-file-uploader-upload-padding-block` | `space.1` | `0.25rem` |
1867
+ | `file-uploader.upload.padding-inline` | `--mx-file-uploader-upload-padding-inline` | `space.3` | `0.75rem` |
1868
+ | `file-uploader.upload.radius` | `--mx-file-uploader-upload-radius` | `radius.sm` | `0.25rem` |
1869
+ | `file-uploader.upload.color` | `--mx-file-uploader-upload-color` | `color.accent.on-solid` | `#ffffff` |
1870
+ | `file-uploader.upload.font-weight` | `--mx-file-uploader-upload-font-weight` | `font.weight.semibold` | `600` |
1871
+ | `file-uploader.upload.bg` | `--mx-file-uploader-upload-bg` | `color.accent.solid` | `#c24523` |
1872
+ | `file-uploader.upload.border-width` | `--mx-file-uploader-upload-border-width` | `border.width.1` | `1px` |
1873
+ | `file-uploader.upload.border-color` | `--mx-file-uploader-upload-border-color` | `color.accent.solid` | `#c24523` |
1874
+ | `file-uploader.upload.hover.bg` | `--mx-file-uploader-upload-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
1875
+ | `file-uploader.upload.hover.cursor` | `--mx-file-uploader-upload-hover-cursor` | `` | `pointer` |
1876
+ | `file-uploader.upload.pressed.bg` | `--mx-file-uploader-upload-pressed-bg` | `color.accent.solid-hover` | `#b43f20` |
1877
+ | `file-uploader.upload.focus.glow` | `--mx-file-uploader-upload-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
1878
+ | `file-uploader.upload.focus.outline-width` | `--mx-file-uploader-upload-focus-outline-width` | `focus.ring.width` | `2px` |
1879
+ | `file-uploader.upload.focus.outline-color` | `--mx-file-uploader-upload-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
1880
+ | `file-uploader.upload.focus.outline-offset` | `--mx-file-uploader-upload-focus-outline-offset` | `focus.ring.offset` | `1px` |
1881
+ | `file-uploader.hint.color` | `--mx-file-uploader-hint-color` | `color.fg.secondary` | `#5e5c55` |
1882
+ | `file-uploader.list.margin-top` | `--mx-file-uploader-list-margin-top` | `space.2` | `0.5rem` |
1883
+ | `file-uploader.list.gap` | `--mx-file-uploader-list-gap` | `space.1` | `0.25rem` |
1884
+ | `file-uploader.item.padding-block` | `--mx-file-uploader-item-padding-block` | `space.1` | `0.25rem` |
1885
+ | `file-uploader.item.padding-inline` | `--mx-file-uploader-item-padding-inline` | `space.2` | `0.5rem` |
1886
+ | `file-uploader.item.radius` | `--mx-file-uploader-item-radius` | `radius.sm` | `0.25rem` |
1887
+ | `file-uploader.item.error.bg` | `--mx-file-uploader-item-error-bg` | `color.danger.subtle` | `#fde7e9` |
1888
+ | `file-uploader.item.invalid.bg` | `--mx-file-uploader-item-invalid-bg` | `color.danger.subtle` | `#fde7e9` |
1889
+ | `file-uploader.icon.icon` | `--mx-file-uploader-icon-icon` | `` | `var(--mx-icon-file)` |
1890
+ | `file-uploader.icon.bg` | `--mx-file-uploader-icon-bg` | `color.fg.secondary` | `#5e5c55` |
1891
+ | `file-uploader.icon.size` | `--mx-file-uploader-icon-size` | `` | `1.25rem` |
1892
+ | `file-uploader.name.color` | `--mx-file-uploader-name-color` | `color.fg.primary` | `#1d1c1a` |
1893
+ | `file-uploader.size.color` | `--mx-file-uploader-size-color` | `color.fg.secondary` | `#5e5c55` |
1894
+ | `file-uploader.size.font-size` | `--mx-file-uploader-size-font-size` | `font.size.caption` | `0.75rem` |
1895
+ | `file-uploader.state.color` | `--mx-file-uploader-state-color` | `color.fg.secondary` | `#5e5c55` |
1896
+ | `file-uploader.state.font-size` | `--mx-file-uploader-state-font-size` | `font.size.caption` | `0.75rem` |
1897
+ | `file-uploader.state.done.color` | `--mx-file-uploader-state-done-color` | `color.success.fg` | `#006402` |
1898
+ | `file-uploader.state.error.color` | `--mx-file-uploader-state-error-color` | `color.danger.fg` | `#b03659` |
1790
1899
  | `filterbuilder.indent` | `--mx-filterbuilder-indent` | `space.6` | `1.5rem` |
1791
1900
  | `filterbuilder.line-width` | `--mx-filterbuilder-line-width` | `border.width.1` | `1px` |
1792
1901
  | `filterbuilder.line-color` | `--mx-filterbuilder-line-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
@@ -1953,7 +2062,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1953
2062
  | `listbox.field.frame.disabled.border-color` | `--mx-listbox-field-frame-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
1954
2063
  | `listbox.field.indicator.radius` | `--mx-listbox-field-indicator-radius` | `` | `calc(0.375rem - 1px)` |
1955
2064
  | `listbox.field.indicator.focus.shadow` | `--mx-listbox-field-indicator-focus-shadow` | `` | `inset 0 -1px 0 0 #c24523` |
1956
- | `listbox.field.indicator.invalid-focus.shadow` | `--mx-listbox-field-indicator-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b3261a` |
2065
+ | `listbox.field.indicator.invalid-focus.shadow` | `--mx-listbox-field-indicator-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 #b03659` |
1957
2066
  | `listbox.field.indicator.readonly-focus.shadow` | `--mx-listbox-field-indicator-readonly-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1958
2067
  | `listbox.field.indicator.readonly-invalid-focus.shadow` | `--mx-listbox-field-indicator-readonly-invalid-focus-shadow` | `` | `inset 0 -1px 0 0 rgb(0 0 0 / 0.4458)` |
1959
2068
  | `listbox.search.variant` | `--mx-listbox-search-variant` | `` | `outline` |
@@ -1984,6 +2093,20 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
1984
2093
  | `listbox.keys.outline-offset` | `--mx-listbox-keys-outline-offset` | `` | `calc(-1 * 2px)` |
1985
2094
  | `listbox.idle.bg` | `--mx-listbox-idle-bg` | `` | `rgb(0 0 0 / 0)` |
1986
2095
  | `listbox.container.margin` | `--mx-listbox-container-margin` | `` | `initial` |
2096
+ | `load-panel.padding` | `--mx-load-panel-padding` | `space.4` | `1rem` |
2097
+ | `load-panel.gap` | `--mx-load-panel-gap` | `space.3` | `0.75rem` |
2098
+ | `load-panel.cancel.variant` | `--mx-load-panel-cancel-variant` | `` | `outline` |
2099
+ | `load-panel.shade.shaded.bg` | `--mx-load-panel-shade-shaded-bg` | `color.bg.smoke` | `rgb(0 0 0 / 0.3)` |
2100
+ | `load-panel.pane.shown.bg` | `--mx-load-panel-pane-shown-bg` | `color.bg.surface` | `#f8f7f3` |
2101
+ | `load-panel.pane.shown.border-width` | `--mx-load-panel-pane-shown-border-width` | `border.width.1` | `1px` |
2102
+ | `load-panel.pane.shown.border-color` | `--mx-load-panel-pane-shown-border-color` | `color.stroke.surface` | `rgb(117 117 117 / 0.4)` |
2103
+ | `load-panel.pane.shown.radius` | `--mx-load-panel-pane-shown-radius` | `radius.lg` | `0.625rem` |
2104
+ | `load-panel.pane.shown.shadow` | `--mx-load-panel-pane-shown-shadow` | `elevation.popup` | `0px 8px 16px 0px rgb(0 0 0 / 0.14), 0px 0px 2px 0px rgb(0 0 0 / 0.12)` |
2105
+ | `load-panel.pane.shown.padding-block` | `--mx-load-panel-pane-shown-padding-block` | `space.4` | `1rem` |
2106
+ | `load-panel.pane.shown.padding-inline` | `--mx-load-panel-pane-shown-padding-inline` | `space.5` | `1.25rem` |
2107
+ | `load-panel.pane.shown.min-width` | `--mx-load-panel-pane-shown-min-width` | `` | `10rem` |
2108
+ | `load-panel.message.color` | `--mx-load-panel-message-color` | `color.fg.primary` | `#1d1c1a` |
2109
+ | `load-panel.message.font-size` | `--mx-load-panel-message-font-size` | `font.size.body` | `0.875rem` |
1987
2110
  | `lookup.popup-width` | `--mx-lookup-popup-width` | `` | `28rem` |
1988
2111
  | `lookup.column-gap` | `--mx-lookup-column-gap` | `space.3` | `0.75rem` |
1989
2112
  | `lookup.header.padding-block` | `--mx-lookup-header-padding-block` | `space.1` | `0.25rem` |
@@ -2010,9 +2133,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2010
2133
  | `menu.item.focus.outline-offset` | `--mx-menu-item-focus-outline-offset` | `focus.ring.offset` | `1px` |
2011
2134
  | `menu.item.disabled.color` | `--mx-menu-item-disabled-color` | `color.fg.disabled` | `#a2a098` |
2012
2135
  | `menu.item.accent.color` | `--mx-menu-item-accent-color` | `color.accent.fg` | `#983318` |
2013
- | `menu.item.success.color` | `--mx-menu-item-success-color` | `color.success.fg` | `#0c6a0c` |
2014
- | `menu.item.caution.color` | `--mx-menu-item-caution-color` | `color.caution.fg` | `#845000` |
2015
- | `menu.item.danger.color` | `--mx-menu-item-danger-color` | `color.danger.fg` | `#b3261a` |
2136
+ | `menu.item.success.color` | `--mx-menu-item-success-color` | `color.success.fg` | `#006402` |
2137
+ | `menu.item.caution.color` | `--mx-menu-item-caution-color` | `color.caution.fg` | `#754702` |
2138
+ | `menu.item.danger.color` | `--mx-menu-item-danger-color` | `color.danger.fg` | `#b03659` |
2016
2139
  | `menu.item.checked.bg` | `--mx-menu-item-checked-bg` | `` | `initial` |
2017
2140
  | `menu.item.first.radius-top` | `--mx-menu-item-first-radius-top` | `` | `initial` |
2018
2141
  | `menu.item.last.radius-bottom` | `--mx-menu-item-last-radius-bottom` | `` | `initial` |
@@ -2021,9 +2144,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2021
2144
  | `menu.check.disabled.color` | `--mx-menu-check-disabled-color` | `` | `initial` |
2022
2145
  | `menu.icon.size` | `--mx-menu-icon-size` | `icon.size.md` | `1rem` |
2023
2146
  | `menu.icon.accent.color` | `--mx-menu-icon-accent-color` | `color.accent.fg` | `#983318` |
2024
- | `menu.icon.success.color` | `--mx-menu-icon-success-color` | `color.success.fg` | `#0c6a0c` |
2025
- | `menu.icon.caution.color` | `--mx-menu-icon-caution-color` | `color.caution.fg` | `#845000` |
2026
- | `menu.icon.danger.color` | `--mx-menu-icon-danger-color` | `color.danger.fg` | `#b3261a` |
2147
+ | `menu.icon.success.color` | `--mx-menu-icon-success-color` | `color.success.fg` | `#006402` |
2148
+ | `menu.icon.caution.color` | `--mx-menu-icon-caution-color` | `color.caution.fg` | `#754702` |
2149
+ | `menu.icon.danger.color` | `--mx-menu-icon-danger-color` | `color.danger.fg` | `#b03659` |
2027
2150
  | `menu.icon.color` | `--mx-menu-icon-color` | `` | `initial` |
2028
2151
  | `menu.icon.disabled.color` | `--mx-menu-icon-disabled-color` | `` | `initial` |
2029
2152
  | `menu.check-mark.icon` | `--mx-menu-check-mark-icon` | `` | `var(--mx-icon-check)` |
@@ -2090,6 +2213,36 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2090
2213
  | `pagination.info.color` | `--mx-pagination-info-color` | `color.fg.secondary` | `#5e5c55` |
2091
2214
  | `pagination.info.font-size` | `--mx-pagination-info-font-size` | `font.size.body` | `0.875rem` |
2092
2215
  | `pagination.info.padding-inline` | `--mx-pagination-info-padding-inline` | `space.2` | `0.5rem` |
2216
+ | `popover.offset` | `--mx-popover-offset` | `space.2` | `0.5rem` |
2217
+ | `popover.enter-offset` | `--mx-popover-enter-offset` | `` | `4px` |
2218
+ | `popover.header-gap` | `--mx-popover-header-gap` | `space.2` | `0.5rem` |
2219
+ | `popover.close.variant` | `--mx-popover-close-variant` | `` | `ghost` |
2220
+ | `popover.surface.bg` | `--mx-popover-surface-bg` | `color.bg.surface` | `#f8f7f3` |
2221
+ | `popover.surface.border-width` | `--mx-popover-surface-border-width` | `border.width.1` | `1px` |
2222
+ | `popover.surface.border-color` | `--mx-popover-surface-border-color` | `color.stroke.surface` | `rgb(117 117 117 / 0.4)` |
2223
+ | `popover.surface.radius` | `--mx-popover-surface-radius` | `radius.lg` | `0.625rem` |
2224
+ | `popover.surface.shadow` | `--mx-popover-surface-shadow` | `elevation.popup` | `0px 8px 16px 0px rgb(0 0 0 / 0.14), 0px 0px 2px 0px rgb(0 0 0 / 0.12)` |
2225
+ | `popover.surface.color` | `--mx-popover-surface-color` | `color.fg.primary` | `#1d1c1a` |
2226
+ | `popover.surface.font-size` | `--mx-popover-surface-font-size` | `font.size.body` | `0.875rem` |
2227
+ | `popover.surface.line-height` | `--mx-popover-surface-line-height` | `font.line.body` | `1.25rem` |
2228
+ | `popover.surface.max-width` | `--mx-popover-surface-max-width` | `` | `24rem` |
2229
+ | `popover.surface.focus.glow` | `--mx-popover-surface-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
2230
+ | `popover.surface.focus.outline-width` | `--mx-popover-surface-focus-outline-width` | `focus.ring.width` | `2px` |
2231
+ | `popover.surface.focus.outline-color` | `--mx-popover-surface-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
2232
+ | `popover.surface.focus.outline-offset` | `--mx-popover-surface-focus-outline-offset` | `focus.ring.offset` | `1px` |
2233
+ | `popover.arrow.display` | `--mx-popover-arrow-display` | `` | `block` |
2234
+ | `popover.arrow.size` | `--mx-popover-arrow-size` | `` | `0.75rem` |
2235
+ | `popover.arrow.bg` | `--mx-popover-arrow-bg` | `color.bg.surface` | `#f8f7f3` |
2236
+ | `popover.arrow.border-width` | `--mx-popover-arrow-border-width` | `border.width.1` | `1px` |
2237
+ | `popover.arrow.border-color` | `--mx-popover-arrow-border-color` | `color.stroke.surface` | `rgb(117 117 117 / 0.4)` |
2238
+ | `popover.header.padding-block` | `--mx-popover-header-padding-block` | `space.2` | `0.5rem` |
2239
+ | `popover.header.padding-start` | `--mx-popover-header-padding-start` | `space.3` | `0.75rem` |
2240
+ | `popover.header.padding-end` | `--mx-popover-header-padding-end` | `space.2` | `0.5rem` |
2241
+ | `popover.header.border-bottom-width` | `--mx-popover-header-border-bottom-width` | `border.width.1` | `1px` |
2242
+ | `popover.header.border-bottom-color` | `--mx-popover-header-border-bottom-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
2243
+ | `popover.title.font-weight` | `--mx-popover-title-font-weight` | `font.weight.semibold` | `600` |
2244
+ | `popover.title.color` | `--mx-popover-title-color` | `color.fg.primary` | `#1d1c1a` |
2245
+ | `popover.body.padding` | `--mx-popover-body-padding` | `space.3` | `0.75rem` |
2093
2246
  | `popup.offset` | `--mx-popup-offset` | `space.1` | `0.25rem` |
2094
2247
  | `popup.list-box.box.bg` | `--mx-popup-list-box-box-bg` | `` | `rgb(0 0 0 / 0)` |
2095
2248
  | `popup.list-box.box.hover.bg` | `--mx-popup-list-box-box-hover-bg` | `` | `rgb(0 0 0 / 0)` |
@@ -2168,11 +2321,11 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2168
2321
  | `progress.accent-subtle` | `--mx-progress-accent-subtle` | `color.accent.subtle` | `#fbe6de` |
2169
2322
  | `progress.neutral` | `--mx-progress-neutral` | `color.fg.secondary` | `#5e5c55` |
2170
2323
  | `progress.neutral-subtle` | `--mx-progress-neutral-subtle` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
2171
- | `progress.success` | `--mx-progress-success` | `color.success.fg` | `#0c6a0c` |
2324
+ | `progress.success` | `--mx-progress-success` | `color.success.fg` | `#006402` |
2172
2325
  | `progress.success-subtle` | `--mx-progress-success-subtle` | `color.success.subtle` | `#dff6dd` |
2173
- | `progress.caution` | `--mx-progress-caution` | `color.caution.fg` | `#845000` |
2326
+ | `progress.caution` | `--mx-progress-caution` | `color.caution.fg` | `#754702` |
2174
2327
  | `progress.caution-subtle` | `--mx-progress-caution-subtle` | `color.caution.subtle` | `#fff4ce` |
2175
- | `progress.danger` | `--mx-progress-danger` | `color.danger.solid` | `#b3261a` |
2328
+ | `progress.danger` | `--mx-progress-danger` | `color.danger.solid` | `#b03659` |
2176
2329
  | `progress.danger-subtle` | `--mx-progress-danger-subtle` | `color.danger.subtle` | `#fde7e9` |
2177
2330
  | `progress.track.bg` | `--mx-progress-track-bg` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
2178
2331
  | `progress.track.radius` | `--mx-progress-track-radius` | `radius.full` | `9999px` |
@@ -2248,21 +2401,21 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2248
2401
  | `radiogroup.circle.checked.bg` | `--mx-radiogroup-circle-checked-bg` | `color.accent.solid` | `#c24523` |
2249
2402
  | `radiogroup.circle.checked.border-color` | `--mx-radiogroup-circle-checked-border-color` | `color.accent.solid` | `#c24523` |
2250
2403
  | `radiogroup.circle.checked.shadow` | `--mx-radiogroup-circle-checked-shadow` | `` | `0 1px 0 rgb(0 0 0 / 0.3)` |
2251
- | `radiogroup.circle.invalid.border-color` | `--mx-radiogroup-circle-invalid-border-color` | `color.danger.solid` | `#b3261a` |
2252
- | `radiogroup.circle.invalid.shadow` | `--mx-radiogroup-circle-invalid-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b3261a` |
2253
- | `radiogroup.circle.checked-invalid.shadow` | `--mx-radiogroup-circle-checked-invalid-shadow` | `` | `0 1px 0 #b3261a` |
2404
+ | `radiogroup.circle.invalid.border-color` | `--mx-radiogroup-circle-invalid-border-color` | `color.danger.solid` | `#b03659` |
2405
+ | `radiogroup.circle.invalid.shadow` | `--mx-radiogroup-circle-invalid-shadow` | `` | `inset 0px 1px 0px 0px rgb(255 255 255 / 0.7), 0 1px 0 #b03659` |
2406
+ | `radiogroup.circle.checked-invalid.shadow` | `--mx-radiogroup-circle-checked-invalid-shadow` | `` | `0 1px 0 #b03659` |
2254
2407
  | `radiogroup.circle.hover.bg` | `--mx-radiogroup-circle-hover-bg` | `color.fill.control.secondary` | `#ebeae5` |
2255
2408
  | `radiogroup.circle.hover.border-color` | `--mx-radiogroup-circle-hover-border-color` | `` | `initial` |
2256
2409
  | `radiogroup.circle.checked-hover.bg` | `--mx-radiogroup-circle-checked-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
2257
2410
  | `radiogroup.circle.checked-hover.border-color` | `--mx-radiogroup-circle-checked-hover-border-color` | `color.accent.solid-hover` | `#b43f20` |
2258
- | `radiogroup.circle.invalid-hover.border-color` | `--mx-radiogroup-circle-invalid-hover-border-color` | `color.danger.solid` | `#b3261a` |
2411
+ | `radiogroup.circle.invalid-hover.border-color` | `--mx-radiogroup-circle-invalid-hover-border-color` | `color.danger.solid` | `#b03659` |
2259
2412
  | `radiogroup.circle.pressed.bg` | `--mx-radiogroup-circle-pressed-bg` | `color.fill.control.tertiary` | `#e1e0da` |
2260
2413
  | `radiogroup.circle.pressed.border-color` | `--mx-radiogroup-circle-pressed-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
2261
2414
  | `radiogroup.circle.pressed.shadow` | `--mx-radiogroup-circle-pressed-shadow` | `` | `0 0 #0000` |
2262
2415
  | `radiogroup.circle.checked-pressed.bg` | `--mx-radiogroup-circle-checked-pressed-bg` | `color.accent.solid-hover` | `#b43f20` |
2263
2416
  | `radiogroup.circle.checked-pressed.border-color` | `--mx-radiogroup-circle-checked-pressed-border-color` | `color.accent.solid-hover` | `#b43f20` |
2264
2417
  | `radiogroup.circle.checked-pressed.shadow` | `--mx-radiogroup-circle-checked-pressed-shadow` | `` | `0 0 #0000` |
2265
- | `radiogroup.circle.invalid-pressed.border-color` | `--mx-radiogroup-circle-invalid-pressed-border-color` | `color.danger.solid` | `#b3261a` |
2418
+ | `radiogroup.circle.invalid-pressed.border-color` | `--mx-radiogroup-circle-invalid-pressed-border-color` | `color.danger.solid` | `#b03659` |
2266
2419
  | `radiogroup.circle.focus.outline-width` | `--mx-radiogroup-circle-focus-outline-width` | `focus.ring.width` | `2px` |
2267
2420
  | `radiogroup.circle.focus.outline-color` | `--mx-radiogroup-circle-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
2268
2421
  | `radiogroup.circle.focus.outline-offset` | `--mx-radiogroup-circle-focus-outline-offset` | `focus.ring.offset` | `1px` |
@@ -2528,9 +2681,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2528
2681
  | `scheduler.cell.line-hour.border-start-color` | `--mx-scheduler-cell-line-hour-border-start-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
2529
2682
  | `scheduler.cell.line-day.border-start-color` | `--mx-scheduler-cell-line-day-border-start-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
2530
2683
  | `scheduler.now.height` | `--mx-scheduler-now-height` | `border.width.2` | `2px` |
2531
- | `scheduler.now.bg` | `--mx-scheduler-now-bg` | `color.danger.solid` | `#b3261a` |
2684
+ | `scheduler.now.bg` | `--mx-scheduler-now-bg` | `color.danger.solid` | `#b03659` |
2532
2685
  | `scheduler.now-dot.size` | `--mx-scheduler-now-dot-size` | `` | `0px` |
2533
- | `scheduler.now-dot.bg` | `--mx-scheduler-now-dot-bg` | `color.danger.solid` | `#b3261a` |
2686
+ | `scheduler.now-dot.bg` | `--mx-scheduler-now-dot-bg` | `color.danger.solid` | `#b03659` |
2534
2687
  | `scheduler.now-dot.radius` | `--mx-scheduler-now-dot-radius` | `` | `50%` |
2535
2688
  | `scheduler.weekdays.bg` | `--mx-scheduler-weekdays-bg` | `color.bg.surface` | `#f8f7f3` |
2536
2689
  | `scheduler.weekdays.border-bottom-width` | `--mx-scheduler-weekdays-border-bottom-width` | `border.width.1` | `1px` |
@@ -2559,7 +2712,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2559
2712
  | `scheduler.appointment.draft.cursor` | `--mx-scheduler-appointment-draft-cursor` | `` | `grabbing` |
2560
2713
  | `scheduler.appointment.invalid.outline-style` | `--mx-scheduler-appointment-invalid-outline-style` | `` | `dashed` |
2561
2714
  | `scheduler.appointment.invalid.outline-width` | `--mx-scheduler-appointment-invalid-outline-width` | `border.width.2` | `2px` |
2562
- | `scheduler.appointment.invalid.outline-color` | `--mx-scheduler-appointment-invalid-outline-color` | `color.danger.solid` | `#b3261a` |
2715
+ | `scheduler.appointment.invalid.outline-color` | `--mx-scheduler-appointment-invalid-outline-color` | `color.danger.solid` | `#b03659` |
2563
2716
  | `scheduler.appointment.invalid.cursor` | `--mx-scheduler-appointment-invalid-cursor` | `` | `not-allowed` |
2564
2717
  | `scheduler.appointment.saving.opacity` | `--mx-scheduler-appointment-saving-opacity` | `` | `0.7` |
2565
2718
  | `scheduler.appointment.saving.cursor` | `--mx-scheduler-appointment-saving-cursor` | `` | `progress` |
@@ -2652,7 +2805,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2652
2805
  | `scheduler.state.bg` | `--mx-scheduler-state-bg` | `color.bg.surface` | `#f8f7f3` |
2653
2806
  | `scheduler.state.radius` | `--mx-scheduler-state-radius` | `radius.md` | `0.375rem` |
2654
2807
  | `scheduler.state.shadow` | `--mx-scheduler-state-shadow` | `elevation.popup` | `0px 8px 16px 0px rgb(0 0 0 / 0.14), 0px 0px 2px 0px rgb(0 0 0 / 0.12)` |
2655
- | `scheduler.state.danger.color` | `--mx-scheduler-state-danger-color` | `color.danger.fg` | `#b3261a` |
2808
+ | `scheduler.state.danger.color` | `--mx-scheduler-state-danger-color` | `color.danger.fg` | `#b03659` |
2656
2809
  | `scheduler.timeline-row.border-top-width` | `--mx-scheduler-timeline-row-border-top-width` | `border.width.1` | `1px` |
2657
2810
  | `scheduler.timeline-row.border-color` | `--mx-scheduler-timeline-row-border-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
2658
2811
  | `scheduler.timeline-row.first.border-top-width` | `--mx-scheduler-timeline-row-first-border-top-width` | `` | `0px` |
@@ -2770,6 +2923,17 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2770
2923
  | `scheduler.swipe-icon.height` | `--mx-scheduler-swipe-icon-height` | `icon.size.md` | `1rem` |
2771
2924
  | `scheduler.swipe-icon.icon` | `--mx-scheduler-swipe-icon-icon` | `` | `var(--mx-icon-chevron-end)` |
2772
2925
  | `scheduler.swipe-icon.previous.icon` | `--mx-scheduler-swipe-icon-previous-icon` | `` | `var(--mx-icon-chevron-start)` |
2926
+ | `scroll-view.panel-height` | `--mx-scroll-view-panel-height` | `` | `3rem` |
2927
+ | `scroll-view.panel-gap` | `--mx-scroll-view-panel-gap` | `space.2` | `0.5rem` |
2928
+ | `scroll-view.box.focus.glow` | `--mx-scroll-view-box-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
2929
+ | `scroll-view.box.focus.outline-width` | `--mx-scroll-view-box-focus-outline-width` | `focus.ring.width` | `2px` |
2930
+ | `scroll-view.box.focus.outline-color` | `--mx-scroll-view-box-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
2931
+ | `scroll-view.box.focus.outline-offset` | `--mx-scroll-view-box-focus-outline-offset` | `focus.ring.offset` | `1px` |
2932
+ | `scroll-view.pull.color` | `--mx-scroll-view-pull-color` | `color.fg.secondary` | `#5e5c55` |
2933
+ | `scroll-view.pull.font-size` | `--mx-scroll-view-pull-font-size` | `font.size.caption` | `0.75rem` |
2934
+ | `scroll-view.pull.refreshing.color` | `--mx-scroll-view-pull-refreshing-color` | `color.fg.primary` | `#1d1c1a` |
2935
+ | `scroll-view.bottom.color` | `--mx-scroll-view-bottom-color` | `color.fg.secondary` | `#5e5c55` |
2936
+ | `scroll-view.bottom.font-size` | `--mx-scroll-view-bottom-font-size` | `font.size.caption` | `0.75rem` |
2773
2937
  | `sheet.font-family` | `--mx-sheet-font-family` | `font.family.sans` | `Archivo, system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif` |
2774
2938
  | `sheet.inset` | `--mx-sheet-inset` | `` | `0px` |
2775
2939
  | `sheet.top-gap` | `--mx-sheet-top-gap` | `space.10` | `2.5rem` |
@@ -2956,6 +3120,20 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2956
3120
  | `slider.stop.radius` | `--mx-slider-stop-radius` | `` | `initial` |
2957
3121
  | `slider.stop.bg` | `--mx-slider-stop-bg` | `` | `initial` |
2958
3122
  | `slider.stop.active.bg` | `--mx-slider-stop-active-bg` | `` | `initial` |
3123
+ | `sortable.gap` | `--mx-sortable-gap` | `space.1` | `0.25rem` |
3124
+ | `sortable.container.target.bg` | `--mx-sortable-container-target-bg` | `color.accent.subtle` | `#fbe6de` |
3125
+ | `sortable.item.sortable.cursor` | `--mx-sortable-item-sortable-cursor` | `` | `grab` |
3126
+ | `sortable.item.dragging.opacity` | `--mx-sortable-item-dragging-opacity` | `` | `0.4` |
3127
+ | `sortable.item.focus.glow` | `--mx-sortable-item-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
3128
+ | `sortable.item.focus.outline-width` | `--mx-sortable-item-focus-outline-width` | `focus.ring.width` | `2px` |
3129
+ | `sortable.item.focus.outline-color` | `--mx-sortable-item-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
3130
+ | `sortable.item.focus.outline-offset` | `--mx-sortable-item-focus-outline-offset` | `focus.ring.offset` | `1px` |
3131
+ | `sortable.line.height` | `--mx-sortable-line-height` | `` | `2px` |
3132
+ | `sortable.line.radius` | `--mx-sortable-line-radius` | `radius.full` | `9999px` |
3133
+ | `sortable.line.bg` | `--mx-sortable-line-bg` | `color.accent.solid` | `#c24523` |
3134
+ | `sortable.ghost.radius` | `--mx-sortable-ghost-radius` | `radius.md` | `0.375rem` |
3135
+ | `sortable.ghost.shadow` | `--mx-sortable-ghost-shadow` | `elevation.popup` | `0px 8px 16px 0px rgb(0 0 0 / 0.14), 0px 0px 2px 0px rgb(0 0 0 / 0.12)` |
3136
+ | `sortable.ghost.opacity` | `--mx-sortable-ghost-opacity` | `` | `0.9` |
2959
3137
  | `spinner.gap` | `--mx-spinner-gap` | `space.2` | `0.5rem` |
2960
3138
  | `spinner.cover-padding` | `--mx-spinner-cover-padding` | `space.4` | `1rem` |
2961
3139
  | `spinner.cover-background` | `--mx-spinner-cover-background` | `color.bg.glass` | `rgb(248 247 243 / 0.78)` |
@@ -2971,9 +3149,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
2971
3149
  | `spinner.track-color` | `--mx-spinner-track-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
2972
3150
  | `spinner.accent` | `--mx-spinner-accent` | `color.accent.solid` | `#c24523` |
2973
3151
  | `spinner.neutral` | `--mx-spinner-neutral` | `color.fg.secondary` | `#5e5c55` |
2974
- | `spinner.success` | `--mx-spinner-success` | `color.success.fg` | `#0c6a0c` |
2975
- | `spinner.caution` | `--mx-spinner-caution` | `color.caution.fg` | `#845000` |
2976
- | `spinner.danger` | `--mx-spinner-danger` | `color.danger.solid` | `#b3261a` |
3152
+ | `spinner.success` | `--mx-spinner-success` | `color.success.fg` | `#006402` |
3153
+ | `spinner.caution` | `--mx-spinner-caution` | `color.caution.fg` | `#754702` |
3154
+ | `spinner.danger` | `--mx-spinner-danger` | `color.danger.solid` | `#b03659` |
2977
3155
  | `spinner.radius` | `--mx-spinner-radius` | `radius.full` | `9999px` |
2978
3156
  | `spinner.cover-fg` | `--mx-spinner-cover-fg` | `color.fg.primary` | `#1d1c1a` |
2979
3157
  | `spinner.focus-width` | `--mx-spinner-focus-width` | `focus.ring.width` | `2px` |
@@ -3000,6 +3178,63 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3000
3178
  | `spinner.shape.display` | `--mx-spinner-shape-display` | `` | `initial` |
3001
3179
  | `spinner.shape.contained.bg` | `--mx-spinner-shape-contained-bg` | `` | `initial` |
3002
3180
  | `spinner.shape.contained.scale` | `--mx-spinner-shape-contained-scale` | `` | `initial` |
3181
+ | `stepper.font-size.sm` | `--mx-stepper-font-size-sm` | `font.size.caption` | `0.75rem` |
3182
+ | `stepper.font-size.md` | `--mx-stepper-font-size-md` | `font.size.body` | `0.875rem` |
3183
+ | `stepper.font-size.lg` | `--mx-stepper-font-size-lg` | `` | `1rem` |
3184
+ | `stepper.description-font-size` | `--mx-stepper-description-font-size` | `font.size.caption` | `0.75rem` |
3185
+ | `stepper.gap` | `--mx-stepper-gap` | `space.2` | `0.5rem` |
3186
+ | `stepper.line-gap` | `--mx-stepper-line-gap` | `space.2` | `0.5rem` |
3187
+ | `stepper.line-min-length` | `--mx-stepper-line-min-length` | `` | `1rem` |
3188
+ | `stepper.size.sm` | `--mx-stepper-size-sm` | `` | `1.5rem` |
3189
+ | `stepper.size.md` | `--mx-stepper-size-md` | `` | `1.75rem` |
3190
+ | `stepper.size.lg` | `--mx-stepper-size-lg` | `` | `2.25rem` |
3191
+ | `stepper.padding.sm` | `--mx-stepper-padding-sm` | `` | `0.25rem` |
3192
+ | `stepper.padding.md` | `--mx-stepper-padding-md` | `` | `0.375rem` |
3193
+ | `stepper.padding.lg` | `--mx-stepper-padding-lg` | `` | `0.5rem` |
3194
+ | `stepper.step.radius` | `--mx-stepper-step-radius` | `radius.sm` | `0.25rem` |
3195
+ | `stepper.step.color` | `--mx-stepper-step-color` | `color.fg.secondary` | `#5e5c55` |
3196
+ | `stepper.step.hover.bg` | `--mx-stepper-step-hover-bg` | `color.fill.subtle.secondary` | `rgb(0 0 0 / 0.0373)` |
3197
+ | `stepper.step.hover.cursor` | `--mx-stepper-step-hover-cursor` | `` | `pointer` |
3198
+ | `stepper.step.pressed.bg` | `--mx-stepper-step-pressed-bg` | `color.fill.subtle.tertiary` | `rgb(0 0 0 / 0.0241)` |
3199
+ | `stepper.step.focus.glow` | `--mx-stepper-step-focus-glow` | `focus.ring.halo` | `0px 0px 0px 1px rgb(255 255 255 / 0.7)` |
3200
+ | `stepper.step.focus.outline-width` | `--mx-stepper-step-focus-outline-width` | `focus.ring.width` | `2px` |
3201
+ | `stepper.step.focus.outline-color` | `--mx-stepper-step-focus-outline-color` | `focus.ring.color` | `#1d1c1a` |
3202
+ | `stepper.step.focus.outline-offset` | `--mx-stepper-step-focus-outline-offset` | `focus.ring.offset` | `1px` |
3203
+ | `stepper.step.disabled.color` | `--mx-stepper-step-disabled-color` | `color.fg.disabled` | `#a2a098` |
3204
+ | `stepper.step.current.color` | `--mx-stepper-step-current-color` | `color.fg.primary` | `#1d1c1a` |
3205
+ | `stepper.step.done.color` | `--mx-stepper-step-done-color` | `color.fg.primary` | `#1d1c1a` |
3206
+ | `stepper.indicator.radius` | `--mx-stepper-indicator-radius` | `radius.full` | `9999px` |
3207
+ | `stepper.indicator.bg` | `--mx-stepper-indicator-bg` | `color.fill.control.default` | `#f5f4f0` |
3208
+ | `stepper.indicator.border-width` | `--mx-stepper-indicator-border-width` | `` | `1px` |
3209
+ | `stepper.indicator.border-color` | `--mx-stepper-indicator-border-color` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
3210
+ | `stepper.indicator.color` | `--mx-stepper-indicator-color` | `color.fg.secondary` | `#5e5c55` |
3211
+ | `stepper.indicator.font-size` | `--mx-stepper-indicator-font-size` | `font.size.caption` | `0.75rem` |
3212
+ | `stepper.indicator.font-weight` | `--mx-stepper-indicator-font-weight` | `font.weight.semibold` | `600` |
3213
+ | `stepper.indicator.current.bg` | `--mx-stepper-indicator-current-bg` | `color.accent.solid` | `#c24523` |
3214
+ | `stepper.indicator.current.border-color` | `--mx-stepper-indicator-current-border-color` | `color.accent.solid` | `#c24523` |
3215
+ | `stepper.indicator.current.color` | `--mx-stepper-indicator-current-color` | `color.accent.on-solid` | `#ffffff` |
3216
+ | `stepper.indicator.done.bg` | `--mx-stepper-indicator-done-bg` | `color.accent.solid` | `#c24523` |
3217
+ | `stepper.indicator.done.border-color` | `--mx-stepper-indicator-done-border-color` | `color.accent.solid` | `#c24523` |
3218
+ | `stepper.indicator.done.color` | `--mx-stepper-indicator-done-color` | `color.accent.on-solid` | `#ffffff` |
3219
+ | `stepper.indicator.error.bg` | `--mx-stepper-indicator-error-bg` | `color.danger.solid` | `#b03659` |
3220
+ | `stepper.indicator.error.border-color` | `--mx-stepper-indicator-error-border-color` | `color.danger.solid` | `#b03659` |
3221
+ | `stepper.indicator.error.color` | `--mx-stepper-indicator-error-color` | `color.danger.on-solid` | `#ffffff` |
3222
+ | `stepper.indicator.disabled.border-color` | `--mx-stepper-indicator-disabled-border-color` | `color.stroke.control.default` | `rgb(0 0 0 / 0.12)` |
3223
+ | `stepper.indicator.disabled.color` | `--mx-stepper-indicator-disabled-color` | `color.fg.disabled` | `#a2a098` |
3224
+ | `stepper.indicator.disabled.bg` | `--mx-stepper-indicator-disabled-bg` | `` | `initial` |
3225
+ | `stepper.mark.done.icon` | `--mx-stepper-mark-done-icon` | `` | `var(--mx-icon-check)` |
3226
+ | `stepper.mark.done.bg` | `--mx-stepper-mark-done-bg` | `color.accent.on-solid` | `#ffffff` |
3227
+ | `stepper.mark.error.icon` | `--mx-stepper-mark-error-icon` | `` | `var(--mx-icon-danger)` |
3228
+ | `stepper.mark.error.bg` | `--mx-stepper-mark-error-bg` | `color.danger.on-solid` | `#ffffff` |
3229
+ | `stepper.label.current.font-weight` | `--mx-stepper-label-current-font-weight` | `font.weight.semibold` | `600` |
3230
+ | `stepper.label.error.color` | `--mx-stepper-label-error-color` | `color.danger.fg` | `#b03659` |
3231
+ | `stepper.description.color` | `--mx-stepper-description-color` | `color.fg.secondary` | `#5e5c55` |
3232
+ | `stepper.description.disabled.color` | `--mx-stepper-description-disabled-color` | `color.fg.disabled` | `#a2a098` |
3233
+ | `stepper.note.color` | `--mx-stepper-note-color` | `color.fg.secondary` | `#5e5c55` |
3234
+ | `stepper.line.height` | `--mx-stepper-line-height` | `` | `2px` |
3235
+ | `stepper.line.bg` | `--mx-stepper-line-bg` | `color.stroke.control.secondary` | `rgb(0 0 0 / 0.2)` |
3236
+ | `stepper.line.done.bg` | `--mx-stepper-line-done-bg` | `color.accent.solid` | `#c24523` |
3237
+ | `stepper.line.radius` | `--mx-stepper-line-radius` | `` | `initial` |
3003
3238
  | `switch.thumb-inset` | `--mx-switch-thumb-inset` | `space.1` | `0.25rem` |
3004
3239
  | `switch.gap` | `--mx-switch-gap` | `space.2` | `0.5rem` |
3005
3240
  | `switch.text-padding` | `--mx-switch-text-padding` | `space.2` | `0.5rem` |
@@ -3034,7 +3269,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3034
3269
  | `switch.track.radius` | `--mx-switch-track-radius` | `radius.full` | `9999px` |
3035
3270
  | `switch.track.checked.bg` | `--mx-switch-track-checked-bg` | `color.accent.solid` | `#c24523` |
3036
3271
  | `switch.track.checked.border-color` | `--mx-switch-track-checked-border-color` | `color.accent.solid` | `#c24523` |
3037
- | `switch.track.invalid.border-color` | `--mx-switch-track-invalid-border-color` | `color.danger.solid` | `#b3261a` |
3272
+ | `switch.track.invalid.border-color` | `--mx-switch-track-invalid-border-color` | `color.danger.solid` | `#b03659` |
3038
3273
  | `switch.track.hover.bg` | `--mx-switch-track-hover-bg` | `color.fill.control.secondary` | `#ebeae5` |
3039
3274
  | `switch.track.checked-hover.bg` | `--mx-switch-track-checked-hover-bg` | `color.accent.solid-hover` | `#b43f20` |
3040
3275
  | `switch.track.pressed.bg` | `--mx-switch-track-pressed-bg` | `color.fill.control.secondary` | `#ebeae5` |
@@ -3182,9 +3417,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3182
3417
  | `tabdocs.indicator.selected.bg` | `--mx-tabdocs-indicator-selected-bg` | `color.stroke.control.strong` | `rgb(0 0 0 / 0.4458)` |
3183
3418
  | `tabdocs.indicator.active.bg` | `--mx-tabdocs-indicator-active-bg` | `color.accent.solid` | `#c24523` |
3184
3419
  | `tabdocs.indicator.title.bg` | `--mx-tabdocs-indicator-title-bg` | `` | `initial` |
3185
- | `tabdocs.title.warning.color` | `--mx-tabdocs-title-warning-color` | `color.caution.fg` | `#845000` |
3186
- | `tabdocs.title.danger.color` | `--mx-tabdocs-title-danger-color` | `color.danger.fg` | `#b3261a` |
3187
- | `tabdocs.title.success.color` | `--mx-tabdocs-title-success-color` | `color.success.fg` | `#0c6a0c` |
3420
+ | `tabdocs.title.warning.color` | `--mx-tabdocs-title-warning-color` | `color.caution.fg` | `#754702` |
3421
+ | `tabdocs.title.danger.color` | `--mx-tabdocs-title-danger-color` | `color.danger.fg` | `#b03659` |
3422
+ | `tabdocs.title.success.color` | `--mx-tabdocs-title-success-color` | `color.success.fg` | `#006402` |
3188
3423
  | `tabdocs.title.accent.color` | `--mx-tabdocs-title-accent-color` | `color.accent.fg` | `#983318` |
3189
3424
  | `tabdocs.letter.font-weight` | `--mx-tabdocs-letter-font-weight` | `font.weight.semibold` | `600` |
3190
3425
  | `tabdocs.pin.radius` | `--mx-tabdocs-pin-radius` | `radius.sm` | `0.25rem` |
@@ -3205,16 +3440,16 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3205
3440
  | `tabdocs.badge.dot.padding-inline` | `--mx-tabdocs-badge-dot-padding-inline` | `` | `0px` |
3206
3441
  | `tabdocs.badge.dot.bg` | `--mx-tabdocs-badge-dot-bg` | `color.accent.solid` | `#c24523` |
3207
3442
  | `tabdocs.badge.warning.bg` | `--mx-tabdocs-badge-warning-bg` | `color.caution.subtle` | `#fff4ce` |
3208
- | `tabdocs.badge.warning.color` | `--mx-tabdocs-badge-warning-color` | `color.caution.fg` | `#845000` |
3443
+ | `tabdocs.badge.warning.color` | `--mx-tabdocs-badge-warning-color` | `color.caution.fg` | `#754702` |
3209
3444
  | `tabdocs.badge.danger.bg` | `--mx-tabdocs-badge-danger-bg` | `color.danger.subtle` | `#fde7e9` |
3210
- | `tabdocs.badge.danger.color` | `--mx-tabdocs-badge-danger-color` | `color.danger.fg` | `#b3261a` |
3445
+ | `tabdocs.badge.danger.color` | `--mx-tabdocs-badge-danger-color` | `color.danger.fg` | `#b03659` |
3211
3446
  | `tabdocs.badge.success.bg` | `--mx-tabdocs-badge-success-bg` | `color.success.subtle` | `#dff6dd` |
3212
- | `tabdocs.badge.success.color` | `--mx-tabdocs-badge-success-color` | `color.success.fg` | `#0c6a0c` |
3447
+ | `tabdocs.badge.success.color` | `--mx-tabdocs-badge-success-color` | `color.success.fg` | `#006402` |
3213
3448
  | `tabdocs.badge.accent.bg` | `--mx-tabdocs-badge-accent-bg` | `color.accent.subtle` | `#fbe6de` |
3214
3449
  | `tabdocs.badge.accent.color` | `--mx-tabdocs-badge-accent-color` | `color.accent.fg` | `#983318` |
3215
- | `tabdocs.badge.warning-dot.bg` | `--mx-tabdocs-badge-warning-dot-bg` | `color.caution.fg` | `#845000` |
3216
- | `tabdocs.badge.danger-dot.bg` | `--mx-tabdocs-badge-danger-dot-bg` | `color.danger.fg` | `#b3261a` |
3217
- | `tabdocs.badge.success-dot.bg` | `--mx-tabdocs-badge-success-dot-bg` | `color.success.fg` | `#0c6a0c` |
3450
+ | `tabdocs.badge.warning-dot.bg` | `--mx-tabdocs-badge-warning-dot-bg` | `color.caution.fg` | `#754702` |
3451
+ | `tabdocs.badge.danger-dot.bg` | `--mx-tabdocs-badge-danger-dot-bg` | `color.danger.fg` | `#b03659` |
3452
+ | `tabdocs.badge.success-dot.bg` | `--mx-tabdocs-badge-success-dot-bg` | `color.success.fg` | `#006402` |
3218
3453
  | `tabdocs.badge.accent-dot.bg` | `--mx-tabdocs-badge-accent-dot-bg` | `color.accent.fg` | `#983318` |
3219
3454
  | `tabdocs.close.radius` | `--mx-tabdocs-close-radius` | `radius.sm` | `0.25rem` |
3220
3455
  | `tabdocs.close.color` | `--mx-tabdocs-close-color` | `color.fg.secondary` | `#5e5c55` |
@@ -3616,9 +3851,9 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3616
3851
  | `toast.surface.danger.bg` | `--mx-toast-surface-danger-bg` | `` | `initial` |
3617
3852
  | `toast.icon.size` | `--mx-toast-icon-size` | `icon.size.md` | `1rem` |
3618
3853
  | `toast.icon.color` | `--mx-toast-icon-color` | `color.fg.secondary` | `#5e5c55` |
3619
- | `toast.icon.success.color` | `--mx-toast-icon-success-color` | `color.success.fg` | `#0c6a0c` |
3620
- | `toast.icon.caution.color` | `--mx-toast-icon-caution-color` | `color.caution.fg` | `#845000` |
3621
- | `toast.icon.danger.color` | `--mx-toast-icon-danger-color` | `color.danger.fg` | `#b3261a` |
3854
+ | `toast.icon.success.color` | `--mx-toast-icon-success-color` | `color.success.fg` | `#006402` |
3855
+ | `toast.icon.caution.color` | `--mx-toast-icon-caution-color` | `color.caution.fg` | `#754702` |
3856
+ | `toast.icon.danger.color` | `--mx-toast-icon-danger-color` | `color.danger.fg` | `#b03659` |
3622
3857
  | `toast.mark.icon` | `--mx-toast-mark-icon` | `` | `var(--mx-icon-info)` |
3623
3858
  | `toast.mark.success.icon` | `--mx-toast-mark-success-icon` | `` | `var(--mx-icon-success)` |
3624
3859
  | `toast.mark.caution.icon` | `--mx-toast-mark-caution-icon` | `` | `var(--mx-icon-caution)` |
@@ -3747,7 +3982,7 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3747
3982
  | `treeview.mark.size` | `--mx-treeview-mark-size` | `icon.size.sm` | `0.75rem` |
3748
3983
  | `treeview.icon.size` | `--mx-treeview-icon-size` | `icon.size.md` | `1rem` |
3749
3984
  | `treeview.error.gap` | `--mx-treeview-error-gap` | `space.1` | `0.25rem` |
3750
- | `treeview.error.color` | `--mx-treeview-error-color` | `color.danger.fg` | `#b3261a` |
3985
+ | `treeview.error.color` | `--mx-treeview-error-color` | `color.danger.fg` | `#b03659` |
3751
3986
  | `treeview.error.font-size` | `--mx-treeview-error-font-size` | `font.size.caption` | `0.75rem` |
3752
3987
  | `treeview.retry.padding-inline` | `--mx-treeview-retry-padding-inline` | `space.1` | `0.25rem` |
3753
3988
  | `treeview.retry.radius` | `--mx-treeview-retry-radius` | `radius.sm` | `0.25rem` |
@@ -3829,9 +4064,18 @@ Source: `tokens/schema/*.json` (names and types) and `tokens/languages/<language
3829
4064
  | `window.message.gap` | `--mx-window-message-gap` | `space.3` | `0.75rem` |
3830
4065
  | `window.message-icon.size` | `--mx-window-message-icon-size` | `icon.size.lg` | `1.25rem` |
3831
4066
  | `window.message-icon.color` | `--mx-window-message-icon-color` | `color.accent.fg` | `#983318` |
3832
- | `window.message-icon.success.color` | `--mx-window-message-icon-success-color` | `color.success.fg` | `#0c6a0c` |
3833
- | `window.message-icon.caution.color` | `--mx-window-message-icon-caution-color` | `color.caution.fg` | `#845000` |
3834
- | `window.message-icon.danger.color` | `--mx-window-message-icon-danger-color` | `color.danger.fg` | `#b3261a` |
4067
+ | `window.message-icon.success.color` | `--mx-window-message-icon-success-color` | `color.success.fg` | `#006402` |
4068
+ | `window.message-icon.caution.color` | `--mx-window-message-icon-caution-color` | `color.caution.fg` | `#754702` |
4069
+ | `window.message-icon.danger.color` | `--mx-window-message-icon-danger-color` | `color.danger.fg` | `#b03659` |
4070
+ | `wizard.gap` | `--mx-wizard-gap` | `space.4` | `1rem` |
4071
+ | `wizard.bar-gap` | `--mx-wizard-bar-gap` | `space.2` | `0.5rem` |
4072
+ | `wizard.rail-width` | `--mx-wizard-rail-width` | `` | `14rem` |
4073
+ | `wizard.previous.variant` | `--mx-wizard-previous-variant` | `` | `outline` |
4074
+ | `wizard.next.variant` | `--mx-wizard-next-variant` | `` | `solid` |
4075
+ | `wizard.next.tone` | `--mx-wizard-next-tone` | `` | `accent` |
4076
+ | `wizard.bar.padding-top` | `--mx-wizard-bar-padding-top` | `space.3` | `0.75rem` |
4077
+ | `wizard.bar.border-top-width` | `--mx-wizard-bar-border-top-width` | `` | `1px` |
4078
+ | `wizard.bar.border-top-color` | `--mx-wizard-bar-border-top-color` | `color.stroke.divider` | `rgb(0 0 0 / 0.1)` |
3835
4079
 
3836
4080
  ## Semantic ({semantic.length} per theme)
3837
4081
 
@@ -3846,13 +4090,13 @@ The theme's language, the only layer a theme redefines — switch the theme abov
3846
4090
  | `color.accent.fg` | `--mx-color-accent-fg` | `#983318` | `#ffb89c` | `#c7c7ff` |
3847
4091
  | `color.accent.subtle` | `--mx-color-accent-subtle` | `#fbe6de` | `#45271d` | `#000000` |
3848
4092
  | `color.accent.on-subtle` | `--mx-color-accent-on-subtle` | `#983318` | `#ffb89c` | `#c7c7ff` |
3849
- | `color.success.fg` | `--mx-color-success-fg` | `#0c6a0c` | `#6ccb5f` | `#3ff23f` |
4093
+ | `color.success.fg` | `--mx-color-success-fg` | `#006402` | `#6dc43a` | `#3ff23f` |
3850
4094
  | `color.success.subtle` | `--mx-color-success-subtle` | `#dff6dd` | `#393d1b` | `#000000` |
3851
- | `color.success.solid` | `--mx-color-success-solid` | `#0c6a0c` | `#6ccb5f` | `#3ff23f` |
4095
+ | `color.success.solid` | `--mx-color-success-solid` | `#006402` | `#6dc43a` | `#3ff23f` |
3852
4096
  | `color.success.on-solid` | `--mx-color-success-on-solid` | `#ffffff` | `#000000` | `#000000` |
3853
- | `color.caution.fg` | `--mx-color-caution-fg` | `#845000` | `#fce100` | `#ffee32` |
4097
+ | `color.caution.fg` | `--mx-color-caution-fg` | `#754702` | `#fce100` | `#ffee32` |
3854
4098
  | `color.caution.subtle` | `--mx-color-caution-subtle` | `#fff4ce` | `#433519` | `#000000` |
3855
- | `color.caution.solid` | `--mx-color-caution-solid` | `#845000` | `#fce100` | `#ffee32` |
4099
+ | `color.caution.solid` | `--mx-color-caution-solid` | `#754702` | `#fce100` | `#ffee32` |
3856
4100
  | `color.caution.on-solid` | `--mx-color-caution-on-solid` | `#ffffff` | `#000000` | `#000000` |
3857
4101
  | `color.bg.canvas` | `--mx-color-bg-canvas` | `#e1e0da` | `#232220` | `#000000` |
3858
4102
  | `color.bg.layer` | `--mx-color-bg-layer` | `#ebeae5` | `#2b2a27` | `#000000` |
@@ -3894,10 +4138,10 @@ The theme's language, the only layer a theme redefines — switch the theme abov
3894
4138
  | `color.stroke.surface` | `--mx-color-stroke-surface` | `rgb(117 117 117 / 0.4)` | `rgb(117 117 117 / 0.4)` | `#ffffff` |
3895
4139
  | `color.stroke.divider` | `--mx-color-stroke-divider` | `rgb(0 0 0 / 0.1)` | `rgb(255 255 255 / 0.0837)` | `#ffffff` |
3896
4140
  | `color.highlight.control` | `--mx-color-highlight-control` | `rgb(255 255 255 / 0.7)` | `rgb(255 255 255 / 0.06)` | `#000000` |
3897
- | `color.danger.solid` | `--mx-color-danger-solid` | `#b3261a` | `#ff99a4` | `#ff8080` |
3898
- | `color.danger.solid-hover` | `--mx-color-danger-solid-hover` | `#c42b1c` | `#e98d97` | `#ffa0a0` |
4141
+ | `color.danger.solid` | `--mx-color-danger-solid` | `#b03659` | `#ff99a4` | `#ff8080` |
4142
+ | `color.danger.solid-hover` | `--mx-color-danger-solid-hover` | `#c13b61` | `#e98d97` | `#ffa0a0` |
3899
4143
  | `color.danger.on-solid` | `--mx-color-danger-on-solid` | `#ffffff` | `#000000` | `#000000` |
3900
- | `color.danger.fg` | `--mx-color-danger-fg` | `#b3261a` | `#ff99a4` | `#ffbcbc` |
4144
+ | `color.danger.fg` | `--mx-color-danger-fg` | `#b03659` | `#ff99a4` | `#ffbcbc` |
3901
4145
  | `color.danger.subtle` | `--mx-color-danger-subtle` | `#fde7e9` | `#442726` | `#000000` |
3902
4146
  | `color.info.subtle` | `--mx-color-info-subtle` | `#ebeae5` | `#2b2a27` | `#000000` |
3903
4147
  | `color.info.solid` | `--mx-color-info-solid` | `#5e5c55` | `#d0cfc9` | `#ffffff` |
@@ -4035,17 +4279,17 @@ The shared palette and scales, the same in every design language. Themes and com
4035
4279
  | `color.accent.light3` | color | `--mx-color-accent-light3` | `#ffb89c` |
4036
4280
  | `color.accent.tint-light` | color | `--mx-color-accent-tint-light` | `#fbe6de` |
4037
4281
  | `color.accent.tint-dark` | color | `--mx-color-accent-tint-dark` | `#45271d` |
4038
- | `color.critical.light` | color | `--mx-color-critical-light` | `#b3261a` |
4039
- | `color.critical.light-hover` | color | `--mx-color-critical-light-hover` | `#c42b1c` |
4282
+ | `color.critical.light` | color | `--mx-color-critical-light` | `#b03659` |
4283
+ | `color.critical.light-hover` | color | `--mx-color-critical-light-hover` | `#c13b61` |
4040
4284
  | `color.critical.light-bg` | color | `--mx-color-critical-light-bg` | `#fde7e9` |
4041
4285
  | `color.critical.dark` | color | `--mx-color-critical-dark` | `#ff99a4` |
4042
4286
  | `color.critical.dark-hover` | color | `--mx-color-critical-dark-hover` | `#e98d97` |
4043
4287
  | `color.critical.dark-bg` | color | `--mx-color-critical-dark-bg` | `#442726` |
4044
- | `color.success.light` | color | `--mx-color-success-light` | `#0c6a0c` |
4288
+ | `color.success.light` | color | `--mx-color-success-light` | `#006402` |
4045
4289
  | `color.success.light-bg` | color | `--mx-color-success-light-bg` | `#dff6dd` |
4046
- | `color.success.dark` | color | `--mx-color-success-dark` | `#6ccb5f` |
4290
+ | `color.success.dark` | color | `--mx-color-success-dark` | `#6dc43a` |
4047
4291
  | `color.success.dark-bg` | color | `--mx-color-success-dark-bg` | `#393d1b` |
4048
- | `color.caution.light` | color | `--mx-color-caution-light` | `#845000` |
4292
+ | `color.caution.light` | color | `--mx-color-caution-light` | `#754702` |
4049
4293
  | `color.caution.light-bg` | color | `--mx-color-caution-light-bg` | `#fff4ce` |
4050
4294
  | `color.caution.dark` | color | `--mx-color-caution-dark` | `#fce100` |
4051
4295
  | `color.caution.dark-bg` | color | `--mx-color-caution-dark-bg` | `#433519` |
@@ -4214,7 +4458,7 @@ cssVar('color.accent.solid'); // 'var(--mx-color-accent-solid)' — a design-sy
4214
4458
 
4215
4459
  # Control
4216
4460
 
4217
- > Foundations · @motifx-community/ui 0.1.0-beta.0
4461
+ > Foundations · @motifx-community/ui 0.1.0-beta.2
4218
4462
 
4219
4463
  The base of every control in the package. It gives each one the same `text`, `enabled`, `visible` and `tabStop`, and the same focus methods, whether the control is written in JSX and bound to state or created with `new` and changed from code.
4220
4464
 
@@ -4450,7 +4694,7 @@ The base adds no listeners per control and pays only for what is used.
4450
4694
 
4451
4695
  # Keyboard and focus
4452
4696
 
4453
- > Foundations · @motifx-community/ui 0.1.0-beta.0
4697
+ > Foundations · @motifx-community/ui 0.1.0-beta.2
4454
4698
 
4455
4699
  The rules every control follows: Tab order, the active control of a container, focus that never falls to `<body>`, `&File` access keys and app-wide shortcuts.
4456
4700
 
@@ -4638,11 +4882,244 @@ export default function FocusGuard() {
4638
4882
  Controls: see `Control` for `tabStop`, `tabIndex`, `focus()`, `onAccessKey()` and `FocusContainer`.
4639
4883
 
4640
4884
 
4885
+ ---
4886
+
4887
+ # Language
4888
+
4889
+ > Foundations · @motifx-community/ui 0.1.0-beta.2
4890
+
4891
+ The texts the controls write, the locale their dates and numbers follow, and the direction: one `uiLocale` for the kit, with a pack per language loaded as it is asked for.
4892
+
4893
+ ## Import
4894
+
4895
+ ```tsx
4896
+ import { uiLocale, connectI18n } from '@motifx-community/ui';
4897
+ ```
4898
+
4899
+ ## Switching the language
4900
+
4901
+ `uiLocale.use('tr')` loads the Turkish pack the first time, then every control on the page draws its texts and formats again. The Language menu in the header of these docs does the same.
4902
+
4903
+ ```tsx
4904
+ import { reactive } from '@motifx/core';
4905
+ import { Button, DateBox, NumberBox, Pagination, Stack, uiLocale } from '@motifx-community/ui';
4906
+ import { kitTexts } from '../../../shared/kit-texts';
4907
+
4908
+ /** The kit's language switched live: the pack is loaded first, then every control draws its texts and formats again. */
4909
+ export default function Switch() {
4910
+ const s = reactive({ price: 1234.5, when: new Date(2026, 2, 18) as Date | null });
4911
+ return (
4912
+ <Stack gap="md">
4913
+ <Stack orientation="horizontal" wrap align="center">
4914
+ <Button text="English" variant="outline" onclick={() => void uiLocale.use('en')} />
4915
+ <Button text="Türkçe" variant="outline" onclick={() => void uiLocale.use('tr')} />
4916
+ <span>
4917
+ In use: <output class="lang-locale">{() => kitTexts.locale}</output>
4918
+ </span>
4919
+ </Stack>
4920
+ <Stack orientation="horizontal" wrap align="center">
4921
+ <NumberBox label="Price" x-model={() => s.price} format={{ style: 'currency', currency: 'EUR' }} />
4922
+ <DateBox label="When" x-model={() => s.when} clearButton />
4923
+ </Stack>
4924
+ <Pagination total={95} pageSizes={[10, 20, 50]} label="Orders" />
4925
+ </Stack>
4926
+ );
4927
+ }
4928
+ ```
4929
+
4930
+ ## The rules
4931
+
4932
+ | Rule | How |
4933
+ | --- | --- |
4934
+ | `Start` | The page’s `<html lang>`, else the browser’s language. Set `lang` before the first control is made; `uiLocale.ready` settles once that language is in. |
4935
+ | `Texts` | Every text a control writes itself (a button’s name, a message, “No items”) comes from the pack of the language in use; English fills what the pack leaves out. |
4936
+ | `Formats` | Dates, numbers, the first day of the week and 12 or 24 hours follow `uiLocale.locale`; a control’s own `locale` prop wins for that control. |
4937
+ | `Direction` | `uiLocale.dir` is `rtl` for Arabic, Hebrew, Persian, Urdu…; the controls lay themselves out from `<html dir>`, which `@motifx-community/i18n` keeps in step. |
4938
+ | `Nothing follows` | A change is one event, `onChanged`: the controls draw again on it, and so can your own texts. No binding reads `uiLocale`. |
4939
+ | `Plurals` | A text with a count is an ICU message, `{count, plural, one {# record} other {# records}}`; a pack writes it the way its language counts. |
4940
+
4941
+ ## Packs
4942
+
4943
+ | Pack | Where it comes from |
4944
+ | --- | --- |
4945
+ | `English` | Built in. What a pack leaves out is shown in English. |
4946
+ | `Turkish` | `uiLocale.use('tr')` loads it the first time, as a chunk of the package. |
4947
+ | `@motifx-community/ui/locales/<language>.json` | The same packs as files, for an app that bundles or serves them its own way: `uiLocale.add('tr', pack)`. |
4948
+ | `uiLocale.loader` | Where the kit asks for a pack it does not have: `(language) => fetch(`/i18n/ui/${language}.json`).then((r) => r.json())`. A language without a pack keeps the English texts. |
4949
+
4950
+ A pack of your own is a plain object of the kit’s texts: `uiLocale.add` gives a language its texts, `use` switches to it. A few texts are enough to start; the rest stay English until the pack has them.
4951
+
4952
+ ```tsx
4953
+ import { Button, DropDown, Stack, uiLocale } from '@motifx-community/ui';
4954
+
4955
+ // A few German texts; what is left out stays English.
4956
+ uiLocale.add('de', {
4957
+ close: 'Schließen',
4958
+ clear: 'Leeren',
4959
+ search: 'Suchen',
4960
+ noItems: 'Keine Einträge',
4961
+ loading: 'Wird geladen…',
4962
+ ok: 'OK',
4963
+ cancel: 'Abbrechen',
4964
+ });
4965
+
4966
+ /** A pack of your own: `uiLocale.add` gives a language its texts, `use` switches to it. */
4967
+ export default function OwnPack() {
4968
+ return (
4969
+ <Stack gap="md">
4970
+ <Stack orientation="horizontal" wrap align="center">
4971
+ <Button text="Deutsch" variant="outline" onclick={() => void uiLocale.use('de')} />
4972
+ <Button text="English" variant="outline" onclick={() => void uiLocale.use('en')} />
4973
+ </Stack>
4974
+ <DropDown label="Empty list" items={[]} placeholder="Open me" />
4975
+ </Stack>
4976
+ );
4977
+ }
4978
+ ```
4979
+
4980
+ ## With your app’s translations
4981
+
4982
+ An app translated with `@motifx-community/i18n` has one locale already. `connectI18n(i18n)` makes the kit follow it: when the app switches, the kit loads its own pack and switches too. The link is undone by what it returns.
4983
+
4984
+ ```tsx
4985
+ import { Component } from '@motifx/core';
4986
+ import { createI18n } from '@motifx-community/i18n';
4987
+ import { Button, connectI18n, Stack, TextBox } from '@motifx-community/ui';
4988
+
4989
+ // The app's own translations; the kit follows their locale.
4990
+ const i18n = createI18n({
4991
+ locale: 'en',
4992
+ messages: {
4993
+ en: { greeting: 'Hello {name}', hint: 'The clear button is named by the kit' },
4994
+ tr: { greeting: 'Merhaba {name}', hint: 'Temizle düğmesini kit adlandırır' },
4995
+ },
4996
+ dom: false,
4997
+ });
4998
+
4999
+ /** One locale for the app and the kit: `connectI18n` switches the kit whenever the app's translations switch. */
5000
+ export default class Connect extends Component<HTMLDivElement> {
5001
+ override onBuilt(): void {
5002
+ this.motif.setDisposable(connectI18n(i18n));
5003
+ }
5004
+
5005
+ override view() {
5006
+ return (
5007
+ <Stack gap="md">
5008
+ <Stack orientation="horizontal" wrap align="center">
5009
+ <Button text="English" variant="outline" onclick={() => void i18n.setLocale('en')} />
5010
+ <Button text="Türkçe" variant="outline" onclick={() => void i18n.setLocale('tr')} />
5011
+ </Stack>
5012
+ <p class="lang-greeting">{() => i18n.t('greeting', { name: 'Ada' })}</p>
5013
+ <TextBox label={() => i18n.t('hint')} value="Clear me" clearButton />
5014
+ </Stack>
5015
+ );
5016
+ }
5017
+ }
5018
+ ```
5019
+
5020
+ ## Your own texts that follow
5021
+
5022
+ The kit follows nothing: a change of language is told once, through `uiLocale.onChanged`. Keep your own texts with it, and fill the kit’s own texts with `uiLocale.text`, plurals included.
5023
+
5024
+ ```tsx
5025
+ import { Component, reactive } from '@motifx/core';
5026
+ import { Button, NumberBox, Stack, uiLocale } from '@motifx-community/ui';
5027
+
5028
+ const OWN = {
5029
+ en: { title: 'Orders', hint: 'Written by the app, kept with the kit’s language' },
5030
+ tr: { title: 'Siparişler', hint: 'Uygulama yazar, kitin diliyle birlikte değişir' },
5031
+ };
5032
+
5033
+ /** Your own texts drawn again on `uiLocale.onChanged`, and the kit's plural texts filled with `uiLocale.text`. */
5034
+ export default class OwnTexts extends Component<HTMLDivElement> {
5035
+ s = reactive({ count: 3, title: '', hint: '', records: '' });
5036
+
5037
+ override onBuilt(): void {
5038
+ this.motif.register(uiLocale.onChanged(() => this.draw()));
5039
+ this.draw();
5040
+ }
5041
+
5042
+ draw(): void {
5043
+ const own = uiLocale.locale.startsWith('tr') ? OWN.tr : OWN.en;
5044
+ this.s.title = own.title;
5045
+ this.s.hint = own.hint;
5046
+ this.s.records = uiLocale.text('gridRecords', { count: this.s.count });
5047
+ }
5048
+
5049
+ override view() {
5050
+ return (
5051
+ <Stack gap="md">
5052
+ <Stack orientation="horizontal" wrap align="center">
5053
+ <Button text="English" variant="outline" onclick={() => void uiLocale.use('en')} />
5054
+ <Button text="Türkçe" variant="outline" onclick={() => void uiLocale.use('tr')} />
5055
+ </Stack>
5056
+ <p>
5057
+ <strong class="lang-own-title">{this.s.title}</strong>
5058
+ </p>
5059
+ <p>{this.s.hint}</p>
5060
+ <Stack orientation="horizontal" wrap align="center">
5061
+ <NumberBox label="Count" min={0} max={99} x-model={() => this.s.count} onValueChanged={() => this.draw()} />
5062
+ <output class="lang-records">{this.s.records}</output>
5063
+ </Stack>
5064
+ </Stack>
5065
+ );
5066
+ }
5067
+ }
5068
+ ```
5069
+
5070
+ ## Formats of one control
5071
+
5072
+ Dates and numbers follow the kit’s locale. A control given a `locale` of its own writes that one, whatever the kit’s language is.
5073
+
5074
+ ```tsx
5075
+ import { reactive } from '@motifx/core';
5076
+ import { DateBox, NumberBox, Stack } from '@motifx-community/ui';
5077
+
5078
+ /** A control's own `locale` wins over the kit's: these write German and Japanese whatever the kit's language is. */
5079
+ export default function Formats() {
5080
+ const s = reactive({ amount: 98765.43, day: new Date(2026, 2, 18) as Date | null });
5081
+ return (
5082
+ <Stack orientation="horizontal" wrap align="center">
5083
+ <NumberBox label="Betrag" locale="de-DE" format={{ style: 'currency', currency: 'EUR' }} x-model={() => s.amount} />
5084
+ <DateBox label="日付" locale="ja-JP" x-model={() => s.day} />
5085
+ <NumberBox label="The kit's locale" format={{ style: 'currency', currency: 'EUR' }} x-model={() => s.amount} />
5086
+ </Stack>
5087
+ );
5088
+ }
5089
+ ```
5090
+
5091
+ ## Checking a pack
5092
+
5093
+ In the repository, `npm run locales` checks every pack the kit ships, and `npm run locales -- path/to/de.json` one of your own. The texts themselves are in `src/locales/en.json`; a pack is the same keys in another language.
5094
+
5095
+ | Check | What it means |
5096
+ | --- | --- |
5097
+ | `Every text` | A pack names every text of `en.json`; one it leaves out is shown in English, and the check says which. |
5098
+ | `Only the kit’s texts` | A key `en.json` does not have is a typo. |
5099
+ | `The same arguments` | A text fills the same `{values}` as the English one, in ICU; the plural forms are the language’s own. |
5100
+ | `The interface` | `UiStrings` and `en.json` name the same keys. |
5101
+
5102
+ ## API reference
5103
+
5104
+ | Member | Type | Description |
5105
+ | --- | --- | --- |
5106
+ | `uiLocale.use(locale)` | `Promise<void>` | Switches to `locale` (`tr`, `tr-TR`): its pack is loaded first when it is not there, then every control draws again. A later call wins over one still loading. |
5107
+ | `uiLocale.locale` | `string` | The locale in use. |
5108
+ | `uiLocale.dir` | `'ltr' \| 'rtl'` | The direction of the locale in use. |
5109
+ | `uiLocale.strings` | `UiStrings` | The texts in use. Assigning a set changes the texts and keeps the locale: `uiLocale.strings = { ...uiLocale.strings, close: 'Shut' }`. |
5110
+ | `uiLocale.text(key, values)` | `string` | A text of the kit with its values filled in: `uiLocale.text('gridRecords', { count: 3 })`. |
5111
+ | `uiLocale.add(language, pack)` | `void` | Adds the pack of a language, or more texts to it; a language in use shows them at once. |
5112
+ | `uiLocale.loader` | `(language) => Promise<UiPackModule>` | Where packs come from; the package by default. |
5113
+ | `uiLocale.ready` | `Promise<void>` | Settles once the starting language is in. |
5114
+ | `uiLocale.onChanged` | event | Raised once the language changed, with `locale` and `previous`. |
5115
+ | `connectI18n(i18n)` | `() => void` | Keeps the kit’s language with your app’s translations (`@motifx-community/i18n`, or anything with `locale` and `onLocaleChanged`); returns what stops it. |
5116
+
5117
+
4641
5118
  ---
4642
5119
 
4643
5120
  # Button
4644
5121
 
4645
- > Buttons · @motifx-community/ui 0.1.0-beta.0
5122
+ > Buttons · @motifx-community/ui 0.1.0-beta.2
4646
5123
 
4647
5124
  A native `<button>` drawn from the design tokens: three variants, three tones, three sizes, an icon, an `&` access key. It can be a toggle, show that work is running, and open a menu or any content — from the whole button, or with `split` from an arrow next to it while the button keeps its own action.
4648
5125
 
@@ -4946,7 +5423,7 @@ The only text a button writes itself is the name of a split button's arrow. It c
4946
5423
 
4947
5424
  ```tsx
4948
5425
  import { reactive } from '@motifx/core';
4949
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
5426
+ import { Button, uiLocale } from '@motifx-community/ui';
4950
5427
  import { kitTexts } from '../../../shared/kit-texts';
4951
5428
 
4952
5429
  /** The name of a split button's arrow, from uiLocale: a shipped language or a text of your own. */
@@ -4955,7 +5432,7 @@ export default function Localization() {
4955
5432
 
4956
5433
  const toggle = () => {
4957
5434
  s.lang = s.lang === 'en' ? 'tr' : 'en';
4958
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
5435
+ void uiLocale.use(s.lang);
4959
5436
  };
4960
5437
 
4961
5438
  return (
@@ -5062,7 +5539,7 @@ The menu and the surface it opens on are shared parts, `MenuList` and `Popup`, e
5062
5539
 
5063
5540
  # ButtonGroup
5064
5541
 
5065
- > Buttons · @motifx-community/ui 0.1.0-beta.0
5542
+ > Buttons · @motifx-community/ui 0.1.0-beta.2
5066
5543
 
5067
5544
  Buttons that belong together: a segmented choice of one or several, or a row of actions. The buttons are the kit’s own, touching by default.
5068
5545
 
@@ -5207,7 +5684,7 @@ export default function Looks() {
5207
5684
 
5208
5685
  # Toolbar
5209
5686
 
5210
- > Buttons · @motifx-community/ui 0.1.0-beta.0
5687
+ > Buttons · @motifx-community/ui 0.1.0-beta.2
5211
5688
 
5212
5689
  A bar of commands: buttons, toggle buttons, menus and fields in groups between separators. It is one Tab stop and the arrow keys move inside it; items that do not fit move into a “more” menu at the end. Items come as data, as JSX children, or both.
5213
5690
 
@@ -5374,7 +5851,7 @@ The only text a toolbar writes itself is the name of its “more” button, from
5374
5851
 
5375
5852
  ```tsx
5376
5853
  import { reactive } from '@motifx/core';
5377
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
5854
+ import { Button, uiLocale } from '@motifx-community/ui';
5378
5855
  import { kitTexts } from '../../../shared/kit-texts';
5379
5856
 
5380
5857
  /** Switches the texts of the kit; the “more” buttons take the new name at once. */
@@ -5382,7 +5859,7 @@ export default function Localization() {
5382
5859
  const s = reactive({ lang: 'en' });
5383
5860
  const toggle = () => {
5384
5861
  s.lang = s.lang === 'en' ? 'tr' : 'en';
5385
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
5862
+ void uiLocale.use(s.lang);
5386
5863
  };
5387
5864
  return (
5388
5865
  <>
@@ -5673,7 +6150,7 @@ export default function SizeAndOrientation() {
5673
6150
 
5674
6151
  # MenuBar and ContextMenu
5675
6152
 
5676
- > Buttons · @motifx-community/ui 0.1.0-beta.0
6153
+ > Buttons · @motifx-community/ui 0.1.0-beta.2
5677
6154
 
5678
6155
  A menu bar of an app (File, Edit, View) and the menu that opens on a right-click. Both show the same menu items: submenus, check and radio items, shortcuts, access keys.
5679
6156
 
@@ -5989,7 +6466,7 @@ Menus write no text of their own: every label, shortcut and name comes from your
5989
6466
 
5990
6467
  # TextBox
5991
6468
 
5992
- > Editors · @motifx-community/ui 0.1.0-beta.0
6469
+ > Editors · @motifx-community/ui 0.1.0-beta.2
5993
6470
 
5994
6471
  A one-line text field with its label, help text and error: placeholder, prefix and suffix, buttons in the box, a clear button, a password that can be shown, a character counter, an input mask and validation — alone, in a group, or every field in a panel.
5995
6472
 
@@ -6305,7 +6782,7 @@ The names of the clear and password buttons and every validation message come fr
6305
6782
 
6306
6783
  ```tsx
6307
6784
  import { reactive } from '@motifx/core';
6308
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
6785
+ import { Button, uiLocale } from '@motifx-community/ui';
6309
6786
  import { kitTexts } from '../../../shared/kit-texts';
6310
6787
 
6311
6788
  /** Switches the texts of every field on the page; errors already shown follow too. */
@@ -6313,7 +6790,7 @@ export default function Localization() {
6313
6790
  const s = reactive({ lang: 'en' });
6314
6791
  const toggle = () => {
6315
6792
  s.lang = s.lang === 'en' ? 'tr' : 'en';
6316
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
6793
+ void uiLocale.use(s.lang);
6317
6794
  };
6318
6795
  return (
6319
6796
  <>
@@ -6442,7 +6919,7 @@ The frame (`Field`), the mask (`InputMask`, which works on any `<input>`) and va
6442
6919
 
6443
6920
  # TextArea
6444
6921
 
6445
- > Editors · @motifx-community/ui 0.1.0-beta.0
6922
+ > Editors · @motifx-community/ui 0.1.0-beta.2
6446
6923
 
6447
6924
  A text field of several lines: a box that grows with the text or that the user drags bigger, a character counter, a clear button, Ctrl+Enter to send, and the label, help text and validation every field has.
6448
6925
 
@@ -6659,7 +7136,7 @@ The name of the clear button and the validation messages come from `uiLocale.str
6659
7136
 
6660
7137
  ```tsx
6661
7138
  import { reactive } from '@motifx/core';
6662
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
7139
+ import { Button, uiLocale } from '@motifx-community/ui';
6663
7140
  import { kitTexts } from '../../../shared/kit-texts';
6664
7141
 
6665
7142
  /** Switches the texts of every field on the page, the clear button's name included. */
@@ -6667,7 +7144,7 @@ export default function Localization() {
6667
7144
  const s = reactive({ lang: 'en' });
6668
7145
  const toggle = () => {
6669
7146
  s.lang = s.lang === 'en' ? 'tr' : 'en';
6670
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
7147
+ void uiLocale.use(s.lang);
6671
7148
  };
6672
7149
  return (
6673
7150
  <>
@@ -6751,7 +7228,7 @@ TextArea uses the field tokens (`field.*`, see TextBox) and has none of its own:
6751
7228
 
6752
7229
  # NumberBox
6753
7230
 
6754
- > Editors · @motifx-community/ui 0.1.0-beta.0
7231
+ > Editors · @motifx-community/ui 0.1.0-beta.2
6755
7232
 
6756
7233
  A number field: arrow keys, PageUp / PageDown and spin buttons that repeat while held, bounds, a step without float noise, a format for display (currency, percent) and typing in the locale’s own way.
6757
7234
 
@@ -6963,7 +7440,7 @@ The names of the spin buttons and the range messages come from `uiLocale.strings
6963
7440
 
6964
7441
  ```tsx
6965
7442
  import { reactive } from '@motifx/core';
6966
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
7443
+ import { Button, uiLocale } from '@motifx-community/ui';
6967
7444
  import { kitTexts } from '../../../shared/kit-texts';
6968
7445
 
6969
7446
  /** Switches the names of the spin buttons and the range messages. */
@@ -6972,7 +7449,7 @@ export default function Localization() {
6972
7449
 
6973
7450
  const toggle = () => {
6974
7451
  s.lang = s.lang === 'en' ? 'tr' : 'en';
6975
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
7452
+ void uiLocale.use(s.lang);
6976
7453
  };
6977
7454
 
6978
7455
  return (
@@ -7064,7 +7541,7 @@ export default function Localization() {
7064
7541
 
7065
7542
  # DateBox
7066
7543
 
7067
- > Editors · @motifx-community/ui 0.1.0-beta.0
7544
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7068
7545
 
7069
7546
  A date, a time or both. It is typed in the order of the locale through a mask, or picked from a calendar and a list of times; `min`, `max` and `disabledDates` limit both ways.
7070
7547
 
@@ -7210,14 +7687,14 @@ Button names and messages come from `uiLocale.strings`; dates and names from `lo
7210
7687
 
7211
7688
  ```tsx
7212
7689
  import { reactive } from '@motifx/core';
7213
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
7690
+ import { Button, uiLocale } from '@motifx-community/ui';
7214
7691
 
7215
7692
  /** Switches the button names and messages of every date box on the page. */
7216
7693
  export default function Localization() {
7217
7694
  const s = reactive({ lang: 'en' });
7218
7695
  const toggle = () => {
7219
7696
  s.lang = s.lang === 'en' ? 'tr' : 'en';
7220
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
7697
+ void uiLocale.use(s.lang);
7221
7698
  };
7222
7699
  return <Button text={() => (s.lang === 'en' ? 'Language: English' : 'Dil: Türkçe')} variant="outline" onclick={toggle} />;
7223
7700
  }
@@ -7265,11 +7742,207 @@ export default function Localization() {
7265
7742
  The date helpers are shared: `datePatternOf(locale, kind)`, `dateToDigits`, `digitsToDate`.
7266
7743
 
7267
7744
 
7745
+ ---
7746
+
7747
+ # DateRangeBox
7748
+
7749
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7750
+
7751
+ A start and an end date in one field: typed through two masks, or picked on two months side by side, from ready-made ranges, within the dates and the span allowed. The value is a `[start, end]` pair.
7752
+
7753
+ ## Import
7754
+
7755
+ ```tsx
7756
+ import { DateRangeBox, type DateRange } from '@motifx-community/ui';
7757
+ ```
7758
+
7759
+ ## From JSX and from code
7760
+
7761
+ ```tsx
7762
+ import { reactive } from '@motifx/core';
7763
+ import { Button, DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
7764
+
7765
+ const say = (d: Date | null) => (d ? d.toLocaleDateString('en-GB') : '—');
7766
+
7767
+ /** A range bound with x-model, and one made from code and read through its properties. */
7768
+ export default function FromCode() {
7769
+ const s = reactive({ stay: [new Date(2026, 2, 10), new Date(2026, 2, 14)] as DateRange, told: '' });
7770
+ const coded = new DateRangeBox({ label: 'Report period', clearButton: true, onValueChanged: e => (s.told = `${say(e.value[0])} to ${say(e.value[1])}`) });
7771
+
7772
+ return (
7773
+ <Stack gap="md">
7774
+ <Stack orientation="horizontal" wrap align="center">
7775
+ <DateRangeBox label="Stay" x-model={() => s.stay} clearButton />
7776
+ <output class="dr-stay">{() => `${say(s.stay[0])} to ${say(s.stay[1])}`}</output>
7777
+ </Stack>
7778
+ <Stack orientation="horizontal" wrap align="center">
7779
+ <span onConfig={c => c.controls.add(coded)} />
7780
+ <Button text="This week" variant="outline" onclick={() => (coded.value = [new Date(2026, 2, 16), new Date(2026, 2, 22)])} />
7781
+ <output class="dr-told">{() => s.told}</output>
7782
+ </Stack>
7783
+ </Stack>
7784
+ );
7785
+ }
7786
+ ```
7787
+
7788
+ ## Presets
7789
+
7790
+ `presets` puts ready-made ranges beside the calendars: `true` for the kit’s, or your own, each made when it is chosen. `calendars={1}` shows one month.
7791
+
7792
+ ```tsx
7793
+ import { reactive } from '@motifx/core';
7794
+ import { DateRangeBox, Stack, type DateRange, type DateRangePreset } from '@motifx-community/ui';
7795
+
7796
+ const day = (offset: number) => {
7797
+ const d = new Date();
7798
+ d.setHours(0, 0, 0, 0);
7799
+ d.setDate(d.getDate() + offset);
7800
+ return d;
7801
+ };
7802
+
7803
+ // Ranges of our own, made when chosen so they are about today.
7804
+ const QUARTERS: DateRangePreset[] = [
7805
+ { text: 'Next 3 days', range: () => [day(0), day(2)] },
7806
+ { text: 'Next week', range: () => [day(1), day(7)] },
7807
+ { text: 'Next 90 days', range: () => [day(0), day(89)] }
7808
+ ];
7809
+
7810
+ /** The kit's presets beside the calendars, and presets of your own. */
7811
+ export default function Presets() {
7812
+ const s = reactive({ sales: [null, null] as DateRange, plan: [null, null] as DateRange });
7813
+ return (
7814
+ <Stack orientation="horizontal" wrap align="center">
7815
+ <DateRangeBox label="Sales period" presets x-model={() => s.sales} />
7816
+ <DateRangeBox label="Planning" presets={QUARTERS} calendars={1} x-model={() => s.plan} />
7817
+ </Stack>
7818
+ );
7819
+ }
7820
+ ```
7821
+
7822
+ ## Limits
7823
+
7824
+ `min`, `max` and `disabledDates` bound both ends, typed or picked; `minDays` and `maxDays` bound the span, and the calendars offer only the days within while the end is being picked. A failed rule says which.
7825
+
7826
+ ```tsx
7827
+ import { reactive } from '@motifx/core';
7828
+ import { Button, DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
7829
+
7830
+ const today = new Date();
7831
+ const inMonths = (n: number) => new Date(today.getFullYear(), today.getMonth() + n, today.getDate());
7832
+
7833
+ /** A stay of one to fourteen nights, within the next six months, never starting on a Sunday; the message says which rule failed. */
7834
+ export default function Limits() {
7835
+ const s = reactive({ stay: [null, null] as DateRange, told: '' });
7836
+ let box!: DateRangeBox;
7837
+ return (
7838
+ <Stack orientation="horizontal" wrap align="center">
7839
+ <DateRangeBox
7840
+ ref={(b: DateRangeBox) => (box = b)}
7841
+ label="Stay"
7842
+ min={today}
7843
+ max={inMonths(6)}
7844
+ minDays={1}
7845
+ maxDays={14}
7846
+ disabledDates={d => d.getDay() === 0}
7847
+ required
7848
+ x-model={() => s.stay}
7849
+ />
7850
+ <Button text="Check" variant="outline" onclick={() => void box.validate().then(ok => (s.told = ok ? 'Fine.' : box.validationMessage))} />
7851
+ <output class="dr-check">{() => s.told}</output>
7852
+ </Stack>
7853
+ );
7854
+ }
7855
+ ```
7856
+
7857
+ ## With a time, and in another locale
7858
+
7859
+ ```tsx
7860
+ import { reactive } from '@motifx/core';
7861
+ import { DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
7862
+
7863
+ /** Date and time on both ends: the time is typed after the date, the calendars keep it; one box in Turkish. */
7864
+ export default function DateTime() {
7865
+ const s = reactive({ shift: [new Date(2026, 2, 10, 8, 30), new Date(2026, 2, 10, 17, 0)] as DateRange, trip: [null, null] as DateRange });
7866
+ return (
7867
+ <Stack orientation="horizontal" wrap align="center">
7868
+ <DateRangeBox label="Shift" type="datetime" x-model={() => s.shift} displayFormat={{ dateStyle: 'short', timeStyle: 'short' }} />
7869
+ <DateRangeBox label="Seyahat" locale="tr-TR" showWeekNumbers x-model={() => s.trip} startPlaceholder="gidiş" endPlaceholder="dönüş" />
7870
+ </Stack>
7871
+ );
7872
+ }
7873
+ ```
7874
+
7875
+ ## Behaviour
7876
+
7877
+ | Topic | How |
7878
+ | --- | --- |
7879
+ | `Typing` | Each side is a masked input in the locale’s order (`22.11.2006`); a whole, real date is taken as it is finished, an emptied side becomes `null`. Tab moves from the start to the end. |
7880
+ | `Picking` | On the popup the first pick is the start, the second the end: an earlier second pick becomes the start. With both chosen, the next pick starts a new range. While the end is being picked, the pointer shows the range it would make. |
7881
+ | `Two months` | The calendars show the start’s month and the next; paging one pages the other with it. |
7882
+ | `Presets` | A list beside the calendars; a press takes the range and closes. |
7883
+ | `Keyboard` | Alt+Down opens the popup; in it the calendars take the arrow keys, Enter picks; Escape closes, and clears the field when `clearButton` is on and the popup is closed. |
7884
+
7885
+ ## Accessibility
7886
+
7887
+ | Topic | How |
7888
+ | --- | --- |
7889
+ | `Inputs` | Two text boxes named “<label>, Start date” and “<label>, End date” in the kit language; the field’s label marks the start. |
7890
+ | `Popup` | A dialog named “Choose date”; the calendars are the kit’s grids, the presets a list box. |
7891
+ | `Messages` | The rules speak in the kit language; a rule of your own in yours. |
7892
+
7893
+ ## Styling
7894
+
7895
+ | Hook | What it is |
7896
+ | --- | --- |
7897
+ | `.mx-date-range-box` | The field. `data-type`. |
7898
+ | `.mx-date-range-box__start, .mx-date-range-box__end, .mx-date-range-box__separator` | The inputs and the glyph between them. |
7899
+ | `.mx-date-range-box__toggle, .mx-date-range-box__clear` | The buttons in the box. |
7900
+ | `.mx-date-range-box__popup, .mx-date-range-box__calendar, .mx-date-range-box__presets` | The popup, each calendar, the presets. |
7901
+
7902
+ ### Component tokens
7903
+
7904
+ | Token | What it sets |
7905
+ | --- | --- |
7906
+ | `date-range-box.separator, .presets` | Units: the glyph between the inputs (`icon`, `bg`), the list of presets (`focus`, `beside`). |
7907
+ | `date-range-box.calendar` | Place: a calendar on the popup. |
7908
+ | `date-range-box.popup-gap` | Between the calendars and the presets. |
7909
+ | `calendar.cell range-start, range-end, range-single, range-in` | The calendar’s cells in a range: its ends and the days between, drawn by each language. |
7910
+
7911
+ ## API reference
7912
+
7913
+ ### Props
7914
+
7915
+ | Prop | Type | Default | Description |
7916
+ | --- | --- | --- | --- |
7917
+ | `value` | `Bind<DateRange>` | `[null, null]` | The `[start, end]` pair; either `null` while not chosen. `x-model` binds it two-way. |
7918
+ | `type` | `Bind<'date' \| 'datetime'>` | `'date'` | With `datetime` the time is typed after the date; the calendars keep it. |
7919
+ | `min, max, disabledDates` | `Bind<Date \| null>`, `Bind<(d: Date) => boolean>` | — | The dates allowed, on both ends, typed or picked. |
7920
+ | `minDays, maxDays` | `Bind<number \| null>` | `null` | The least and the most days a range may span, the end counted from the start; while the end is picked the calendars offer only days within. |
7921
+ | `presets` | `Bind<readonly DateRangePreset[] \| boolean>` | `false` | `true`: the kit’s ready-made ranges beside the calendars (today, yesterday, the last 7 and 30 days, this and last month); your own as `{ text, range: () => DateRange }`. |
7922
+ | `calendars` | `Bind<1 \| 2>` | `2` | Months side by side on the popup; two stay a month apart as one is paged. |
7923
+ | `closeOnComplete` | `Bind<boolean>` | `true` | The popup closes once both ends are picked. |
7924
+ | `locale, displayFormat, firstDayOfWeek, showWeekNumbers, showSeconds` | | | As on the `DateBox`. |
7925
+ | `startPlaceholder, endPlaceholder` | `Bind<string>` | `''` | Shown in an empty box. |
7926
+ | `clearButton, showPickerButton` | `Bind<boolean>` | `false`, `true` | The clear button; the button that opens the calendars. |
7927
+ | `label, helpText, required, rules, readOnly, size, variant…` | | | The field props, as on every editor. |
7928
+
7929
+ ### Events, properties and methods
7930
+
7931
+ | Member | Kind | Description |
7932
+ | --- | --- | --- |
7933
+ | `startDate, endDate` | `Date \| null` | The ends as properties of their own. |
7934
+ | `inputElement, endInputElement` | read-only | The start’s and the end’s inputs. |
7935
+ | `open(), close(), opened` | `boolean` / `void` | The popup with the calendars; `onOpened`, `onClosed`. |
7936
+ | `clear()` | `void` | Empties both ends. |
7937
+ | `validate(), validationMessage, isValid` | | As on every field: an unfinished date, a date outside `min`, `max` or `disabledDates`, a start after the end, a span under `minDays` or over `maxDays`. |
7938
+ | `onValueChanged` | event | The pair changed (`value`, `previousValue`, `byUser`). |
7939
+
7940
+
7268
7941
  ---
7269
7942
 
7270
7943
  # ColorBox and ColorPicker
7271
7944
 
7272
- > Editors · @motifx-community/ui 0.1.0-beta.0
7945
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7273
7946
 
7274
7947
  A colour as a field, with a picker in a popup; or the picker on its own. The picker has an area of saturation and brightness, a hue strip, an opacity strip, inputs for the channels and preset colours.
7275
7948
 
@@ -7426,7 +8099,7 @@ export default function Buttons() {
7426
8099
 
7427
8100
  # Calendar
7428
8101
 
7429
- > Editors · @motifx-community/ui 0.1.0-beta.0
8102
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7430
8103
 
7431
8104
  A month of days to pick a date from, with a year and a decade view to get far quickly. It is the picker of DateBox, and it works on its own.
7432
8105
 
@@ -7566,7 +8239,7 @@ export default function Views() {
7566
8239
 
7567
8240
  # Slider
7568
8241
 
7569
- > Editors · @motifx-community/ui 0.1.0-beta.0
8242
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7570
8243
 
7571
8244
  A value picked on a track by dragging a thumb or with the keys: one number, or a range with two thumbs. Steps, marks with labels, a value bubble, a vertical form and number formatting, with the label, help line and validation every field has.
7572
8245
 
@@ -7813,7 +8486,7 @@ The names of the two thumbs of a range come from `uiLocale.strings` (`minimum`,
7813
8486
 
7814
8487
  ```tsx
7815
8488
  import { reactive } from '@motifx/core';
7816
- import { Button, enStrings, Slider, trStrings, uiLocale } from '@motifx-community/ui';
8489
+ import { Button, Slider, uiLocale } from '@motifx-community/ui';
7817
8490
  import { kitTexts } from '../../../shared/kit-texts';
7818
8491
 
7819
8492
  /** Switches the names of the thumbs; the price slider writes its numbers in the chosen language. */
@@ -7821,7 +8494,7 @@ export default function Localization() {
7821
8494
  const s = reactive({ lang: 'en' });
7822
8495
  const toggle = () => {
7823
8496
  s.lang = s.lang === 'en' ? 'tr' : 'en';
7824
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
8497
+ void uiLocale.use(s.lang);
7825
8498
  };
7826
8499
  return (
7827
8500
  <>
@@ -7931,7 +8604,7 @@ export default function Localization() {
7931
8604
 
7932
8605
  # Rating
7933
8606
 
7934
- > Editors · @motifx-community/ui 0.1.0-beta.0
8607
+ > Editors · @motifx-community/ui 0.1.0-beta.2
7935
8608
 
7936
8609
  A row of stars to give a score or to show one, whole or by halves. It is a field: label, help text, rules and `x-model` work as in every field.
7937
8610
 
@@ -8055,11 +8728,216 @@ export default function Icons() {
8055
8728
  | `label, helpText, readOnly, required, rules, size…` | see Field | | Everything a field has: a rating is one. |
8056
8729
 
8057
8730
 
8731
+ ---
8732
+
8733
+ # FileUploader
8734
+
8735
+ > Editors · @motifx-community/ui 0.1.0-beta.2
8736
+
8737
+ Files chosen with a button or dropped on the box, listed with their size and what happens to them: uploaded as they come, on a button or from code, with progress, cancel, retry and remove on each. Files outside the limits are listed with the reason.
8738
+
8739
+ ## Import
8740
+
8741
+ ```tsx
8742
+ import { FileUploader } from '@motifx-community/ui';
8743
+ ```
8744
+
8745
+ ## Choosing, dropping, uploading
8746
+
8747
+ `upload` is your own way to send a file: report progress, stop on the signal, resolve to the response. With `uploadUrl` instead, the uploader sends the file itself, in one piece or in chunks (`chunkSize`).
8748
+
8749
+ ```tsx
8750
+ import { reactive } from '@motifx/core';
8751
+ import { FileUploader, Stack } from '@motifx-community/ui';
8752
+
8753
+ // Stands in for a server: takes two seconds per megabyte, reports as it goes, stops on the signal.
8754
+ const send = (file: File, report: (fraction: number) => void, signal: AbortSignal) =>
8755
+ new Promise<string>((resolve, reject) => {
8756
+ const steps = 20;
8757
+ const wait = Math.max(600, Math.min(4000, (file.size / 1_000_000) * 2000)) / steps;
8758
+ let step = 0;
8759
+ const timer = setInterval(() => {
8760
+ step++;
8761
+ report(step / steps);
8762
+ if (step === steps) {
8763
+ clearInterval(timer);
8764
+ resolve(`id-${file.name}`);
8765
+ }
8766
+ }, wait);
8767
+ signal.addEventListener('abort', () => {
8768
+ clearInterval(timer);
8769
+ reject(new Error('stopped'));
8770
+ });
8771
+ });
8772
+
8773
+ /** Files chosen or dropped go up as they come, through your own upload; each row shows progress, cancel, retry, remove. */
8774
+ export default function Basic() {
8775
+ const s = reactive({ files: [] as readonly File[], told: '' });
8776
+ return (
8777
+ <Stack gap="md" style="inline-size: 100%">
8778
+ <FileUploader
8779
+ label="Attachments"
8780
+ helpText="Any files; a stand-in server takes them."
8781
+ upload={send}
8782
+ x-model={() => s.files}
8783
+ onUploaded={e => (s.told = `${e.file.name} is up as ${String(e.item.response)}.`)}
8784
+ onUploadAborted={e => (s.told = `${e.file.name} was stopped.`)}
8785
+ />
8786
+ <output class="fu-told">{() => s.told || `${s.files.length} file(s) taken`}</output>
8787
+ </Stack>
8788
+ );
8789
+ }
8790
+ ```
8791
+
8792
+ ## Limits
8793
+
8794
+ ```tsx
8795
+ import { reactive } from '@motifx/core';
8796
+ import { FileUploader, Stack } from '@motifx-community/ui';
8797
+
8798
+ /** Only pictures and PDFs, up to 2 MB each and three in all; a file outside is listed with the reason. */
8799
+ export default function Limits() {
8800
+ const s = reactive({ files: [] as readonly File[], refused: '' });
8801
+ return (
8802
+ <Stack gap="md" style="inline-size: 100%">
8803
+ <FileUploader
8804
+ label="Documents"
8805
+ accept=".pdf,image/*"
8806
+ maxFileSize={2_000_000}
8807
+ maxFiles={3}
8808
+ required
8809
+ x-model={() => s.files}
8810
+ onFilesAdded={e => (s.refused = e.refused.length ? e.refused.map(r => r.message).join(' ') : '')}
8811
+ />
8812
+ <output class="fu-refused">{() => s.refused}</output>
8813
+ </Stack>
8814
+ );
8815
+ }
8816
+ ```
8817
+
8818
+ ## When files go up
8819
+
8820
+ ```tsx
8821
+ import { reactive } from '@motifx/core';
8822
+ import { Button, FileUploader, Stack } from '@motifx-community/ui';
8823
+
8824
+ const quick = (file: File, report: (fraction: number) => void) =>
8825
+ new Promise<void>(resolve => {
8826
+ let step = 0;
8827
+ const timer = setInterval(() => {
8828
+ report(++step / 10);
8829
+ if (step === 10) {
8830
+ clearInterval(timer);
8831
+ resolve();
8832
+ }
8833
+ }, 120);
8834
+ });
8835
+
8836
+ /** An Upload button sends what was chosen; or nothing goes until code says so. One file only, no dropping. */
8837
+ export default function Modes() {
8838
+ const s = reactive({ one: [] as readonly File[] });
8839
+ let manual!: FileUploader;
8840
+ return (
8841
+ <Stack gap="md" style="inline-size: 100%">
8842
+ <FileUploader label="Photo" multiple={false} allowDrop={false} accept="image/*" upload={quick} uploadMode="button" x-model={() => s.one} />
8843
+ <Stack orientation="horizontal" wrap align="center">
8844
+ <FileUploader ref={(u: FileUploader) => (manual = u)} label="Logs" accept=".log,.txt" upload={quick} uploadMode="manual" />
8845
+ <Button text="Send the logs" variant="outline" onclick={() => void manual.upload()} />
8846
+ </Stack>
8847
+ </Stack>
8848
+ );
8849
+ }
8850
+ ```
8851
+
8852
+ ## Sending to a server
8853
+
8854
+ The uploader posts a form with the file in `uploadField` (`file` by default) to `uploadUrl`, with `uploadHeaders`; a 2xx answer is the item’s `response`, JSON parsed when it is JSON. With `chunkSize` each piece carries `Content-Range` and the fields `chunkIndex` and `chunkCount`.
8855
+
8856
+ ```tsx
8857
+ <FileUploader
8858
+ label="Attachments"
8859
+ uploadUrl="/api/files"
8860
+ uploadHeaders={{ Authorization: 'Bearer ' + token }}
8861
+ chunkSize={1_000_000}
8862
+ onUploaded={(e) => this.attachments.push(e.item.response as Attachment)}
8863
+ />
8864
+ ```
8865
+
8866
+ ## Behaviour
8867
+
8868
+ | Topic | How |
8869
+ | --- | --- |
8870
+ | `Choosing` | The button opens the file dialog; files may be dropped on the box too, which lights up while they are over it. |
8871
+ | `Refusing` | A file outside `accept`, the sizes or `maxFiles` is listed as refused with the reason, and is not in the value. |
8872
+ | `Uploading` | As chosen, on the Upload button, or from code. A row shows the progress and a Cancel button meanwhile; afterwards “Uploaded”, or the failure with Retry. The server’s answer is the item’s `response` (JSON parsed). |
8873
+ | `Chunks` | With `chunkSize` the file goes in pieces, each a request with `Content-Range: bytes start-end/total`; progress runs over the whole. |
8874
+ | `Removing` | Each row has a remove button; a running upload is stopped first. |
8875
+
8876
+ ## Accessibility
8877
+
8878
+ | Topic | How |
8879
+ | --- | --- |
8880
+ | `Button` | The select button is the field’s control: the label marks it, Space and Enter open the dialog. |
8881
+ | `List` | A list of rows: the name, the size and the state as text; the progress bar named after the file; the buttons named “Cancel the upload of …”, “Retry”, “Remove …”. |
8882
+ | `Messages` | The reasons a file was refused and the failures speak in the kit language, or in the server’s words. |
8883
+
8884
+ ## Styling
8885
+
8886
+ | Hook | What it is |
8887
+ | --- | --- |
8888
+ | `.mx-file-uploader` | The field. `data-dragover` while files are over it. |
8889
+ | `.mx-file-uploader__select, .mx-file-uploader__drop, .mx-file-uploader__upload` | The select button, the hint, the Upload button. |
8890
+ | `.mx-file-uploader__list, .mx-file-uploader__item` | The list and each row. `data-status` on the row. |
8891
+ | `.mx-file-uploader__icon, __name, __size, __state, __progress, __actions, __action` | The parts of a row. |
8892
+
8893
+ ### Component tokens
8894
+
8895
+ | Token | What it sets |
8896
+ | --- | --- |
8897
+ | `file-uploader.over, .select, .upload, .hint, .list, .item, .icon, .name, .size, .state` | Units: the box with files over it, the two buttons (`hover`, `pressed`, `focus`, `disabled`), the hint, the list, a row per status, the file glyph, the texts. |
8898
+ | `file-uploader.field, .action` | Places: the field’s box as a drop zone (a dashed frame, its corners, its padding); the row’s buttons. |
8899
+ | `file-uploader.box-gap, .button-gap, .item-gap` | The spaces in the box, in a button and in a row. |
8900
+
8901
+ ## API reference
8902
+
8903
+ ### Props
8904
+
8905
+ | Prop | Type | Default | Description |
8906
+ | --- | --- | --- | --- |
8907
+ | `value` | `Bind<readonly File[]>` | `[]` | The files taken (the refused ones are not in it). `x-model` binds it two-way. |
8908
+ | `multiple` | `Bind<boolean>` | `true` | Several files at once; `false` keeps one, the newest. |
8909
+ | `accept` | `Bind<string>` | `''` | What may be chosen, as for `<input type="file">`: `.png,.jpg`, `image/*`, `application/pdf`. |
8910
+ | `maxFileSize, minFileSize` | `Bind<number \| null>` | `null` | Bytes. A file outside is listed as refused, with the reason. |
8911
+ | `maxFiles` | `Bind<number \| null>` | `null` | How many files may be taken in all. |
8912
+ | `allowDrop` | `Bind<boolean>` | `true` | Files may be dropped on the box. |
8913
+ | `uploadMode` | `Bind<UploadMode>` | `instant` / `manual` | `instant`: as chosen; `button`: an Upload button; `manual`: `upload()` from code. Default `instant` with `uploadUrl` or `upload`, else `manual`. |
8914
+ | `uploadUrl, uploadMethod, uploadHeaders, uploadField` | `Bind<string \| null>`, … | `null`, `POST`, `null`, `file` | Where and how the uploader itself sends a file (XMLHttpRequest, with progress), as a form with the file in `uploadField`. |
8915
+ | `chunkSize` | `Bind<number \| null>` | `null` | Bytes per request: the file goes in pieces, each with its `Content-Range` and `chunkIndex` / `chunkCount` fields; the last answer is the response. |
8916
+ | `upload` | `(file, report, signal) => Promise<unknown>` | — | Your own upload instead of `uploadUrl`: call `report(0…1)` as it goes, stop on `signal`; what it resolves to is the response. |
8917
+ | `selectText, dropText, uploadText` | `Bind<string>` | the kit’s | The button, the hint beside it, the Upload button. |
8918
+ | `showFileList` | `Bind<boolean>` | `true` | The list of files under the box. |
8919
+ | `label, helpText, required, rules, readOnly, size, variant…` | | | The field props, as on every editor. |
8920
+
8921
+ ### Events, properties and methods
8922
+
8923
+ | Member | Kind | Description |
8924
+ | --- | --- | --- |
8925
+ | `items` | read-only | Every file in the list with what happened to it: `file`, `status` (`ready`, `uploading`, `done`, `error`, `aborted`, `invalid`), `progress`, `response`, `message`. |
8926
+ | `isUploading` | read-only | An upload is running. |
8927
+ | `openDialog()` | `void` | Opens the browser’s file dialog, as the button does. |
8928
+ | `addFiles(files)` | `void` | Takes files as if chosen: the limits apply, `onFilesAdded` is asked, uploads start as the mode says. |
8929
+ | `upload(item?)` | `Promise<void>` | Uploads the files waiting, or one of them; what `manual` mode calls. |
8930
+ | `abort(item?), remove(item), clear()` | `void` | Stops an upload (the file stays, cancelled); takes a file out; takes every file out. |
8931
+ | `onFilesAdded` | event | Files were chosen or dropped (`files`, `refused`); `cancel = true` takes none. |
8932
+ | `onFileRemoved, onUploadStarted, onProgress, onUploaded, onUploadError, onUploadAborted` | event | One file’s way through: each with `item` and `file`, a failure with `error`. |
8933
+ | `onValueChanged` | event | The files taken changed. |
8934
+
8935
+
8058
8936
  ---
8059
8937
 
8060
8938
  # CheckBox
8061
8939
 
8062
- > Choice · @motifx-community/ui 0.1.0-beta.0
8940
+ > Choice · @motifx-community/ui 0.1.0-beta.2
8063
8941
 
8064
8942
  A checkbox with its caption: checked, unchecked or indeterminate, three states on request, read-only, required and checked with its group. A native checkbox underneath, drawn from the design tokens.
8065
8943
 
@@ -8303,7 +9181,7 @@ The checkbox writes no text of its own; the `required` message comes from `uiLoc
8303
9181
 
8304
9182
  ```tsx
8305
9183
  import { reactive } from '@motifx/core';
8306
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
9184
+ import { Button, uiLocale } from '@motifx-community/ui';
8307
9185
  import { kitTexts } from '../../../shared/kit-texts';
8308
9186
 
8309
9187
  /** Switches the texts of every field on the page; a required message already shown follows too. */
@@ -8311,7 +9189,7 @@ export default function Localization() {
8311
9189
  const s = reactive({ lang: 'en' });
8312
9190
  const toggle = () => {
8313
9191
  s.lang = s.lang === 'en' ? 'tr' : 'en';
8314
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
9192
+ void uiLocale.use(s.lang);
8315
9193
  };
8316
9194
  return (
8317
9195
  <>
@@ -8399,7 +9277,7 @@ export default function Localization() {
8399
9277
 
8400
9278
  # Switch
8401
9279
 
8402
- > Choice · @motifx-community/ui 0.1.0-beta.0
9280
+ > Choice · @motifx-community/ui 0.1.0-beta.2
8403
9281
 
8404
9282
  An on / off switch with its caption: a track with a thumb that slides, an optional on / off text inside or next to it, read-only and required. A native checkbox with the switch role underneath.
8405
9283
 
@@ -8645,7 +9523,7 @@ The switch writes no text of its own: `onText` and `offText` are yours, and can
8645
9523
 
8646
9524
  # RadioGroup
8647
9525
 
8648
- > Choice · @motifx-community/ui 0.1.0-beta.0
9526
+ > Choice · @motifx-community/ui 0.1.0-beta.2
8649
9527
 
8650
9528
  A set of options of which one is chosen: from plain values, from your own objects or from a live list; one under the other, side by side or in columns; options that are disabled, hidden or carry a help line; one Tab stop and the arrow keys.
8651
9529
 
@@ -8973,7 +9851,7 @@ The group writes no text of its own: the option texts are yours (functions of yo
8973
9851
 
8974
9852
  # DropDown
8975
9853
 
8976
- > Choice · @motifx-community/ui 0.1.0-beta.0
9854
+ > Choice · @motifx-community/ui 0.1.0-beta.2
8977
9855
 
8978
9856
  Picks one item from a list. The field shows the chosen item; the list opens below it with the keyboard or a press, can be searched, grouped and drawn your way, and stays fast with thousands of items.
8979
9857
 
@@ -9121,21 +9999,22 @@ export const cities = ['Ankara', 'Antalya', 'Bursa', 'İstanbul', 'İzmir', 'Kon
9121
9999
  | `Groups` | Each group is `role="group"` named by its header. |
9122
10000
  | `Long lists` | Only the rows in view are drawn; each option says where it is with `aria-posinset` and `aria-setsize`. |
9123
10001
  | `Search` | The search box controls the list and names the highlighted option the same way. |
10002
+ | `Waiting` | While the value's item is asked for, the combobox is `aria-busy` and its text says "Loading…" to screen readers; a key the source does not have carries the reason as its title. |
9124
10003
 
9125
10004
  ## Localization
9126
10005
 
9127
- The search box, the clear button and the empty list text come from `uiLocale.strings`.
10006
+ The search box, the clear button, the empty list text, the wait (`loading`) and the reason a key is marked (`notInList`, `loadFailed`) come from `uiLocale.strings`.
9128
10007
 
9129
10008
  ```tsx
9130
10009
  import { reactive } from '@motifx/core';
9131
- import { Button, DropDown, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
10010
+ import { Button, DropDown, uiLocale } from '@motifx-community/ui';
9132
10011
 
9133
10012
  /** Switches the texts of every drop-down on the page: the search box, the clear button, the empty list. */
9134
10013
  export default function Localization() {
9135
10014
  const s = reactive({ lang: 'en' });
9136
10015
  const toggle = () => {
9137
10016
  s.lang = s.lang === 'en' ? 'tr' : 'en';
9138
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
10017
+ void uiLocale.use(s.lang);
9139
10018
  };
9140
10019
  return (
9141
10020
  <>
@@ -9150,8 +10029,9 @@ export default function Localization() {
9150
10029
 
9151
10030
  | Hook | What it is |
9152
10031
  | --- | --- |
9153
- | `.mx-drop-down` | Added to the field. `data-open` while the list is open; the field attributes of TextBox. |
9154
- | `.mx-drop-down__display, .mx-drop-down__text, .mx-drop-down__chevron` | The combobox, the chosen text (`data-placeholder` when empty), the arrow. |
10032
+ | `.mx-drop-down` | Added to the field. `data-open` while the list is open, `data-loading` while the value's item is asked for; the field attributes of TextBox. |
10033
+ | `.mx-drop-down__display, .mx-drop-down__text, .mx-drop-down__chevron` | The combobox, the chosen text (`data-placeholder` when empty, `data-missing` for a key the source does not have), the arrow. |
10034
+ | `.mx-drop-down__spinner` | The spinner in the arrow's place while the value's item is asked for. |
9155
10035
  | `.mx-drop-down__popup, .mx-drop-down__search` | The popup and its search box. |
9156
10036
  | `.mx-list, .mx-list__item, .mx-list__header` | The list (shared), its options (`data-active`, `data-selected`) and group headers. |
9157
10037
 
@@ -9160,6 +10040,7 @@ export default function Localization() {
9160
10040
  | Token | What it sets |
9161
10041
  | --- | --- |
9162
10042
  | `field.*` | The field, as for TextBox. |
10043
+ | `drop-down.value, drop-down.chevron, drop-down.spinner, drop-down.spinner-shape` | Units: the chosen text (`placeholder`, `missing`, `disabled`), the arrow (`open`, `disabled`), the ring that turns while the value's item is asked for and the shape a language may draw instead (with the spinner's shapes and timing). |
9163
10044
  | `list.item-height, list.item` | The options: their row height, and the item unit in each state (`hover`, `pressed`, `active`, `selected`, `selected-hover`, `selected-pressed`, `disabled`, `next`, `select-all`). |
9164
10045
  | `list.indicator, list.check, list.mark, list.icon, list.text` | Units: the bar on the chosen option (`multiple`), the check of a list of several choices and its mark, an icon, the text. |
9165
10046
  | `list.container, list.group, list.header, list.select-all-divider, list.empty` | Units: the list (its space and most height), a group, group headers, the line under "Select all", the empty text. |
@@ -9172,6 +10053,9 @@ export default function Localization() {
9172
10053
  | --- | --- | --- | --- |
9173
10054
  | `value` | `Bind<V \| null>` | `null` | The value of the chosen item. `x-model` binds it two-way. |
9174
10055
  | `items` | `Bind<readonly T[]>` | `[]` | Plain values, `DropDownItem`s (`{ value, text, icon?, group?, enabled? }`) or objects of your own. A function is followed; items changed in place show after `refresh()`. |
10056
+ | `dataSource` | `Bind<DataSource<T> \| null>` | `null` | Items from the data layer, loaded where the list is scrolled to and searched on its `searchFields`. Wins over `items`. A value on no loaded page is asked for by key; meanwhile the field waits (see Lookup). |
10057
+ | `valueText` | `Bind<string>` | `''` | The value's text while its item is asked for from `dataSource`, shown at once instead of waiting (a record that carries the name: `valueText={() => order.customerName}`). |
10058
+ | `searchDelay` | `Bind<number>` | `250` with a data source, else `0` | Milliseconds between the last key in the search box and the search. |
9175
10059
  | `textField / valueField` | `Bind<ItemField<T>>` | `'text'` / `'value'` | A property name or a function `(item) => …`. Without `valueField` an object with a `value` gives that, anything else is its own value. |
9176
10060
  | `iconField, groupField, enabledField` | `Bind<ItemField<T>>` | — | An icon per option; options with the same group follow each other under its name; options that cannot be chosen. |
9177
10061
  | `placeholder` | `Bind<string>` | `''` | Shown while nothing is chosen. |
@@ -9197,7 +10081,7 @@ A prop whose value is a function of its own (`textField`, a template) takes the
9197
10081
 
9198
10082
  | Method | Returns | Description |
9199
10083
  | --- | --- | --- |
9200
- | `open(search?)` | `boolean` | Opens the list; `search` starts the search box with that text. `false` when disabled or read-only. |
10084
+ | `open(search?)` | `boolean` | Opens the list; `search` starts the search box with that text. `false` when disabled, read-only, or while the value's item is asked for. |
9201
10085
  | `close()` | `void` | Closes it; focus goes back to the field. |
9202
10086
  | `clear()` | `void` | Empties the value. |
9203
10087
  | `refresh()` | `void` | Your items may be plain or reactive; the drop-down reads them as they are. After changing them in place, call `refresh()`. The field's text and the open list follow. |
@@ -9294,7 +10178,7 @@ export default function Validation() {
9294
10178
 
9295
10179
  # ComboBox and Autocomplete
9296
10180
 
9297
- > Choice · @motifx-community/ui 0.1.0-beta.0
10181
+ > Choice · @motifx-community/ui 0.1.0-beta.2
9298
10182
 
9299
10183
  A text field with a list that follows what is typed. The items come from memory or from a data source of the data layer, searched on the server. `Autocomplete` is the free-text kind: the value is the text.
9300
10184
 
@@ -9512,7 +10396,7 @@ export default function CustomValues() {
9512
10396
 
9513
10397
  # Lookup
9514
10398
 
9515
- > Choice · @motifx-community/ui 0.1.0-beta.0
10399
+ > Choice · @motifx-community/ui 0.1.0-beta.2
9516
10400
 
9517
10401
  Picks one row of a table-like list, typically from a data source searched on the server: a customer by its company, contact and city. The field shows the chosen row's text; everything else works as in DropDown.
9518
10402
 
@@ -9545,6 +10429,29 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
9545
10429
  }
9546
10430
  ```
9547
10431
 
10432
+ ## A value on no loaded page
10433
+
10434
+ A value whose row is not loaded is asked for by key, in one request with the keys other fields and grids over the same source need at that moment. Meanwhile the field waits: a spinner in the arrow's place, the list closed, never the key as its text. A record that carries the name too gives it as `valueText`, and the field shows it at once. A key the server does not have shows itself, muted and underlined, and its title says why; when the request failed, opening the list asks again.
10435
+
10436
+ ```tsx
10437
+ import { data } from '@motifx-community/data';
10438
+
10439
+ /** Rows in memory that answer a little later, the way a server does; for the examples. */
10440
+ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
10441
+ constructor(
10442
+ options: data.ArrayAdapterOptions<T>,
10443
+ private readonly delayMs = 300,
10444
+ ) {
10445
+ super(options);
10446
+ }
10447
+
10448
+ override async load(options: data.LoadOptions = {}): Promise<data.LoadResult<T>> {
10449
+ await new Promise((done) => setTimeout(done, this.delayMs));
10450
+ return super.load(options);
10451
+ }
10452
+ }
10453
+ ```
10454
+
9548
10455
  ## API reference
9549
10456
 
9550
10457
  | Prop | Type | Default | Description |
@@ -9553,7 +10460,7 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
9553
10460
  | `showColumnHeaders` | `Bind<boolean>` | `true` | The header above the rows. |
9554
10461
  | `popupWidth` | `Bind<string>` | `lookup.popup-width` | The least width of the list. |
9555
10462
  | `searchEnabled` | `Bind<boolean>` | `true` | A search box above the list (DropDown has it off by default). |
9556
- | `everything of DropDown` | | | `items`, `dataSource`, `textField`, `valueField`, `searchDelay`, `clearButton`, validation, keyboard… |
10463
+ | `everything of DropDown` | | | `items`, `dataSource`, `valueText`, `textField`, `valueField`, `searchDelay`, `clearButton`, validation, keyboard… |
9557
10464
  | `refresh()` | | | Your items and columns may be plain or reactive; the lookup reads them as they are. After changing them in place, call `refresh()`. |
9558
10465
 
9559
10466
  ## Example files
@@ -9639,12 +10546,73 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
9639
10546
  }
9640
10547
  ```
9641
10548
 
10549
+ `ByKey.tsx`
10550
+
10551
+ ```tsx
10552
+ import { reactive } from '@motifx/core';
10553
+ import { data } from '@motifx-community/data';
10554
+ import { Button, Lookup } from '@motifx-community/ui';
10555
+ import { SlowAdapter } from '../../../shared/slow-adapter';
10556
+
10557
+ interface Customer {
10558
+ id: number;
10559
+ company: string;
10560
+ city: string;
10561
+ }
10562
+
10563
+ const companyOf = (id: number) => `${['Alfreds', 'Bon app', 'Ernst', 'Hanari', 'Island', 'Lehmanns'][id % 6]} ${['Trading', 'Handel', 'Markt', 'Foods'][id % 4]} ${id}`;
10564
+ const rows: Customer[] = Array.from({ length: 2000 }, (_, i) => ({ id: i + 1, company: companyOf(i + 1), city: ['Berlin', 'Paris', 'İstanbul', 'Madrid'][i % 4] }));
10565
+
10566
+ /** Values on no loaded page of a server that answers after 1.2 s: one field waits for its row, one shows the name its record carries, one has a key the server does not have. */
10567
+ export default function ByKey() {
10568
+ const customers = new data.DataSource<Customer, number>({
10569
+ adapter: new SlowAdapter<Customer, number>({ data: rows, key: 'id' }, 1200),
10570
+ loadMode: 'blocks',
10571
+ pageSize: 50,
10572
+ searchFields: ['company', 'city'],
10573
+ });
10574
+ const columns = [
10575
+ { field: 'company', caption: 'Company' },
10576
+ { field: 'city', caption: 'City', width: '7rem' },
10577
+ ];
10578
+ const waiting = reactive({ customer: 1500 as number | null });
10579
+ // A record as it came from the server: the customer's key and, beside it, the name.
10580
+ const order = reactive({ customer: 1500 as number | null, customerName: companyOf(1500) });
10581
+
10582
+ const another = () => {
10583
+ const id = 100 + Math.floor(Math.random() * 1900);
10584
+ waiting.customer = id;
10585
+ order.customer = id;
10586
+ order.customerName = companyOf(id);
10587
+ };
10588
+
10589
+ return (
10590
+ <>
10591
+ <Lookup class="lk-waits" label="Waits for its row" dataSource={customers} textField="company" valueField="id" columns={columns} x-model={() => waiting.customer} stretch />
10592
+ <Lookup
10593
+ class="lk-given"
10594
+ label="Shows the name it is given"
10595
+ dataSource={customers}
10596
+ textField="company"
10597
+ valueField="id"
10598
+ columns={columns}
10599
+ valueText={() => order.customerName}
10600
+ x-model={() => order.customer}
10601
+ stretch
10602
+ />
10603
+ <Lookup class="lk-missing" label="A key the server does not have" dataSource={customers} textField="company" valueField="id" columns={columns} value={9999} stretch />
10604
+ <Button class="lk-another" text="Another customer" variant="outline" onclick={another} />
10605
+ </>
10606
+ );
10607
+ }
10608
+ ```
10609
+
9642
10610
 
9643
10611
  ---
9644
10612
 
9645
10613
  # ProgressBar and Spinner
9646
10614
 
9647
- > Feedback · @motifx-community/ui 0.1.0-beta.0
10615
+ > Feedback · @motifx-community/ui 0.1.0-beta.2
9648
10616
 
9649
10617
  ProgressBar shows how far some work is, as a line or a circle, or that it runs when that is not known. Spinner says "busy, wait": a turning ring, alone or over a panel while it loads, shown only after a delay so quick work does not flash it.
9650
10618
 
@@ -9951,7 +10919,7 @@ A bar or a spinner without a label is named `uiLocale.strings.loading`. The perc
9951
10919
 
9952
10920
  ```tsx
9953
10921
  import { reactive } from '@motifx/core';
9954
- import { Button, enStrings, ProgressBar, trStrings, uiLocale } from '@motifx-community/ui';
10922
+ import { Button, ProgressBar, uiLocale } from '@motifx-community/ui';
9955
10923
  import { kitTexts } from '../../../shared/kit-texts';
9956
10924
 
9957
10925
  /** Switches the name of unlabelled bars and spinners, and the language the percent is written in. */
@@ -9959,7 +10927,7 @@ export default function Localization() {
9959
10927
  const s = reactive({ lang: 'en' });
9960
10928
  const toggle = () => {
9961
10929
  s.lang = s.lang === 'en' ? 'tr' : 'en';
9962
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
10930
+ void uiLocale.use(s.lang);
9963
10931
  };
9964
10932
  return (
9965
10933
  <>
@@ -10049,7 +11017,7 @@ export default function Localization() {
10049
11017
 
10050
11018
  # Tooltip
10051
11019
 
10052
- > Feedback · @motifx-community/ui 0.1.0-beta.0
11020
+ > Feedback · @motifx-community/ui 0.1.0-beta.2
10053
11021
 
10054
11022
  A short description shown next to an element: after the pointer rests on it, when it gets keyboard focus, or from code. It can be hovered, Escape hides it, and one is open at a time on the page.
10055
11023
 
@@ -10388,11 +11356,424 @@ export default function ManyElements() {
10388
11356
  | `onClosed` | It was hidden. |
10389
11357
 
10390
11358
 
11359
+ ---
11360
+
11361
+ # Popover
11362
+
11363
+ > Feedback · @motifx-community/ui 0.1.0-beta.2
11364
+
11365
+ Content next to the element it belongs to: a title, a close button, a form, a card. It opens on a press or while the pointer rests on its target, follows it, and points at it with an arrow where the design language has one.
11366
+
11367
+ ## Import
11368
+
11369
+ ```tsx
11370
+ import { Popover } from '@motifx-community/ui';
11371
+ ```
11372
+
11373
+ ## From JSX and from code
11374
+
11375
+ The JSX children are the content; `target` names the element or component it opens next to. From code, `content` gives the content and `open()`, `close()` and `toggle()` move it; `value` and `x-model` say whether it is open.
11376
+
11377
+ ```tsx
11378
+ import { reactive } from '@motifx/core';
11379
+ import { Button, Popover, Stack, TextBox } from '@motifx-community/ui';
11380
+
11381
+ /** A popover with a title, a close button and a small form; one made from code for a plain element. */
11382
+ export default function Basic() {
11383
+ const s = reactive({ open: false, name: 'Ada', saved: '' });
11384
+ let button!: Button;
11385
+ let link!: HTMLElement;
11386
+ const coded = new Popover({ title: 'From code', content: new Button({ text: 'OK', variant: 'outline', onclick: () => coded.close() }) });
11387
+
11388
+ return (
11389
+ <Stack orientation="horizontal" wrap align="center">
11390
+ <Button ref={(b: Button) => (button = b)} text="Rename" variant="outline" />
11391
+ <Popover target={() => button} title="New name" showClose x-model={() => s.open}>
11392
+ <Stack orientation="horizontal" wrap align="center">
11393
+ <TextBox label="Name" x-model={() => s.name} />
11394
+ <Button text="Save" tone="accent" onclick={() => ((s.saved = s.name), (s.open = false))} />
11395
+ </Stack>
11396
+ </Popover>
11397
+ <output class="po-saved">{() => (s.saved ? `Saved: ${s.saved}` : s.open ? 'Open' : 'Closed')}</output>
11398
+ <a
11399
+ href="#from-code"
11400
+ class="po-link"
11401
+ ref={(c: { element: HTMLElement }) => (link = c.element)}
11402
+ onclick={(e: Event) => {
11403
+ e.preventDefault();
11404
+ coded.target = link;
11405
+ coded.toggle();
11406
+ }}
11407
+ >
11408
+ A popover from code
11409
+ </a>
11410
+ </Stack>
11411
+ );
11412
+ }
11413
+ ```
11414
+
11415
+ ## While the pointer rests
11416
+
11417
+ `showOn: 'hover'` opens it after `delay` while the pointer rests on the target, and when the target has keyboard focus; the pointer may move onto the popover. It closes `hideDelay` after the pointer leaves both.
11418
+
11419
+ ```tsx
11420
+ import { Avatar, Popover, Stack } from '@motifx-community/ui';
11421
+
11422
+ /** A card that opens while the pointer rests on a name, or when the name has keyboard focus. */
11423
+ export default function Hover() {
11424
+ let name!: HTMLElement;
11425
+ return (
11426
+ <Stack orientation="horizontal" wrap align="center">
11427
+ <span>
11428
+ Reviewed by{' '}
11429
+ <a href="#ada" class="po-person" ref={(c: { element: HTMLElement }) => (name = c.element)} onclick={(e: Event) => e.preventDefault()}>
11430
+ Ada Lovelace
11431
+ </a>
11432
+ </span>
11433
+ <Popover target={() => name} showOn="hover" placement="top" label="Ada Lovelace">
11434
+ <Stack orientation="horizontal" align="center">
11435
+ <Avatar name="Ada Lovelace" size="lg" />
11436
+ <Stack>
11437
+ <strong>Ada Lovelace</strong>
11438
+ <span>Analytical Engine, Programs</span>
11439
+ </Stack>
11440
+ </Stack>
11441
+ </Popover>
11442
+ </Stack>
11443
+ );
11444
+ }
11445
+ ```
11446
+
11447
+ ## Placements, the arrow and a width
11448
+
11449
+ ```tsx
11450
+ import { reactive } from '@motifx/core';
11451
+ import { Button, CheckBox, Popover, Stack, type PopupPlacement } from '@motifx-community/ui';
11452
+
11453
+ const PLACEMENTS: PopupPlacement[] = ['top-start', 'top', 'top-end', 'start', 'end', 'bottom-start', 'bottom', 'bottom-end'];
11454
+
11455
+ /** Every placement; the arrow where the language draws one, and a width of its own. */
11456
+ export default function Placements() {
11457
+ const s = reactive({ arrow: true, placement: 'bottom' as PopupPlacement });
11458
+ let button!: Button;
11459
+ return (
11460
+ <Stack gap="md">
11461
+ <Stack orientation="horizontal" wrap align="center">
11462
+ {PLACEMENTS.map(placement => (
11463
+ <Button key={placement} text={placement} variant={() => (s.placement === placement ? 'solid' : 'outline')} size="sm" onclick={() => (s.placement = placement)} />
11464
+ ))}
11465
+ <CheckBox label="Arrow" x-model={() => s.arrow} />
11466
+ </Stack>
11467
+ <div style="display: flex; justify-content: center; padding: 3rem 0">
11468
+ <Button ref={(b: Button) => (button = b)} text="Open" />
11469
+ </div>
11470
+ <Popover target={() => button} placement={() => s.placement} arrow={() => s.arrow} width="16rem" label="Placement">
11471
+ <p>{() => `Placed at ${s.placement}; it moves to the other side when there is no room.`}</p>
11472
+ </Popover>
11473
+ </Stack>
11474
+ );
11475
+ }
11476
+ ```
11477
+
11478
+ ## Keeping it open
11479
+
11480
+ ```tsx
11481
+ import { reactive } from '@motifx/core';
11482
+ import { Button, Popover, Stack, TextArea } from '@motifx-community/ui';
11483
+
11484
+ /** A press outside does not close it, and onClosing keeps it open while there is unsaved text; Escape and the button close it. */
11485
+ export default function Events() {
11486
+ const s = reactive({ note: '', told: '' });
11487
+ let button!: Button;
11488
+ let pop!: Popover;
11489
+ return (
11490
+ <Stack orientation="horizontal" wrap align="center">
11491
+ <Button ref={(b: Button) => (button = b)} text="Add a note" variant="outline" />
11492
+ <Popover
11493
+ ref={(p: Popover) => (pop = p)}
11494
+ target={() => button}
11495
+ title="Note"
11496
+ closeOnOutside={false}
11497
+ onClosing={e => {
11498
+ if (e.reason === 'escape' && s.note.trim() !== '') {
11499
+ e.cancel = true;
11500
+ s.told = 'Save or clear the note first.';
11501
+ }
11502
+ }}
11503
+ onClosed={reason => (s.told = `Closed: ${String(reason)}`)}
11504
+ >
11505
+ <Stack gap="sm">
11506
+ <TextArea label="Text" x-model={() => s.note} rows={3} />
11507
+ <Button text="Save" tone="accent" onclick={() => ((s.note = ''), pop.close())} />
11508
+ </Stack>
11509
+ </Popover>
11510
+ <output class="po-told">{() => s.told}</output>
11511
+ </Stack>
11512
+ );
11513
+ }
11514
+ ```
11515
+
11516
+ ## Behaviour
11517
+
11518
+ | Topic | How |
11519
+ | --- | --- |
11520
+ | `Opening` | By a press on the target, by the pointer resting on it (`hover`), or from code. It appears in the browser’s top layer, next to the target, and follows it while the page scrolls. |
11521
+ | `Focus` | Opened by a press or from code, focus moves to the first focusable part inside, else to the popover; it goes back to the target when the popover closes. Opened by hover, focus stays where it is. |
11522
+ | `Closing` | Escape, a press outside it and its target, focus leaving both (Tab out), the close button, the target pressed again, or the pointer leaving both (`hover`). `onClosing` may keep it open. |
11523
+ | `Placement` | `placement` names the side and the alignment, as for the kit’s popups; without room on that side it opens on the other. |
11524
+ | `Where it lives` | Made from code, it goes into the nearest container of its target that can hold it, so it stays in the target’s window and landmark. |
11525
+
11526
+ ## Accessibility
11527
+
11528
+ | Topic | How |
11529
+ | --- | --- |
11530
+ | `Role` | `dialog`, named by its title, else by `label`: give it one. |
11531
+ | `Target` | `aria-controls` and `aria-expanded`; `aria-haspopup="dialog"` when a press opens it. |
11532
+ | `Keyboard` | Tab moves through the content and out (which closes it); Escape closes and returns focus. A `hover` popover opens on keyboard focus too. |
11533
+ | `Arrow` | Decorative. |
11534
+
11535
+ ## Styling
11536
+
11537
+ | Hook | What it is |
11538
+ | --- | --- |
11539
+ | `.mx-popover` | The popover. `data-side` (`top`, `bottom`, `start`, `end`), `data-arrow`. |
11540
+ | `.mx-popover__arrow` | The arrow. |
11541
+ | `.mx-popover__header, .mx-popover__title, .mx-popover__close` | The header, its title and the close button. |
11542
+ | `.mx-popover__body` | The content. |
11543
+
11544
+ ### Component tokens
11545
+
11546
+ | Token | What it sets |
11547
+ | --- | --- |
11548
+ | `popover.surface, .arrow, .header, .title, .body` | Units: the surface (`focus`), the arrow (`display`, `size`, its fill and frame), the header, the title and the body. |
11549
+ | `popover.close` | Place: the close button’s look (`variant`). |
11550
+ | `popover.offset, .enter-offset, .header-gap` | The gap to the target, how far it comes in as it appears, the space between title and close button. |
11551
+
11552
+ ## API reference
11553
+
11554
+ ### Props
11555
+
11556
+ | Prop | Type | Default | Description |
11557
+ | --- | --- | --- | --- |
11558
+ | `target` | `Bind<Element \| ComponentBase \| null>` | `null` | The element or component it opens next to. |
11559
+ | `title` | `Bind<string>` | `''` | A title in the header. The same property as `text`. |
11560
+ | `label` | `Bind<string>` | `''` | What screen readers call it when it has no title. |
11561
+ | `content` | `Bind<ComponentBase \| null>` | `null` | Content from code, after the JSX children. |
11562
+ | `showOn` | `Bind<PopoverShowOn>` | `'click'` | `click`: a press on the target toggles it; `hover`: the pointer resting on the target, or keyboard focus on it; `manual`: only code. |
11563
+ | `placement` | `Bind<PopupPlacement>` | `'bottom'` | The side and the alignment; it opens on the other side when there is no room. |
11564
+ | `arrow` | `Bind<boolean>` | `true` | An arrow towards the target, where the design language draws one. |
11565
+ | `showClose` | `Bind<boolean>` | `false` | A close button in the header. |
11566
+ | `width` | `Bind<string \| number \| null>` | `null` | A width of its own (a CSS length, or pixels). |
11567
+ | `closeOnOutside` | `Bind<boolean>` | `true` | A press outside it and its target closes it. |
11568
+ | `delay, hideDelay` | `Bind<number>` | `300`, `200` | Milliseconds the pointer rests on the target before it opens, and it stays after the pointer leaves both (`showOn: 'hover'`). |
11569
+ | `value` | `Bind<boolean>` | `false` | Open or not; `x-model` binds it two-way. |
11570
+
11571
+ ### Events, properties and methods
11572
+
11573
+ | Member | Kind | Description |
11574
+ | --- | --- | --- |
11575
+ | `onOpened` | event | It opened. |
11576
+ | `onClosing` | event | About to close (`reason`); `cancel = true` keeps it open. |
11577
+ | `onClosed` | event | It closed, with the reason: `escape`, `outside`, `focus`, `toggle`, `hover`, `close-button`, `code`. |
11578
+ | `open(), close(reason?), toggle()` | `boolean` / `void` | From code; `open()` is `false` without a target on the page or when disabled. |
11579
+ | `place()` | `void` | Lines it up with its target again, after its content changed size. |
11580
+ | `isOpen` | read-only | Whether it is open now. |
11581
+ | `closeButton, body` | read-only | The close button (the kit’s) and the part that holds the content. |
11582
+
11583
+
11584
+ ---
11585
+
11586
+ # LoadPanel
11587
+
11588
+ > Feedback · @motifx-community/ui 0.1.0-beta.2
11589
+
11590
+ A “loading” layer over a container or the whole page: a shade, a pane with the kit’s spinner and a message, a Cancel button when the work can be stopped. Nothing under it can be used meanwhile, and focus comes back afterwards.
11591
+
11592
+ ## Import
11593
+
11594
+ ```tsx
11595
+ import { LoadPanel } from '@motifx-community/ui';
11596
+ ```
11597
+
11598
+ ## Over a container
11599
+
11600
+ `target` names the component or element it covers; `value` (or `x-model`) shows and hides it, `show()` and `hide()` from code. `delay` keeps quick work from flashing it.
11601
+
11602
+ ```tsx
11603
+ import { reactive } from '@motifx/core';
11604
+ import { Button, LoadPanel, Panel, Stack, TextBox } from '@motifx-community/ui';
11605
+
11606
+ /** A load panel over a panel while its orders load: bound with x-model, shown after a short delay. */
11607
+ export default function Container() {
11608
+ const s = reactive({ loading: false, result: '' });
11609
+ let panel!: Panel;
11610
+
11611
+ // Stands in for a call to the server.
11612
+ const load = () => {
11613
+ s.loading = true;
11614
+ s.result = '';
11615
+ setTimeout(() => {
11616
+ s.loading = false;
11617
+ s.result = 'Orders loaded.';
11618
+ }, 1800);
11619
+ };
11620
+
11621
+ return (
11622
+ <Stack gap="md" style="inline-size: 100%">
11623
+ <Panel class="lp-panel" variant="outline" padding="md" style="min-block-size: 10rem" ref={(c: Panel) => (panel = c)}>
11624
+ <Stack orientation="horizontal" wrap align="center">
11625
+ <TextBox label="Customer" value="Ada" />
11626
+ <Button text="Load orders" tone="accent" onclick={load} />
11627
+ </Stack>
11628
+ </Panel>
11629
+ <LoadPanel target={() => panel} message="Loading orders" delay={200} x-model={() => s.loading} />
11630
+ <output class="lp-result">{() => s.result}</output>
11631
+ </Stack>
11632
+ );
11633
+ }
11634
+ ```
11635
+
11636
+ ## Over the page, with Cancel
11637
+
11638
+ ```tsx
11639
+ import { reactive } from '@motifx/core';
11640
+ import { Button, LoadPanel, Stack } from '@motifx-community/ui';
11641
+
11642
+ /** Over the whole page, with a Cancel button: the work stops when it is pressed (or on Escape). */
11643
+ export default function Page() {
11644
+ const s = reactive({ told: '' });
11645
+ let timer: ReturnType<typeof setTimeout> | null = null;
11646
+ const panel = new LoadPanel({
11647
+ message: 'Building the report…',
11648
+ cancelable: true,
11649
+ onCancel: () => {
11650
+ if (timer) clearTimeout(timer);
11651
+ timer = null;
11652
+ s.told = 'Cancelled.';
11653
+ }
11654
+ });
11655
+ const start = () => {
11656
+ s.told = '';
11657
+ panel.show();
11658
+ timer = setTimeout(() => {
11659
+ timer = null;
11660
+ panel.hide();
11661
+ s.told = 'The report is ready.';
11662
+ }, 4000);
11663
+ };
11664
+ return (
11665
+ <Stack orientation="horizontal" wrap align="center">
11666
+ <Button text="Build the report" variant="outline" onclick={start} />
11667
+ <span onConfig={c => c.controls.add(panel)} />
11668
+ <output class="lp-told">{() => s.told}</output>
11669
+ </Stack>
11670
+ );
11671
+ }
11672
+ ```
11673
+
11674
+ ## Shade, pane and indicator
11675
+
11676
+ ```tsx
11677
+ import { reactive } from '@motifx/core';
11678
+ import { Button, LoadPanel, Panel, Stack } from '@motifx-community/ui';
11679
+
11680
+ /** Without the shade, without the pane, without the indicator; a press on the shade may hide it. */
11681
+ export default function Options() {
11682
+ const s = reactive({ clear: false, bare: false, words: false });
11683
+ let clear!: Panel;
11684
+ let bare!: Panel;
11685
+ let words!: Panel;
11686
+ const flash = (key: 'clear' | 'bare' | 'words') => {
11687
+ s[key] = true;
11688
+ setTimeout(() => (s[key] = false), 2500);
11689
+ };
11690
+ return (
11691
+ <Stack orientation="horizontal" wrap align="center" style="inline-size: 100%">
11692
+ <Panel variant="outline" padding="md" style="min-inline-size: 16rem; min-block-size: 9rem" ref={(c: Panel) => (clear = c)}>
11693
+ <Button text="No shade" variant="outline" onclick={() => flash('clear')} />
11694
+ </Panel>
11695
+ <LoadPanel target={() => clear} shade={false} x-model={() => s.clear} closeOnOutside />
11696
+ <Panel variant="outline" padding="md" style="min-inline-size: 16rem; min-block-size: 9rem" ref={(c: Panel) => (bare = c)}>
11697
+ <Button text="No pane" variant="outline" onclick={() => flash('bare')} />
11698
+ </Panel>
11699
+ <LoadPanel target={() => bare} showPane={false} x-model={() => s.bare} />
11700
+ <Panel variant="outline" padding="md" style="min-inline-size: 16rem; min-block-size: 9rem" ref={(c: Panel) => (words = c)}>
11701
+ <Button text="Words only" variant="outline" onclick={() => flash('words')} />
11702
+ </Panel>
11703
+ <LoadPanel target={() => words} showIndicator={false} message="Please wait" x-model={() => s.words} />
11704
+ </Stack>
11705
+ );
11706
+ }
11707
+ ```
11708
+
11709
+ ## Behaviour
11710
+
11711
+ | Topic | How |
11712
+ | --- | --- |
11713
+ | `Over a container` | It goes inside the container, over everything in it; the container is `aria-busy` and what is under the panel is inert: nothing there can be pressed or focused. |
11714
+ | `Over the page` | Without a `target`, it covers the viewport and the rest of the page is inert. |
11715
+ | `Focus` | Focus that was under it waits on the panel (on the Cancel button when there is one) and goes back where it was when the panel hides. |
11716
+ | `Delay` | Quick work shows nothing: it comes after `delay`, and a hide before that cancels it. |
11717
+ | `Spinner.cover` | The kit’s spinner covers a container from code in one call (`Spinner.cover`); the load panel is the component with the pane, the message, the delay and the button. |
11718
+
11719
+ ## Accessibility
11720
+
11721
+ | Topic | How |
11722
+ | --- | --- |
11723
+ | `Pane` | A `status` region: the message is read when the panel appears, and again when it changes. |
11724
+ | `Indicator` | Decorative; the message says what is going on. |
11725
+ | `Under it` | `inert` and `aria-busy`, so readers skip it and nothing there takes a press or focus. |
11726
+ | `Cancel` | The kit’s button, named in the kit language; Escape presses it. |
11727
+
11728
+ ## Styling
11729
+
11730
+ | Hook | What it is |
11731
+ | --- | --- |
11732
+ | `.mx-load-panel` | The layer. `data-shade`, `data-pane`, `data-page`. |
11733
+ | `.mx-load-panel__pane` | The pane. |
11734
+ | `.mx-load-panel__indicator, .mx-load-panel__message, .mx-load-panel__cancel` | The spinner, the message and the button. |
11735
+
11736
+ ### Component tokens
11737
+
11738
+ | Token | What it sets |
11739
+ | --- | --- |
11740
+ | `load-panel.shade, .pane, .message` | Units: the layer (`shaded`), the pane (`shown`), the message. |
11741
+ | `load-panel.cancel` | Place: the Cancel button’s look (`variant`). |
11742
+ | `load-panel.padding, .gap` | The least space to the edge of what it covers; the space between the indicator, the message and the button. |
11743
+
11744
+ ## API reference
11745
+
11746
+ ### Props
11747
+
11748
+ | Prop | Type | Default | Description |
11749
+ | --- | --- | --- | --- |
11750
+ | `target` | `Bind<ComponentBase \| HTMLElement \| null>` | `null` | What it covers: a component or an element; `null` covers the whole page. |
11751
+ | `message` | `Bind<string>` | the kit’s “Loading…” | The message under the indicator. The same property as `text`. |
11752
+ | `value` | `Bind<boolean>` | `false` | Shown or not; `x-model` binds it two-way. |
11753
+ | `delay` | `Bind<number>` | `0` | Milliseconds before it shows; a hide before that shows nothing. |
11754
+ | `shade` | `Bind<boolean>` | `true` | Dims what it covers. |
11755
+ | `showPane` | `Bind<boolean>` | `true` | The box behind the indicator and the message. |
11756
+ | `showIndicator` | `Bind<boolean>` | `true` | The turning indicator (the kit’s spinner). |
11757
+ | `cancelable` | `Bind<boolean>` | `false` | A Cancel button in the pane; Escape presses it too. |
11758
+ | `cancelText` | `Bind<string>` | the kit’s “Cancel” | The button’s text. |
11759
+ | `closeOnOutside` | `Bind<boolean>` | `false` | A press on the shade hides it. |
11760
+
11761
+ ### Events, properties and methods
11762
+
11763
+ | Member | Kind | Description |
11764
+ | --- | --- | --- |
11765
+ | `onShown, onHidden` | event | It came on the screen (after its delay); it went. |
11766
+ | `onCancel` | event | The Cancel button was pressed, or Escape; the panel hides after. |
11767
+ | `show(), hide(), cancel()` | `boolean` / `void` | From code; `show()` is `false` while it is shown or waiting for its delay. |
11768
+ | `isShown` | read-only | Whether it is on the screen now. |
11769
+ | `spinner, cancelButton` | read-only | The kit’s spinner and button in the pane. |
11770
+
11771
+
10391
11772
  ---
10392
11773
 
10393
11774
  # Toast
10394
11775
 
10395
- > Feedback · @motifx-community/ui 0.1.0-beta.0
11776
+ > Feedback · @motifx-community/ui 0.1.0-beta.2
10396
11777
 
10397
11778
  Short notifications at an edge of the window: four tones, an action such as Undo, a time of their own or none, six positions and a limit on how many show at once. Called from code; a region of your own can sit in JSX.
10398
11779
 
@@ -10611,7 +11992,7 @@ The name of the region and of the close button come from `uiLocale.strings` (`no
10611
11992
 
10612
11993
  ```tsx
10613
11994
  import { reactive } from '@motifx/core';
10614
- import { Button, enStrings, toast, trStrings, uiLocale } from '@motifx-community/ui';
11995
+ import { Button, toast, uiLocale } from '@motifx-community/ui';
10615
11996
 
10616
11997
  /** Switches the names of the region and the close button. */
10617
11998
  export default function Localization() {
@@ -10619,7 +12000,7 @@ export default function Localization() {
10619
12000
 
10620
12001
  const toggle = () => {
10621
12002
  s.lang = s.lang === 'en' ? 'tr' : 'en';
10622
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
12003
+ void uiLocale.use(s.lang);
10623
12004
  };
10624
12005
 
10625
12006
  return (
@@ -10709,7 +12090,7 @@ export default function Localization() {
10709
12090
 
10710
12091
  # Badge
10711
12092
 
10712
- > Display · @motifx-community/ui 0.1.0-beta.0
12093
+ > Display · @motifx-community/ui 0.1.0-beta.2
10713
12094
 
10714
12095
  A short text, a count or a dot: in a line of text, or on a corner of a button, an avatar or an icon. A count over its maximum shows “99+”, a count of zero hides.
10715
12096
 
@@ -10906,7 +12287,7 @@ A count is written in the kit language (`uiLocale`), again when it changes: “1
10906
12287
 
10907
12288
  # Avatar and AvatarGroup
10908
12289
 
10909
- > Display · @motifx-community/ui 0.1.0-beta.0
12290
+ > Display · @motifx-community/ui 0.1.0-beta.2
10910
12291
 
10911
12292
  Someone’s picture, or their initials, or a person icon, with their presence on its corner. A group stacks or spreads them and counts the ones it does not show.
10912
12293
 
@@ -11148,7 +12529,7 @@ Initials are written in the capitals of the kit language (`uiLocale`): “ilgin
11148
12529
 
11149
12530
  # Chip and ChipGroup
11150
12531
 
11151
- > Display · @motifx-community/ui 0.1.0-beta.0
12532
+ > Display · @motifx-community/ui 0.1.0-beta.2
11152
12533
 
11153
12534
  A short text with an icon or an avatar before it: a filter to turn on, a choice among a few, or something picked that can be removed. A group selects one or several and moves between them with the arrow keys.
11154
12535
 
@@ -11430,7 +12811,7 @@ The remove button’s name is the kit text `removeItem` (“Remove {text}”) an
11430
12811
 
11431
12812
  # Card
11432
12813
 
11433
- > Display · @motifx-community/ui 0.1.0-beta.0
12814
+ > Display · @motifx-community/ui 0.1.0-beta.2
11434
12815
 
11435
12816
  A surface holding one thing: a picture, a header with an avatar and titles, content and a row of actions. Parts with nothing in them are left out.
11436
12817
 
@@ -11688,7 +13069,7 @@ export default function Sizes() {
11688
13069
 
11689
13070
  # Skeleton
11690
13071
 
11691
- > Display · @motifx-community/ui 0.1.0-beta.0
13072
+ > Display · @motifx-community/ui 0.1.0-beta.2
11692
13073
 
11693
13074
  The shape of what is loading, so the page keeps its layout while data arrives. Given content, it shows the content in the same place once loading ends.
11694
13075
 
@@ -11823,7 +13204,7 @@ export default function Animations() {
11823
13204
 
11824
13205
  # Tabs
11825
13206
 
11826
- > Navigation · @motifx-community/ui 0.1.0-beta.0
13207
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
11827
13208
 
11828
13209
  Tabs show one panel at a time under a strip of tabs: from JSX or from code, closable, with icons and badges, scroll buttons when the tabs do not fit, four placements and panels built when they are first shown.
11829
13210
 
@@ -12169,7 +13550,7 @@ Tabs write one text: the close button's tooltip, `uiLocale.strings.close`. Every
12169
13550
 
12170
13551
  ```tsx
12171
13552
  import { reactive } from '@motifx/core';
12172
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
13553
+ import { Button, uiLocale } from '@motifx-community/ui';
12173
13554
  import { kitTexts } from '../../../shared/kit-texts';
12174
13555
 
12175
13556
  /** Switches the texts of every component on the page, the tabs' close button included. */
@@ -12177,7 +13558,7 @@ export default function Localization() {
12177
13558
  const s = reactive({ lang: 'en' });
12178
13559
  const toggle = () => {
12179
13560
  s.lang = s.lang === 'en' ? 'tr' : 'en';
12180
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
13561
+ void uiLocale.use(s.lang);
12181
13562
  };
12182
13563
  return (
12183
13564
  <>
@@ -12283,7 +13664,7 @@ export default function Localization() {
12283
13664
 
12284
13665
  # Breadcrumb
12285
13666
 
12286
- > Navigation · @motifx-community/ui 0.1.0-beta.0
13667
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
12287
13668
 
12288
13669
  The way to the current page: each step a link or a button, the current page last. Steps that do not fit go into a menu after the first.
12289
13670
 
@@ -12295,7 +13676,7 @@ import { Breadcrumb } from '@motifx-community/ui';
12295
13676
 
12296
13677
  ## Links and buttons
12297
13678
 
12298
- A step with `href` is a link; `rel=&quot;router&quot;` lets the MotifJS router take it. A step without one is a button: `onItemClick` tells it.
13679
+ A step with `href` is a link; `rel='router'` lets the MotifJS router take it. A step without one is a button: `onItemClick` tells it.
12299
13680
 
12300
13681
  ```tsx
12301
13682
  import { reactive } from '@motifx/core';
@@ -12412,7 +13793,7 @@ export default function Sizes() {
12412
13793
 
12413
13794
  # Pagination
12414
13795
 
12415
- > Navigation · @motifx-community/ui 0.1.0-beta.0
13796
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
12416
13797
 
12417
13798
  Moving through pages of items: the sizes to choose from, where the page stands, the steps and a button per page around the current one. It turns compact when it does not fit. It looks and works as the grid’s pager.
12418
13799
 
@@ -12527,11 +13908,497 @@ export default function Looks() {
12527
13908
  | `compact` | read-only | Whether the compact look shows now. |
12528
13909
 
12529
13910
 
13911
+ ---
13912
+
13913
+ # Stepper
13914
+
13915
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
13916
+
13917
+ The steps of a longer task and where the user stands in them: an indicator and a text per step, a line between them, the steps before the current one completed. The [Wizard](wizard.md) adds a page and the buttons to each step.
13918
+
13919
+ ## Import
13920
+
13921
+ ```tsx
13922
+ import { Stepper } from '@motifx-community/ui';
13923
+ ```
13924
+
13925
+ ## From JSX and from code
13926
+
13927
+ The current step is `value`: a step’s `key`, else its index; `x-model` binds it two-way. From code, `next()`, `previous()` and `goTo()` move it and `onStepChanged` tells.
13928
+
13929
+ ```tsx
13930
+ import { reactive } from '@motifx/core';
13931
+ import { Button, Stack, Stepper } from '@motifx-community/ui';
13932
+
13933
+ /** A stepper bound with x-model, and one made from code and moved with its own methods. */
13934
+ export default function FromCode() {
13935
+ const s = reactive({ step: 0 as string | number | null, at: 0, told: '' });
13936
+ const coded = new Stepper({
13937
+ label: 'Order',
13938
+ items: ['Cart', 'Address', 'Payment', 'Done'],
13939
+ linear: false,
13940
+ onStepChanged: e => {
13941
+ s.at = e.index;
13942
+ s.told = `Step ${e.index + 1}${e.byUser ? ', pressed' : ''}`;
13943
+ }
13944
+ });
13945
+
13946
+ return (
13947
+ <Stack gap="lg" style="inline-size: 100%">
13948
+ <Stepper label="Sign up" items={['Account', 'Profile', 'Review']} x-model={() => s.step} />
13949
+ <output class="st-value">{() => `value: ${JSON.stringify(s.step)}`}</output>
13950
+ <span onConfig={c => c.controls.add(coded)} />
13951
+ <Stack orientation="horizontal" wrap align="center">
13952
+ <Button text="Back" variant="outline" enabled={() => s.at > 0} onclick={() => void coded.previous()} />
13953
+ <Button text="Next" variant="outline" enabled={() => s.at < 3} onclick={() => void coded.next()} />
13954
+ <output class="st-told">{() => s.told}</output>
13955
+ </Stack>
13956
+ </Stack>
13957
+ );
13958
+ }
13959
+ ```
13960
+
13961
+ ## Statuses
13962
+
13963
+ The steps before the current one are completed by themselves. An item may say `status: 'done'` or `'error'` whatever the current step is, be `optional`, be disabled, or carry an `icon` in place of its number; its fields may be functions of your state.
13964
+
13965
+ | Status | How |
13966
+ | --- | --- |
13967
+ | `pending` | A step to come: its number in the indicator. |
13968
+ | `current` | The step in hand: `aria-current="step"`. |
13969
+ | `done` | The steps before the current one, and any step whose item says `status: 'done'`: a check in the indicator, the line before it filled. |
13970
+ | `error` | A step whose item says `status: 'error'`: a mark in the indicator, the text in the danger colour; read out as “Needs attention”. |
13971
+ | `optional` | Says “Optional” under the text; in linear order it may be skipped. |
13972
+ | `disabled` | An item with `enabled: false`, or a step linear order does not reach yet: `aria-disabled`, out of the Tab order. |
13973
+
13974
+ ```tsx
13975
+ import { reactive } from '@motifx/core';
13976
+ import { Button, Stack, Stepper } from '@motifx-community/ui';
13977
+
13978
+ const pencil = () => {
13979
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
13980
+ svg.setAttribute('viewBox', '0 0 16 16');
13981
+ svg.setAttribute('aria-hidden', 'true');
13982
+ svg.innerHTML = '<path d="M11.5 2.5l2 2L5 13H3v-2z" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>';
13983
+ return svg;
13984
+ };
13985
+
13986
+ /** Completed and failed steps told by the items, an optional step, a disabled one, an icon in place of the number. */
13987
+ export default function Statuses() {
13988
+ const s = reactive({ paid: false });
13989
+ const items = [
13990
+ { text: 'Cart', status: 'done' as const },
13991
+ { text: 'Address', description: 'Checked', status: 'done' as const },
13992
+ { text: 'Payment', description: () => (s.paid ? 'Paid' : 'Card declined'), status: () => (s.paid ? 'done' : 'error') },
13993
+ { text: 'Gift note', optional: true, icon: pencil() },
13994
+ { text: 'Pick-up', enabled: false },
13995
+ { text: 'Done' }
13996
+ ];
13997
+ return (
13998
+ <Stack gap="md" style="inline-size: 100%">
13999
+ <Stepper label="Statuses" items={items} value={5} linear={false} />
14000
+ <Button text={() => (s.paid ? 'Decline the card' : 'Take the payment')} variant="outline" onclick={() => (s.paid = !s.paid)} />
14001
+ </Stack>
14002
+ );
14003
+ }
14004
+ ```
14005
+
14006
+ ## In order, or free
14007
+
14008
+ `linear` (the default) lets a press reach only the completed steps and the next one; `linear={false}` lets it reach any. Either way `onStepChanging` is asked first: `cancel` keeps the step, a `promise` waits for a check or a server.
14009
+
14010
+ ```tsx
14011
+ import { reactive } from '@motifx/core';
14012
+ import { CheckBox, Stack, Stepper } from '@motifx-community/ui';
14013
+
14014
+ /** In linear order a step is reached only after the ones before it; `onStepChanging` refuses a step while the box is unchecked. */
14015
+ export default function Linear() {
14016
+ const s = reactive({ step: 0 as string | number | null, agreed: false, note: '' });
14017
+ return (
14018
+ <Stack gap="md" style="inline-size: 100%">
14019
+ <Stepper
14020
+ label="In order"
14021
+ items={['Terms', 'Details', 'Confirm']}
14022
+ x-model={() => s.step}
14023
+ onStepChanging={e => {
14024
+ if (e.to > 0 && !s.agreed) {
14025
+ e.cancel = true;
14026
+ s.note = 'Accept the terms first.';
14027
+ } else {
14028
+ s.note = '';
14029
+ }
14030
+ }}
14031
+ />
14032
+ <CheckBox label="I accept the terms" x-model={() => s.agreed} />
14033
+ <output class="st-note">{() => s.note}</output>
14034
+ </Stack>
14035
+ );
14036
+ }
14037
+ ```
14038
+
14039
+ ## Orientations
14040
+
14041
+ ```tsx
14042
+ import { Stack, Stepper } from '@motifx-community/ui';
14043
+
14044
+ const STEPS = [
14045
+ { text: 'Details', description: 'Name and e-mail' },
14046
+ { text: 'Address', description: 'Where to send it' },
14047
+ { text: 'Payment', description: 'Card or transfer' },
14048
+ { text: 'Review' }
14049
+ ];
14050
+
14051
+ /** Horizontal with the texts under or after the indicators, and vertical. */
14052
+ export default function Orientations() {
14053
+ return (
14054
+ <Stack gap="lg" style="inline-size: 100%">
14055
+ <Stepper label="Texts under" items={STEPS} value={1} linear={false} />
14056
+ <Stepper label="Texts after" items={STEPS.slice(0, 3)} value={1} labelPosition="end" linear={false} />
14057
+ <div style="inline-size: 18rem">
14058
+ <Stepper label="Standing" items={STEPS} value={1} orientation="vertical" linear={false} />
14059
+ </div>
14060
+ </Stack>
14061
+ );
14062
+ }
14063
+ ```
14064
+
14065
+ ## Sizes
14066
+
14067
+ ```tsx
14068
+ import { Stack, Stepper } from '@motifx-community/ui';
14069
+
14070
+ const STEPS = ['Plan', 'Build', 'Ship'];
14071
+
14072
+ /** Three sizes, and a stepper without numbers. */
14073
+ export default function Sizes() {
14074
+ return (
14075
+ <Stack gap="lg" style="inline-size: 100%">
14076
+ <Stepper label="Small" items={STEPS} value={1} size="sm" linear={false} />
14077
+ <Stepper label="Medium" items={STEPS} value={1} linear={false} />
14078
+ <Stepper label="Large" items={STEPS} value={1} size="lg" linear={false} />
14079
+ <Stepper label="Dots" items={STEPS} value={1} showNumbers={false} size="sm" labelPosition="end" linear={false} />
14080
+ </Stack>
14081
+ );
14082
+ }
14083
+ ```
14084
+
14085
+ ## Keyboard
14086
+
14087
+ | Key | What it does |
14088
+ | --- | --- |
14089
+ | `Tab` | One stop: the step focused last, else the current one, else the first that can be reached. |
14090
+ | `Arrow keys` | Left and Right (Up and Down standing) move between the steps that can be reached, around the ends; Home and End go to the first and the last. |
14091
+ | `Enter, Space` | Choose the focused step; `onStepChanging` may refuse. |
14092
+
14093
+ ## Accessibility
14094
+
14095
+ | Topic | How |
14096
+ | --- | --- |
14097
+ | `Landmark` | A `nav` named “Steps” in the kit language, holding an ordered list; several on one page: give each its own `label`. |
14098
+ | `A step` | A button whose name reads “Step 2 of 4, Address, Where to send it, Completed”: the position, the texts and the status are all in it. |
14099
+ | `Not clickable` | Plain elements: nothing to press, the current one still `aria-current`. |
14100
+ | `Lines and marks` | Decorative, hidden from readers. |
14101
+
14102
+ ## Styling
14103
+
14104
+ | Hook | What it is |
14105
+ | --- | --- |
14106
+ | `.mx-stepper` | The stepper. `data-orientation`, `data-labels`, `data-size`. |
14107
+ | `.mx-stepper__list, .mx-stepper__item` | The list and each step with its line. `data-status` on the item. |
14108
+ | `.mx-stepper__step` | The step: a button or a div. `data-status`, `aria-current`, `aria-disabled`. |
14109
+ | `.mx-stepper__indicator, .mx-stepper__number, .mx-stepper__mark, .mx-stepper__icon` | The circle, the number in it, the check or error mark, an icon of your own. |
14110
+ | `.mx-stepper__label, .mx-stepper__description, .mx-stepper__note` | The texts. |
14111
+ | `.mx-stepper__line` | The line to the next step. `data-status="done"` up to the current one. |
14112
+
14113
+ ### Component tokens
14114
+
14115
+ | Token | What it sets |
14116
+ | --- | --- |
14117
+ | `stepper.step, .indicator, .mark, .label, .description, .note, .line` | Units: the step (`hover`, `pressed`, `focus`, `disabled`, `current`, `done`, `error`), its indicator, the mark (`icon` per state), the texts, the line (`done`); the line turns a quarter in a vertical stepper. |
14118
+ | `stepper.size.*, .font-size.*, .padding.*` | The indicator, the text and the space around a step, per size. |
14119
+ | `stepper.description-font-size, .gap, .line-gap, .line-min-length` | The second line, the space between indicator and texts, and the line’s margins and least length. |
14120
+
14121
+ ## API reference
14122
+
14123
+ ### Props
14124
+
14125
+ | Prop | Type | Default | Description |
14126
+ | --- | --- | --- | --- |
14127
+ | `items` | `Bind<readonly (StepperItem \| string)[]>` | `[]` | The steps in order: `StepperItem`s (`text`, `description`, `key`, `icon`, `status`, `optional`, `enabled`, `data`) or plain texts. |
14128
+ | `value` | `Bind<string \| number \| null>` | `0` | The current step: its `key`, else its index; `null` for none. `x-model` binds it two-way. |
14129
+ | `linear` | `Bind<boolean>` | `true` | A press reaches a completed step, or the one right after the last completed; optional steps may be skipped. |
14130
+ | `orientation` | `Bind<StepperOrientation>` | `'horizontal'` | `horizontal` or `vertical`. |
14131
+ | `labelPosition` | `Bind<StepperLabelPosition>` | `'bottom'` | Horizontal only: the texts under the indicator (`bottom`) or after it (`end`). |
14132
+ | `size` | `Bind<ControlSize>` | `'md'` | `sm`, `md`, `lg`. |
14133
+ | `clickable` | `Bind<boolean>` | `true` | `false` shows the way only: no buttons, no Tab stop. |
14134
+ | `showNumbers` | `Bind<boolean>` | `true` | The indicator of a step to come shows its number. |
14135
+ | `label` | `Bind<string>` | the kit’s “Steps” | What screen readers call it. |
14136
+
14137
+ ### Events, properties and methods
14138
+
14139
+ | Member | Kind | Description |
14140
+ | --- | --- | --- |
14141
+ | `onStepChanging` | event | The current step is about to change (`from`, `to`, `fromItem`, `toItem`, `byUser`). `cancel = true` keeps it; `promise` set to a `Promise<boolean>` waits, and the step changes when it resolves to `true`. |
14142
+ | `onStepChanged` | event | The current step changed (`index`, `item`, `previous`, `byUser`). |
14143
+ | `selectedIndex` | read-only | The index of the current step; -1 when there is none. |
14144
+ | `count` | read-only | How many steps there are. |
14145
+ | `canGoNext, canGoPrevious` | read-only | There is an enabled step after, or before, the current one. |
14146
+ | `next(), previous()` | `Promise<boolean>` | Goes to the next or the previous enabled step; `false` when there is none or the change was refused. |
14147
+ | `goTo(step)` | `Promise<boolean>` | Goes to a step by index or key, whatever the order; `onStepChanging` is asked first. |
14148
+ | `statusOf(index)` | `StepperStatus` | `pending`, `current`, `done` or `error`, as drawn. |
14149
+ | `canReach(index)` | `boolean` | Whether a press may reach the step. |
14150
+ | `refresh()` | `void` | Reads the items again after they were changed in place. |
14151
+
14152
+
14153
+ ---
14154
+
14155
+ # Wizard
14156
+
14157
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
14158
+
14159
+ A task in steps: a [Stepper](stepper.md) above or beside one page per step, and the Back and Next buttons under them. Next validates the page first; on the last step it finishes.
14160
+
14161
+ ## Import
14162
+
14163
+ ```tsx
14164
+ import { Wizard, WizardStep } from '@motifx-community/ui';
14165
+ ```
14166
+
14167
+ ## Pages from JSX
14168
+
14169
+ Each `WizardStep` is a step and its page. Next validates the kit’s fields on the page, then the step’s own `validate`; a page that fails keeps the wizard, marks its step and focuses the first invalid field. On the last step Next reads Finish and raises `onFinished`.
14170
+
14171
+ ```tsx
14172
+ import { reactive } from '@motifx/core';
14173
+ import { CheckBox, Stack, TextBox, Wizard, WizardStep } from '@motifx-community/ui';
14174
+
14175
+ /** Three pages with the kit's fields: Next validates the page first; Finish tells the app. */
14176
+ export default function Basic() {
14177
+ const s = reactive({ name: '', email: '', city: '', agreed: false, result: '' });
14178
+ return (
14179
+ <Stack gap="md" style="inline-size: 100%">
14180
+ <Wizard label="Sign up" onFinished={() => (s.result = `Welcome, ${s.name}.`)}>
14181
+ <WizardStep title="Account" description="Who you are">
14182
+ <Stack orientation="horizontal" wrap align="center">
14183
+ <TextBox label="Name" x-model={() => s.name} required />
14184
+ <TextBox label="E-mail" x-model={() => s.email} required rules={[{ type: 'email' }]} />
14185
+ </Stack>
14186
+ </WizardStep>
14187
+ <WizardStep title="Address" description="Where you live">
14188
+ <TextBox label="City" x-model={() => s.city} required />
14189
+ </WizardStep>
14190
+ <WizardStep title="Review" validate={() => s.agreed}>
14191
+ <p>{() => `${s.name || '—'}, ${s.email || '—'}, ${s.city || '—'}`}</p>
14192
+ <CheckBox label="Everything is right" x-model={() => s.agreed} />
14193
+ </WizardStep>
14194
+ </Wizard>
14195
+ <output class="wz-result">{() => s.result}</output>
14196
+ </Stack>
14197
+ );
14198
+ }
14199
+ ```
14200
+
14201
+ ## From code
14202
+
14203
+ `steps` makes the steps from props, each page from a `content` factory when it is first shown; `add`, `insert` and `remove` change them later. `next()`, `previous()`, `goTo()` and `finish()` move it.
14204
+
14205
+ ```tsx
14206
+ import { Component, reactive } from '@motifx/core';
14207
+ import { Button, Stack, Wizard, WizardStep } from '@motifx-community/ui';
14208
+
14209
+ // A page made from code: any MotifJS component.
14210
+ class Note extends Component<HTMLDivElement, { text: string }> {
14211
+ override view() {
14212
+ return <p>{this.props.text}</p>;
14213
+ }
14214
+ }
14215
+
14216
+ /** A wizard made from code: its steps as props with content factories, moved with its methods, a step added later. */
14217
+ export default function FromCode() {
14218
+ const s = reactive({ told: '' });
14219
+ const wizard = new Wizard({
14220
+ label: 'Setup',
14221
+ steps: [
14222
+ { title: 'Welcome', content: () => new Note({ text: 'A page made by a factory, built when first shown.' }) },
14223
+ { title: 'Options', description: 'Pick what you need', content: () => new Note({ text: 'The second page.' }) },
14224
+ { title: 'Done', content: () => new Note({ text: 'The last page; Next reads Finish here.' }) }
14225
+ ],
14226
+ onStepChanged: e => (s.told = `Step ${e.index + 1}: ${(e.item as { text: string }).text}`),
14227
+ onFinished: () => (s.told = 'Finished.')
14228
+ });
14229
+ const addStep = () => {
14230
+ wizard.insert(2, new WizardStep({ title: 'Extra', optional: true, content: () => new Note({ text: 'Added from code.' }) }));
14231
+ };
14232
+ return (
14233
+ <Stack gap="md" style="inline-size: 100%">
14234
+ <span onConfig={c => c.controls.add(wizard)} />
14235
+ <Stack orientation="horizontal" wrap align="center">
14236
+ <Button text="Go to Done" variant="outline" onclick={() => void wizard.goTo(wizard.steps.length - 1)} />
14237
+ <Button text="Add a step" variant="outline" onclick={addStep} />
14238
+ <output class="wz-told">{() => s.told}</output>
14239
+ </Stack>
14240
+ </Stack>
14241
+ );
14242
+ }
14243
+ ```
14244
+
14245
+ ## Standing
14246
+
14247
+ ```tsx
14248
+ import { reactive } from '@motifx/core';
14249
+ import { RadioGroup, Switch, TextArea, Wizard, WizardStep } from '@motifx-community/ui';
14250
+
14251
+ /** The stepper beside the pages, the texts after the indicators. */
14252
+ export default function Vertical() {
14253
+ const s = reactive({ plan: 'Team', notify: true, note: '' });
14254
+ return (
14255
+ <Wizard label="Subscription" orientation="vertical" style="min-block-size: 16rem; inline-size: 100%">
14256
+ <WizardStep title="Plan" description="What you pay for">
14257
+ <RadioGroup label="Plan" items={['Solo', 'Team', 'Business']} x-model={() => s.plan} />
14258
+ </WizardStep>
14259
+ <WizardStep title="Alerts" description="How we reach you">
14260
+ <Switch label="Send me a monthly summary" x-model={() => s.notify} />
14261
+ </WizardStep>
14262
+ <WizardStep title="Notes" optional>
14263
+ <TextArea label="Anything else?" x-model={() => s.note} rows={3} />
14264
+ </WizardStep>
14265
+ </Wizard>
14266
+ );
14267
+ }
14268
+ ```
14269
+
14270
+ ## Your own buttons, finishing that waits
14271
+
14272
+ `showNavigation={false}` takes the bar away; your own buttons call the methods. `onFinishing` may set a `promise`: the wizard finishes when it resolves to `true`, and stays otherwise.
14273
+
14274
+ ```tsx
14275
+ import { reactive } from '@motifx/core';
14276
+ import { Button, Stack, TextBox, Wizard, WizardStep } from '@motifx-community/ui';
14277
+
14278
+ /** No bar: buttons of your own drive it; finishing waits for a promise (a server) and may be refused. */
14279
+ export default function Custom() {
14280
+ const s = reactive({ code: '', busy: false, note: '' });
14281
+ let wizard!: Wizard;
14282
+ const finish = () => {
14283
+ s.note = '';
14284
+ void wizard.finish().then(ok => (s.note = ok ? 'Saved.' : s.note || 'Not finished.'));
14285
+ };
14286
+ return (
14287
+ <Stack gap="md" style="inline-size: 100%">
14288
+ <Wizard
14289
+ ref={(w: Wizard) => (wizard = w)}
14290
+ label="Redeem"
14291
+ showNavigation={false}
14292
+ labelPosition="end"
14293
+ onFinishing={e => {
14294
+ s.busy = true;
14295
+ e.promise = new Promise<boolean>(resolve => setTimeout(() => resolve(s.code.toUpperCase() === 'MOTIF'), 600)).then(ok => {
14296
+ s.busy = false;
14297
+ if (!ok) s.note = 'That code is not known.';
14298
+ return ok;
14299
+ });
14300
+ }}
14301
+ >
14302
+ <WizardStep title="Code">
14303
+ <TextBox label="Gift code" x-model={() => s.code} required placeholder="MOTIF" />
14304
+ </WizardStep>
14305
+ <WizardStep title="Confirm">
14306
+ <p>{() => `Redeem “${s.code}”?`}</p>
14307
+ </WizardStep>
14308
+ </Wizard>
14309
+ <Stack orientation="horizontal" wrap align="center">
14310
+ <Button text="Back" variant="outline" onclick={() => void wizard.previous()} />
14311
+ <Button text="Next" variant="outline" onclick={() => void wizard.next()} />
14312
+ <Button text="Redeem" busy={() => s.busy} onclick={finish} />
14313
+ <output class="wz-note">{() => s.note}</output>
14314
+ </Stack>
14315
+ </Stack>
14316
+ );
14317
+ }
14318
+ ```
14319
+
14320
+ ## Accessibility
14321
+
14322
+ | Topic | How |
14323
+ | --- | --- |
14324
+ | `Stepper` | A `nav` of steps as on the [Stepper](stepper.md) page: each a button with its position and status in its name, one Tab stop. |
14325
+ | `Page` | A `group` named after its step; the hidden pages are out of the tree. |
14326
+ | `Validation` | A page that fails keeps focus on its first invalid field, with its message; the step reads “Needs attention”. |
14327
+ | `Buttons` | The kit’s buttons, named in the kit language: “Back”, “Next”, “Finish”. |
14328
+
14329
+ ## Styling
14330
+
14331
+ | Hook | What it is |
14332
+ | --- | --- |
14333
+ | `.mx-wizard` | The wizard. `data-orientation`. |
14334
+ | `.mx-wizard__stepper` | The stepper (`.mx-stepper` too). |
14335
+ | `.mx-wizard__pages, .mx-wizard__page` | The pages and each page; a hidden page carries `hidden`. |
14336
+ | `.mx-wizard__bar, .mx-wizard__previous, .mx-wizard__next` | The bar and its buttons. |
14337
+
14338
+ ### Component tokens
14339
+
14340
+ | Token | What it sets |
14341
+ | --- | --- |
14342
+ | `wizard.frame, .page, .bar` | Units: the whole, a page, the bar (a rule over it, its padding). |
14343
+ | `wizard.previous, wizard.next` | Places: the buttons’ look in the bar (`variant`). |
14344
+ | `wizard.gap, .bar-gap, .rail-width` | Between the stepper, the pages and the bar; between the buttons; the stepper’s width when it stands beside the pages. |
14345
+
14346
+ ## API reference
14347
+
14348
+ ### Wizard props
14349
+
14350
+ | Prop | Type | Default | Description |
14351
+ | --- | --- | --- | --- |
14352
+ | `steps` | `readonly WizardStepProps[]` | `[]` | Steps made from code, each as the props of a `WizardStep`; the JSX `WizardStep` children come first. |
14353
+ | `value` | `Bind<string \| number \| null>` | `0` | The current step: its `key`, else its index. `x-model` binds it two-way. |
14354
+ | `linear` | `Bind<boolean>` | `true` | A step is reached only after the ones before it; optional steps may be skipped. |
14355
+ | `orientation` | `Bind<StepperOrientation>` | `'horizontal'` | `horizontal`: the stepper above the pages; `vertical`: beside them. |
14356
+ | `labelPosition` | `Bind<StepperLabelPosition>` | `'bottom'` | Where the stepper’s texts sit, horizontal only. |
14357
+ | `size` | `Bind<ControlSize>` | `'md'` | The stepper’s size. |
14358
+ | `showStepper, showNavigation` | `Bind<boolean>` | `true` | The stepper, and the bar with the Back and Next buttons. |
14359
+ | `clickable` | `Bind<boolean>` | `true` | The steps of the stepper can be pressed. |
14360
+ | `lazy` | `Bind<boolean>` | `true` | A page is built when first shown, then kept (a step’s own `lazy` wins). |
14361
+ | `keepAlive` | `Bind<boolean>` | `true` | `false`: what a step’s `content` made is disposed while hidden and made again when it shows (a step’s own `keepAlive` wins). |
14362
+ | `previousText, nextText, finishText` | `Bind<string>` | the kit’s “Back”, “Next”, “Finish” | The buttons’ texts. |
14363
+ | `label` | `Bind<string>` | the kit’s “Steps” | What screen readers call the stepper. |
14364
+
14365
+ ### WizardStep props
14366
+
14367
+ | Prop | Type | Default | Description |
14368
+ | --- | --- | --- | --- |
14369
+ | `title` | `Bind<string>` | `''` | The step’s text in the stepper. The same property as `text`. |
14370
+ | `description` | `Bind<string>` | `''` | A second line under the title. |
14371
+ | `key` | `Bind<string>` | the index | Names the step in `value`; the JSX `key` works too. |
14372
+ | `icon` | `Bind<IconSource \| null>` | `null` | Drawn in the indicator in place of the number. |
14373
+ | `optional` | `Bind<boolean>` | `false` | May be skipped; says so under the title. |
14374
+ | `enabled` | `Bind<boolean>` | `true` | `false` keeps the step from being reached. |
14375
+ | `error` | `Bind<boolean>` | `false` | Draws the step with an error; the wizard sets it when the page does not validate, and clears it when it does. |
14376
+ | `validateFields` | `Bind<boolean>` | `true` | The kit’s fields on the page are validated before the wizard moves on from it; the first invalid one takes focus. |
14377
+ | `validate` | `() => boolean \| Promise<boolean>` | — | Asked after the fields; `false` keeps the page and marks the step. |
14378
+ | `lazy, keepAlive` | `Bind<boolean \| undefined>` | the wizard’s | See the wizard’s. |
14379
+ | `content` | `() => ComponentBase \| ComponentBase[]` | — | Makes the page from code, when the page is built. |
14380
+
14381
+ ### Events, properties and methods
14382
+
14383
+ | Member | Kind | Description |
14384
+ | --- | --- | --- |
14385
+ | `onStepChanging, onStepChanged` | event | The stepper’s events: `onStepChanging` (`cancel`, `promise`) runs before the page is validated. |
14386
+ | `onFinishing` | event | The last page validated and the wizard is about to finish; `cancel = true` keeps it open, `promise` waits and finishes on `true`. |
14387
+ | `onFinished` | event | The wizard finished: every step is drawn done. |
14388
+ | `next(), previous(), goTo(step)` | `Promise<boolean>` | Next validates the page first and finishes on the last step; Back validates nothing; `goTo` validates when it goes forward. |
14389
+ | `finish()` | `Promise<boolean>` | Validates the page, asks `onFinishing`, then finishes. |
14390
+ | `leaveCheck()` | `Promise<boolean>` | Validates the current page the way Next does, without moving. |
14391
+ | `add(step), insert(index, step), remove(step)` | `WizardStep` / `boolean` | Steps from code; a step of another wizard moves here. |
14392
+ | `stepper, steps, currentStep, selectedIndex` | read-only | The `Stepper`, the `WizardStep`s in order, the current one and its index. |
14393
+ | `isLast, isFinished` | read-only | The current step is the last that can be gone to (Next finishes); the wizard finished. |
14394
+ | `previousButton, nextButton` | read-only | The kit’s buttons in the bar, for an icon or a look of your own. |
14395
+
14396
+
12530
14397
  ---
12531
14398
 
12532
14399
  # Accordion
12533
14400
 
12534
- > Navigation · @motifx-community/ui 0.1.0-beta.0
14401
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
12535
14402
 
12536
14403
  An accordion opens and closes sections under their headers: one at a time or several, kept open, with icons, three looks and sections built when they are first opened.
12537
14404
 
@@ -12830,7 +14697,7 @@ The accordion writes no text of its own, so it has nothing in `uiLocale`.
12830
14697
 
12831
14698
  # Window and dialog
12832
14699
 
12833
- > Navigation · @motifx-community/ui 0.1.0-beta.0
14700
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
12834
14701
 
12835
14702
  A window or a dialog on a native `<dialog>`: one form, shown modeless or modal by whoever shows it. It has a title bar, moves, resizes, minimizes and maximizes; Enter and Escape press its buttons; forms open forms. `messageBox` and `confirm` cover the common questions.
12836
14703
 
@@ -13157,7 +15024,7 @@ The title bar buttons and the `ok`, `cancel`, `yes`, `no` buttons of a message b
13157
15024
 
13158
15025
  ```tsx
13159
15026
  import { reactive } from '@motifx/core';
13160
- import { Button, enStrings, messageBox, trStrings, uiLocale } from '@motifx-community/ui';
15027
+ import { Button, messageBox, uiLocale } from '@motifx-community/ui';
13161
15028
 
13162
15029
  /** Switches the names of the title bar buttons and of the message box buttons. */
13163
15030
  export default function Localization() {
@@ -13165,7 +15032,7 @@ export default function Localization() {
13165
15032
 
13166
15033
  const toggle = () => {
13167
15034
  s.lang = s.lang === 'en' ? 'tr' : 'en';
13168
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
15035
+ void uiLocale.use(s.lang);
13169
15036
  };
13170
15037
 
13171
15038
  const ask = () =>
@@ -13390,7 +15257,7 @@ export default function DefaultButtons() {
13390
15257
 
13391
15258
  # BottomSheet
13392
15259
 
13393
- > Navigation · @motifx-community/ui 0.1.0-beta.0
15260
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
13394
15261
 
13395
15262
  A panel that comes up from the bottom of the page or of a container and stops at a few heights: a peek, half, full, as tall as its content, or heights of your own. Dragged by its handle and its title, flicked, swiped down to close; modal or not, with the browser's back closing it on a phone.
13396
15263
 
@@ -13615,7 +15482,7 @@ The handle's name and heights, the default name and the close button come from `
13615
15482
 
13616
15483
  ```tsx
13617
15484
  import { reactive } from '@motifx/core';
13618
- import { BottomSheet, Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
15485
+ import { BottomSheet, Button, uiLocale } from '@motifx-community/ui';
13619
15486
 
13620
15487
  /** The handle's name and heights and the close button's name come from uiLocale. */
13621
15488
  export default function Localization() {
@@ -13623,7 +15490,7 @@ export default function Localization() {
13623
15490
 
13624
15491
  const toggle = () => {
13625
15492
  s.lang = s.lang === 'en' ? 'tr' : 'en';
13626
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
15493
+ void uiLocale.use(s.lang);
13627
15494
  };
13628
15495
 
13629
15496
  return (
@@ -13710,7 +15577,7 @@ Every prop is a property too, taking a value or a function. The shared parts (th
13710
15577
 
13711
15578
  # Drawer
13712
15579
 
13713
- > Navigation · @motifx-community/ui 0.1.0-beta.0
15580
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
13714
15581
 
13715
15582
  A panel that slides in from an edge of the page or of a container, over the content or pushing it aside. A finger swipes it in from the edge and back again; Escape, the scrim and the browser's back close it.
13716
15583
 
@@ -13943,7 +15810,7 @@ Its default name and the close button come from `uiLocale.strings` (`drawerLabel
13943
15810
 
13944
15811
  # ActionSheet
13945
15812
 
13946
- > Navigation · @motifx-community/ui 0.1.0-beta.0
15813
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
13947
15814
 
13948
15815
  A list of commands that comes up from the bottom, made of the kit's menu items and large enough for a finger, with a title, a message and a cancel button apart. A context menu opens its items here on a touch screen.
13949
15816
 
@@ -14156,7 +16023,7 @@ Cancel, the way back and its default name come from `uiLocale.strings` (`cancel`
14156
16023
 
14157
16024
  # Layout
14158
16025
 
14159
- > Navigation · @motifx-community/ui 0.1.0-beta.0
16026
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
14160
16027
 
14161
16028
  Containers that place controls: `Stack` (a row or a column), `Grid` (rows and columns), `Panel` (a plain box that can scroll), `GroupBox` (a titled frame), `DockPanel` (children stuck to its edges) and `SplitContainer` (two panes and a splitter). All of them are controls: they disable and hide what is inside, and lay out children added at any time.
14162
16029
 
@@ -14582,7 +16449,7 @@ The only text the containers write is the splitter's name, `uiLocale.strings.res
14582
16449
 
14583
16450
  ```tsx
14584
16451
  import { reactive } from '@motifx/core';
14585
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
16452
+ import { Button, uiLocale } from '@motifx-community/ui';
14586
16453
  import { kitTexts } from '../../../shared/kit-texts';
14587
16454
 
14588
16455
  /** Switches the texts of the kit; the splitters on the page take the new name at once. */
@@ -14590,7 +16457,7 @@ export default function Localization() {
14590
16457
  const s = reactive({ lang: 'en' });
14591
16458
  const toggle = () => {
14592
16459
  s.lang = s.lang === 'en' ? 'tr' : 'en';
14593
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
16460
+ void uiLocale.use(s.lang);
14594
16461
  };
14595
16462
  return (
14596
16463
  <>
@@ -14740,11 +16607,417 @@ Every container also has the shared properties of `Control`: `enabled` / `disabl
14740
16607
  `ChildSettings` — the part that reads a child's settings from its props and follows children added later — is exported for containers of your own.
14741
16608
 
14742
16609
 
16610
+ ---
16611
+
16612
+ # ScrollView
16613
+
16614
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
16615
+
16616
+ Content that scrolls in a box of its own: the bars shown as told, a pull from the top that asks for what is new, a reach near the end that asks for more. Moved from code to a position or to an element.
16617
+
16618
+ ## Import
16619
+
16620
+ ```tsx
16621
+ import { ScrollView } from '@motifx-community/ui';
16622
+ ```
16623
+
16624
+ ## A box that scrolls
16625
+
16626
+ The JSX children are the content. `showScrollbar` says when the bars show; `scrollTo` and `scrollToElement` move the content from code, `onScrolled` tells where it stands.
16627
+
16628
+ ```tsx
16629
+ import { reactive } from '@motifx/core';
16630
+ import { Button, ScrollView, Stack, type ScrollViewBars } from '@motifx-community/ui';
16631
+
16632
+ const LINES = Array.from({ length: 40 }, (_, i) => `Line ${i + 1} of a long text that needs a box of its own to scroll in.`);
16633
+ const MODES: ScrollViewBars[] = ['onScroll', 'onHover', 'always', 'never'];
16634
+
16635
+ /** A box that scrolls, its bars shown as told; moved from code to a line and back to the top. */
16636
+ export default function Bars() {
16637
+ const s = reactive({ bars: 'onScroll' as ScrollViewBars, top: 0 });
16638
+ let view!: ScrollView;
16639
+ return (
16640
+ <Stack gap="md" style="inline-size: 100%">
16641
+ <Stack orientation="horizontal" wrap align="center">
16642
+ {MODES.map(mode => (
16643
+ <Button key={mode} text={mode} size="sm" variant={() => (s.bars === mode ? 'solid' : 'outline')} onclick={() => (s.bars = mode)} />
16644
+ ))}
16645
+ <Button text="Line 20" variant="outline" size="sm" onclick={() => view.scrollToElement(view.content.element.querySelectorAll('p')[19], true)} />
16646
+ <Button text="Top" variant="outline" size="sm" onclick={() => view.scrollTo(0, true)} />
16647
+ <output class="sv-top">{() => `scrollTop: ${Math.round(s.top)}`}</output>
16648
+ </Stack>
16649
+ <ScrollView ref={(v: ScrollView) => (view = v)} label="Long text" class="sv-text" showScrollbar={() => s.bars} style="block-size: 12rem" onScrolled={e => (s.top = e.top)}>
16650
+ {LINES.map(line => (
16651
+ <p key={line}>{line}</p>
16652
+ ))}
16653
+ </ScrollView>
16654
+ </Stack>
16655
+ );
16656
+ }
16657
+ ```
16658
+
16659
+ ## Pull to refresh
16660
+
16661
+ With `pullToRefresh`, the content pulled down from its top asks `onPullDown`. Set `promise` (or call `release()`) and the panel goes when the work is done.
16662
+
16663
+ ```tsx
16664
+ import { reactive } from '@motifx/core';
16665
+ import { Panel, ScrollView, Stack } from '@motifx-community/ui';
16666
+
16667
+ /** Pulled down from the top, the list asks for what is new and shows the panel until the promise settles. */
16668
+ export default function Pull() {
16669
+ const s = reactive({ notes: ['Welcome aboard', 'Your plan was renewed', 'A new comment on "Roadmap"'], count: 0 });
16670
+ const reload = () =>
16671
+ new Promise<void>(resolve =>
16672
+ setTimeout(() => {
16673
+ s.count++;
16674
+ s.notes = [`Fresh note ${s.count}`, ...s.notes];
16675
+ resolve();
16676
+ }, 1200)
16677
+ );
16678
+ return (
16679
+ <Stack gap="sm" style="inline-size: 100%">
16680
+ <span>Drag the list down from its top (a finger, or the mouse) and let go.</span>
16681
+ <ScrollView label="Notes" class="sv-notes" pullToRefresh onPullDown={e => (e.promise = reload())} style="block-size: 12rem">
16682
+ {s.notes.map(note => (
16683
+ <Panel key={note} variant="outline" padding="sm">
16684
+ {note}
16685
+ </Panel>
16686
+ ))}
16687
+ </ScrollView>
16688
+ </Stack>
16689
+ );
16690
+ }
16691
+ ```
16692
+
16693
+ ## Load more near the end
16694
+
16695
+ With `loadOnReachBottom`, a scroll within `reachBottomOffset` of the end asks `onReachBottom` once; `release()` lets the next reach ask again, `release(true)` says there is no more. Content that does not fill the box asks at once.
16696
+
16697
+ ```tsx
16698
+ import { reactive } from '@motifx/core';
16699
+ import { Panel, ScrollView, Stack } from '@motifx-community/ui';
16700
+
16701
+ const TOTAL = 60;
16702
+ const PAGE = 15;
16703
+
16704
+ // A page of rows, as a server would send them.
16705
+ const fetchRows = (from: number) =>
16706
+ new Promise<string[]>(resolve => setTimeout(() => resolve(Array.from({ length: Math.min(PAGE, TOTAL - from) }, (_, i) => `Order #${1000 + from + i}`)), 800));
16707
+
16708
+ /** Near the end the view asks for more; the indicator stays until the rows are in, and `release(true)` ends it for good when there is no more. */
16709
+ export default function More() {
16710
+ const s = reactive({ rows: [] as string[] });
16711
+ const more = () =>
16712
+ fetchRows(s.rows.length).then(rows => {
16713
+ s.rows = [...s.rows, ...rows];
16714
+ return s.rows.length >= TOTAL;
16715
+ });
16716
+ return (
16717
+ <Stack gap="sm" style="inline-size: 100%">
16718
+ <output class="sv-more-told">{() => (s.rows.length >= TOTAL ? `All ${TOTAL} orders are in.` : `${s.rows.length} of ${TOTAL} orders`)}</output>
16719
+ <ScrollView label="Orders" class="sv-orders" loadOnReachBottom reachBottomOffset={80} onReachBottom={e => more().then(done => e.release(done))} style="block-size: 14rem">
16720
+ {s.rows.map(row => (
16721
+ <Panel key={row} variant="outline" padding="sm">
16722
+ {row}
16723
+ </Panel>
16724
+ ))}
16725
+ </ScrollView>
16726
+ </Stack>
16727
+ );
16728
+ }
16729
+ ```
16730
+
16731
+ ## Behaviour
16732
+
16733
+ | Topic | How |
16734
+ | --- | --- |
16735
+ | `Scrolling` | The box scrolls with the wheel, the keys when focused, a finger, and from code. `direction` locks the other axis; the page behind does not scroll on when the content ends. |
16736
+ | `Scrollbars` | The design system’s bars. With `onScroll` the thumb shows while the content moves and goes a moment after; with `onHover` while the pointer is over the view or focus is in it; `always` leaves them; `never` hides them, the content still scrolls. |
16737
+ | `Pull to refresh` | From the top, with a finger or the pointer: the content comes down (harder the farther it goes) and the panel above it says to pull, then to release. Let go far enough it refreshes: the spinner turns until `release()` or the promise. A short pull goes back. |
16738
+ | `Load more` | Within `reachBottomOffset` of the end, `onReachBottom` is asked once; the panel under the content shows meanwhile. Released, the next reach asks again, until `release(true)`. Content that does not fill the box asks at once, and again as it grows. |
16739
+ | `Texts` | The kit’s, in the kit language, unless the text props say otherwise. |
16740
+
16741
+ ## Accessibility
16742
+
16743
+ | Topic | How |
16744
+ | --- | --- |
16745
+ | `Region` | A focusable box named by `label`; the arrow keys, Page Up/Down, Home and End scroll it as the browser does. |
16746
+ | `Panels` | Live regions: “Refreshing…” and “Loading…” are read when they appear. |
16747
+ | `Spinners` | Decorative; the texts say what is going on. |
16748
+ | `Motion` | A finger that pulls does not scroll the page; a finger that scrolls does not pull. |
16749
+
16750
+ ## Styling
16751
+
16752
+ | Hook | What it is |
16753
+ | --- | --- |
16754
+ | `.mx-scroll-view` | The box. `data-direction`, `data-bars`, `data-scrolling` while the content moves, `data-pull` when pulling is on, `data-pulling` during a pull, `data-pull-state` (`pull`, `release`, `refreshing`), `data-loading`. |
16755
+ | `.mx-scroll-view__content` | What holds the children; it moves down during a pull. |
16756
+ | `.mx-scroll-view__pull, .mx-scroll-view__pull-text, .mx-scroll-view__pull-spinner` | The panel above the content, its text and the kit’s spinner. |
16757
+ | `.mx-scroll-view__bottom, .mx-scroll-view__bottom-text, .mx-scroll-view__bottom-spinner` | The panel under the content while more loads. |
16758
+
16759
+ ### Component tokens
16760
+
16761
+ | Token | What it sets |
16762
+ | --- | --- |
16763
+ | `scroll-view.box` | Unit: the box (`focus`). |
16764
+ | `scroll-view.pull, .pull-text, .bottom, .bottom-text` | Units: the two panels (the pull one `release` and `refreshing`) and their texts. |
16765
+ | `scroll-view.panel-height, .panel-gap` | The panels’ height; the space between a panel’s spinner and its text. |
16766
+
16767
+ ## API reference
16768
+
16769
+ ### Props
16770
+
16771
+ | Prop | Type | Default | Description |
16772
+ | --- | --- | --- | --- |
16773
+ | `direction` | `Bind<ScrollViewDirection>` | `'vertical'` | `vertical`, `horizontal` or `both`: which way the content scrolls. |
16774
+ | `showScrollbar` | `Bind<ScrollViewBars>` | `'onScroll'` | When the bars show: `onScroll` while scrolling, `onHover` while the pointer is over the view, `always`, `never`. |
16775
+ | `pullToRefresh` | `Bind<boolean>` | `false` | Pulling the content down from its top asks `onPullDown` for what is new. |
16776
+ | `loadOnReachBottom` | `Bind<boolean>` | `false` | Scrolling near the end asks `onReachBottom` for more; so does content that does not reach the end. |
16777
+ | `reachBottomOffset` | `Bind<number>` | `100` | Pixels before the end at which `onReachBottom` is asked. |
16778
+ | `pullDownText, releaseText, refreshingText` | `Bind<string>` | the kit’s texts | The pull panel’s texts: while pulling, once far enough, while refreshing. |
16779
+ | `reachBottomText` | `Bind<string>` | the kit’s “Loading…” | The text under the content while more loads. |
16780
+ | `label` | `Bind<string>` | `''` | What screen readers call the scrolling region. |
16781
+
16782
+ ### Events, properties and methods
16783
+
16784
+ | Member | Kind | Description |
16785
+ | --- | --- | --- |
16786
+ | `onPullDown` | event | The content was pulled down and let go. Load what is new, then `release()`, or set `promise` and the panel goes when it settles. |
16787
+ | `onReachBottom` | event | The content was scrolled near its end. Load more, then `release()`; `release(true)` says there is no more and the view stops asking. A `promise` releases too. |
16788
+ | `onScrolled` | event | The position changed: `top`, `left`. |
16789
+ | `scrollTo(where, smooth?)` | `void` | To a top, or `{ top, left }`; `smooth` animates. |
16790
+ | `scrollBy({ top, left }, smooth?)` | `void` | By a distance. |
16791
+ | `scrollToElement(target, smooth?)` | `void` | Brings an element (or a component) of the content into view. |
16792
+ | `refresh(), release()` | `void` | Starts a refresh as a pull would; ends it. |
16793
+ | `loadMore(), update()` | `boolean` / `void` | Asks for more now; looks at the position again after the content changed. |
16794
+ | `scrollTop, scrollLeft` | read-only | Where the content stands. |
16795
+ | `isRefreshing, isLoading` | read-only | A refresh or a loading is going on. |
16796
+ | `content` | read-only | The element that holds the children, between the two panels. |
16797
+
16798
+
16799
+ ---
16800
+
16801
+ # Sortable
16802
+
16803
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
16804
+
16805
+ Items the user puts in order by dragging them, with the pointer or a finger, or with the keys; lists of one group take each other’s items. A drop moves the element and tells you the indexes: your data stays yours.
16806
+
16807
+ ## Import
16808
+
16809
+ ```tsx
16810
+ import { Sortable } from '@motifx-community/ui';
16811
+ ```
16812
+
16813
+ ## Children as items
16814
+
16815
+ The JSX children are the items. Drag one, or focus it and press Ctrl + Down; `onReorder` says from where to where, and the app reorders its own data.
16816
+
16817
+ ```tsx
16818
+ import { reactive } from '@motifx/core';
16819
+ import { Panel, Sortable, Stack } from '@motifx-community/ui';
16820
+
16821
+ /** Rows put in order by dragging, or with Ctrl + an arrow on the focused row; the app reorders its data when told. */
16822
+ export default function Basic() {
16823
+ const s = reactive({ steps: ['Collect the order', 'Pack it', 'Print the label', 'Hand it over'], told: '' });
16824
+ return (
16825
+ <Stack gap="md" style="inline-size: 100%">
16826
+ <Sortable
16827
+ label="Steps"
16828
+ class="so-steps"
16829
+ onReorder={e => {
16830
+ const next = s.steps.slice();
16831
+ next.splice(e.toIndex, 0, ...next.splice(e.fromIndex, 1));
16832
+ s.steps = next;
16833
+ s.told = `"${next[e.toIndex]}" is step ${e.toIndex + 1} now`;
16834
+ }}
16835
+ >
16836
+ <Panel variant="outline" padding="sm">
16837
+ Collect the order
16838
+ </Panel>
16839
+ <Panel variant="outline" padding="sm">
16840
+ Pack it
16841
+ </Panel>
16842
+ <Panel variant="outline" padding="sm">
16843
+ Print the label
16844
+ </Panel>
16845
+ <Panel variant="outline" padding="sm">
16846
+ Hand it over
16847
+ </Panel>
16848
+ </Sortable>
16849
+ <output class="so-told">{() => s.told || `Order: ${s.steps.join(' → ')}`}</output>
16850
+ </Stack>
16851
+ );
16852
+ }
16853
+ ```
16854
+
16855
+ ## Items from data, across lists
16856
+
16857
+ `items` with an `itemTemplate` draws the rows from your data and keeps each row as the order changes. Two sortables of one `group` take each other’s items: `onRemove` and `onAdd` tell both sides, and each list draws its array again.
16858
+
16859
+ ```tsx
16860
+ import { reactive } from '@motifx/core';
16861
+ import { Panel, Sortable, Stack } from '@motifx-community/ui';
16862
+
16863
+ interface Task {
16864
+ id: number;
16865
+ title: string;
16866
+ }
16867
+
16868
+ // A task as a row.
16869
+ const row = (task: Task) => {
16870
+ const panel = new Panel({ variant: 'outline', padding: 'sm' });
16871
+ panel.element.textContent = task.title;
16872
+ return panel;
16873
+ };
16874
+
16875
+ /** Two lists of one group take each other's items; each list draws its own data and the app moves the task between arrays when told. */
16876
+ export default function Groups() {
16877
+ const s = reactive({
16878
+ todo: [{ id: 1, title: 'Write the brief' }, { id: 2, title: 'Book the room' }, { id: 3, title: 'Send the invites' }] as Task[],
16879
+ done: [{ id: 4, title: 'Pick the date' }] as Task[]
16880
+ });
16881
+ const reorder = (key: 'todo' | 'done') => (e: { fromIndex: number; toIndex: number }) => {
16882
+ const next = s[key].slice();
16883
+ next.splice(e.toIndex, 0, ...next.splice(e.fromIndex, 1));
16884
+ s[key] = next;
16885
+ };
16886
+ // The item leaves one array when removed and joins the other when added: the lists draw themselves again.
16887
+ const remove = (key: 'todo' | 'done') => (e: { fromIndex: number }) => (s[key] = s[key].filter((_, i) => i !== e.fromIndex));
16888
+ const add = (key: 'todo' | 'done') => (e: { item: Task; toIndex: number }) => {
16889
+ const next = s[key].slice();
16890
+ next.splice(e.toIndex, 0, e.item);
16891
+ s[key] = next;
16892
+ };
16893
+ return (
16894
+ <Stack orientation="horizontal" gap="lg" style="inline-size: 100%">
16895
+ <Stack gap="sm" grow>
16896
+ <strong>To do</strong>
16897
+ <Sortable<Task> label="To do" class="so-todo" group="tasks" items={() => s.todo} itemTemplate={row} onReorder={reorder('todo')} onRemove={remove('todo')} onAdd={add('todo')} style="min-block-size: 8rem" />
16898
+ </Stack>
16899
+ <Stack gap="sm" grow>
16900
+ <strong>Done</strong>
16901
+ <Sortable<Task> label="Done" class="so-done" group="tasks" items={() => s.done} itemTemplate={row} onReorder={reorder('done')} onRemove={remove('done')} onAdd={add('done')} style="min-block-size: 8rem" />
16902
+ </Stack>
16903
+ </Stack>
16904
+ );
16905
+ }
16906
+ ```
16907
+
16908
+ ## A handle, side by side, a refused drag
16909
+
16910
+ ```tsx
16911
+ import { reactive } from '@motifx/core';
16912
+ import { Chip, Sortable, Stack } from '@motifx-community/ui';
16913
+
16914
+ /** Chips side by side, moved by their handle only (the dots), with Ctrl + Left / Right on the handle; a drag may be refused. */
16915
+ export default function Handle() {
16916
+ const s = reactive({ tags: ['Design', 'Build', 'Test', 'Ship', 'Locked'], told: '' });
16917
+ return (
16918
+ <Stack gap="md" style="inline-size: 100%">
16919
+ <Sortable
16920
+ label="Tags"
16921
+ class="so-tags"
16922
+ orientation="horizontal"
16923
+ handle=".so-grip"
16924
+ items={() => s.tags}
16925
+ itemTemplate={tag => {
16926
+ const chip = new Chip({ text: tag });
16927
+ const grip = document.createElement('span');
16928
+ grip.className = 'mx-glyph so-grip';
16929
+ grip.dataset.icon = 'drag-dots';
16930
+ grip.setAttribute('aria-label', `Move ${tag}`);
16931
+ chip.element.prepend(grip);
16932
+ return chip;
16933
+ }}
16934
+ onDragStarting={e => {
16935
+ if (e.item === 'Locked') {
16936
+ e.cancel = true;
16937
+ s.told = 'Locked stays where it is.';
16938
+ }
16939
+ }}
16940
+ onReorder={e => {
16941
+ const next = s.tags.slice();
16942
+ next.splice(e.toIndex, 0, ...next.splice(e.fromIndex, 1));
16943
+ s.tags = next;
16944
+ s.told = next.join(', ');
16945
+ }}
16946
+ />
16947
+ <output class="so-tags-told">{() => s.told}</output>
16948
+ </Stack>
16949
+ );
16950
+ }
16951
+ ```
16952
+
16953
+ ## Behaviour
16954
+
16955
+ | Topic | How |
16956
+ | --- | --- |
16957
+ | `Dragging` | With the pointer after a few pixels; with a finger after a long press (a finger that moves before that scrolls). A copy follows the pointer, the item stays faint in its place, a line shows where it would land; the list scrolls near its edges. |
16958
+ | `Dropping` | The item’s element moves there at once and `onReorder` says from where to where: your data is yours to reorder. Across sortables of a group, `onRemove` and `onAdd` say the same on both sides. |
16959
+ | `Items from data` | With `items`, each item keeps its component as the order changes (the rows are keyed by item): reordering your array moves the rows, no row is made again. |
16960
+ | `Keys` | The focused item (its handle when there is one) takes Ctrl + Up / Down (Left / Right side by side), Ctrl + Home / End; each move is told to `onReorder` and read out. |
16961
+ | `Escape` | Cancels a drag; nothing moves. |
16962
+
16963
+ ## Accessibility
16964
+
16965
+ | Topic | How |
16966
+ | --- | --- |
16967
+ | `List` | A `group` named by `label`; the items are whatever you put in it. |
16968
+ | `Items` | One Tab stop that moves between the items with the keys; an item with a focusable part of its own keeps that. A handle is a button named by you. |
16969
+ | `Moves` | Each move by the keys is read out: “Moved to 2 of 5”. |
16970
+
16971
+ ## Styling
16972
+
16973
+ | Hook | What it is |
16974
+ | --- | --- |
16975
+ | `.mx-sortable` | The list. `data-orientation`, `data-sortable`, `data-drop-target` while a dragged item may land here. |
16976
+ | `.mx-sortable__item` | Each item. `data-dragging` on the one being dragged. |
16977
+ | `.mx-sortable__line` | The line where a drop would land. |
16978
+ | `.mx-sortable__ghost` | The copy after the pointer. |
16979
+
16980
+ ### Component tokens
16981
+
16982
+ | Token | What it sets |
16983
+ | --- | --- |
16984
+ | `sortable.container, .item, .line, .ghost` | Units: the list (`target`), an item (`sortable`, `dragging`, `focus`), the line (its thickness and colour; standing in a horizontal list), the copy. |
16985
+ | `sortable.gap` | Between the items. |
16986
+
16987
+ ## API reference
16988
+
16989
+ ### Props
16990
+
16991
+ | Prop | Type | Default | Description |
16992
+ | --- | --- | --- | --- |
16993
+ | `items` | `Bind<readonly T[]>` | — | The items, each drawn with `itemTemplate`; without them the JSX children are the items. |
16994
+ | `itemTemplate` | `(item, index) => ComponentBase` | the item’s text | Makes an item’s component. A function, so it is not bound like the other props. |
16995
+ | `handle` | `Bind<string \| null>` | `null` | A selector inside an item that takes the drag and the keys; without one the whole item does. |
16996
+ | `group` | `Bind<string \| null>` | `null` | Sortables of one group take each other’s items. |
16997
+ | `allowReordering` | `Bind<boolean>` | `true` | The items can be moved; `false` leaves them as they are. |
16998
+ | `orientation` | `Bind<SortableOrientation>` | `'vertical'` | `vertical` or `horizontal`: the drop line and the move keys follow. |
16999
+ | `label` | `Bind<string>` | `''` | What screen readers call the list. |
17000
+
17001
+ ### Events, properties and methods
17002
+
17003
+ | Member | Kind | Description |
17004
+ | --- | --- | --- |
17005
+ | `onDragStarting` | event | A drag (or a move by the keys) is about to start (`item`, `fromIndex`); `cancel = true` refuses. |
17006
+ | `onDragChanging` | event | The place it would land changed (`to`, `toIndex`); `cancel = true` refuses that place. |
17007
+ | `onDragEnding` | event | About to drop; `cancel = true` leaves everything as it was. |
17008
+ | `onReorder` | event | An item moved within this sortable (`fromIndex`, `toIndex`, `item`), by a drop or the keys. Reorder your data here. |
17009
+ | `onRemove, onAdd` | event | An item went to another sortable of the group, and came into one: `from`, `to`, the indexes and the item. Move the data between your arrays here. |
17010
+ | `move(fromIndex, toIndex)` | `boolean` | Moves an item from code as a drop would, telling `onReorder`. |
17011
+ | `elements` | read-only | The items’ elements, in order. |
17012
+ | `isDragging` | read-only | An item is being dragged. |
17013
+ | `refresh()` | `void` | Reads the items again after they were changed in place. |
17014
+
17015
+
14743
17016
  ---
14744
17017
 
14745
17018
  # FormLayout
14746
17019
 
14747
- > Navigation · @motifx-community/ui 0.1.0-beta.0
17020
+ > Navigation · @motifx-community/ui 0.1.0-beta.2
14748
17021
 
14749
17022
  Lays out the fields of a data object on a grid. Each field gets an editor — by name, or by the type of its value — bound to the object both ways; groups, spans and buttons arrange them; sending the form checks every field first.
14750
17023
 
@@ -14866,7 +17139,7 @@ FormLayout.editors.set('color', (props) => new ColorPicker(props));
14866
17139
 
14867
17140
  # TreeView
14868
17141
 
14869
- > Data · @motifx-community/ui 0.1.0-beta.0
17142
+ > Data · @motifx-community/ui 0.1.0-beta.2
14870
17143
 
14871
17144
  A tree view shows items in a hierarchy. Rows open and close, are selected one or many at a time, can carry check boxes that add up to their parents, can be searched, and can load their children when they are first opened. Long trees draw only the rows in view.
14872
17145
 
@@ -15051,7 +17324,7 @@ The tree writes four texts, all from `uiLocale.strings`: `noItems` (nothing to s
15051
17324
 
15052
17325
  ```tsx
15053
17326
  import { reactive } from '@motifx/core';
15054
- import { Button, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
17327
+ import { Button, uiLocale } from '@motifx-community/ui';
15055
17328
  import { kitTexts } from '../../../shared/kit-texts';
15056
17329
 
15057
17330
  /** Switches the texts of the kit; the trees on the page follow at once. */
@@ -15059,7 +17332,7 @@ export default function Localization() {
15059
17332
  const s = reactive({ lang: 'en' });
15060
17333
  const toggle = () => {
15061
17334
  s.lang = s.lang === 'en' ? 'tr' : 'en';
15062
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
17335
+ void uiLocale.use(s.lang);
15063
17336
  };
15064
17337
  return (
15065
17338
  <>
@@ -15633,7 +17906,7 @@ export default function SizesAndLines() {
15633
17906
 
15634
17907
  # ListBox
15635
17908
 
15636
- > Data · @motifx-community/ui 0.1.0-beta.0
17909
+ > Data · @motifx-community/ui 0.1.0-beta.2
15637
17910
 
15638
17911
  A list that stays on the page. One item or several are chosen with the keys or the pointer; items come from memory or from a data source, can be searched and grouped, and long lists draw only the rows in view.
15639
17912
 
@@ -15797,14 +18070,14 @@ export const cities = ['Ankara', 'Antalya', 'Bursa', 'İstanbul', 'İzmir', 'Kon
15797
18070
 
15798
18071
  ```tsx
15799
18072
  import { reactive } from '@motifx/core';
15800
- import { Button, ListBox, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
18073
+ import { Button, ListBox, uiLocale } from '@motifx-community/ui';
15801
18074
 
15802
18075
  /** Switches the texts of every list on the page: “Select all”, the search box, “No items”. */
15803
18076
  export default function Localization() {
15804
18077
  const s = reactive({ lang: 'en' });
15805
18078
  const toggle = () => {
15806
18079
  s.lang = s.lang === 'en' ? 'tr' : 'en';
15807
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
18080
+ void uiLocale.use(s.lang);
15808
18081
  };
15809
18082
  return (
15810
18083
  <>
@@ -16011,7 +18284,7 @@ export default function Validation() {
16011
18284
 
16012
18285
  # TagBox
16013
18286
 
16014
- > Data · @motifx-community/ui 0.1.0-beta.0
18287
+ > Data · @motifx-community/ui 0.1.0-beta.2
16015
18288
 
16016
18289
  Picks several items. The chosen ones are tags in the field, followed by a text input that searches the list; items come from memory or from a data source, and typed text can become a tag of its own.
16017
18290
 
@@ -16352,7 +18625,7 @@ export default function Validation() {
16352
18625
 
16353
18626
  ```tsx
16354
18627
  import { reactive } from '@motifx/core';
16355
- import { Button, TagBox, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
18628
+ import { Button, TagBox, uiLocale } from '@motifx-community/ui';
16356
18629
  import { skills } from './skills';
16357
18630
 
16358
18631
  /** Switches the texts of every tag box on the page: remove buttons, “+3”, “Select all”. */
@@ -16360,7 +18633,7 @@ export default function Localization() {
16360
18633
  const s = reactive({ lang: 'en' });
16361
18634
  const toggle = () => {
16362
18635
  s.lang = s.lang === 'en' ? 'tr' : 'en';
16363
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
18636
+ void uiLocale.use(s.lang);
16364
18637
  };
16365
18638
  return (
16366
18639
  <>
@@ -16376,7 +18649,7 @@ export default function Localization() {
16376
18649
 
16377
18650
  # FilterBuilder
16378
18651
 
16379
- > Data · @motifx-community/ui 0.1.0-beta.0
18652
+ > Data · @motifx-community/ui 0.1.0-beta.2
16380
18653
 
16381
18654
  A filter builder lets people put a filter together by hand: groups joined by And, Or, Not And or Not Or, and conditions of a field, an operation and a value. Its value is the data layer's filter expression, so it goes to rows in memory and to every adapter as it is. The DataGrid opens it from its filter panel; on its own it serves a report screen or a saved search.
16382
18655
 
@@ -16950,7 +19223,7 @@ export default function CustomOperations() {
16950
19223
  ```tsx
16951
19224
  import { reactive } from '@motifx/core';
16952
19225
  import { data } from '@motifx-community/data';
16953
- import { Button, FilterBuilder, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
19226
+ import { Button, FilterBuilder, uiLocale } from '@motifx-community/ui';
16954
19227
  import { saleFields } from './sales';
16955
19228
 
16956
19229
  /** The builder's texts come from `uiLocale`; `texts` changes some for one builder only. */
@@ -16958,7 +19231,7 @@ export default function Localization() {
16958
19231
  const s = reactive({ lang: 'en' });
16959
19232
  const toggle = () => {
16960
19233
  s.lang = s.lang === 'en' ? 'tr' : 'en';
16961
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
19234
+ void uiLocale.use(s.lang);
16962
19235
  };
16963
19236
  return (
16964
19237
  <>
@@ -16981,7 +19254,7 @@ export default function Localization() {
16981
19254
 
16982
19255
  # TabDocumentManager
16983
19256
 
16984
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
19257
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
16985
19258
 
16986
19259
  A document manager in the way code editors arrange files: documents in tabs, tabs in groups, groups split side by side and one under the other. A document's content is any component, a form, a grid or plain text, and it is moved, never made again, when its tab goes to another group. Everything the user does is a method too, asks first and reports after; the whole layout saves to JSON and comes back. Preview and pinned tabs, sizes and copies are on [Tabs](tabdocs-tabs.md); context menus, lists and keys on [Menus and keys](tabdocs-menus.md).
16987
19260
 
@@ -17873,7 +20146,7 @@ export default function SaveRestore() {
17873
20146
 
17874
20147
  # TabDocumentManager: Tabs
17875
20148
 
17876
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
20149
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
17877
20150
 
17878
20151
  What a tab does in a code editor: preview tabs that the next preview replaces, pinned tabs that stay at the start, tabs that shrink, wrap or scroll, counts and colours, and the same document open in two groups.
17879
20152
 
@@ -18707,7 +20980,7 @@ export default function Duplicates() {
18707
20980
 
18708
20981
  # TabDocumentManager: Menus and keys
18709
20982
 
18710
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
20983
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
18711
20984
 
18712
20985
  The commands around the tabs: context menus on tabs and on the empty strip, a searchable list of a group's documents, the app's own toolbar buttons, the recently used list, back and forward, reopening what was closed, locked groups, and the keys for all of them.
18713
20986
 
@@ -19400,7 +21673,7 @@ export function customerCard(customer: Customer): ComponentBase {
19400
21673
 
19401
21674
  # TabDocumentManager: Drag and drop
19402
21675
 
19403
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
21676
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
19404
21677
 
19405
21678
  Tabs and whole groups dragged as in a code editor: along a strip, to another group, beside a group or along an edge of the layout, between two managers, and the same moves from the keyboard. Every drop goes through the methods and events of what it does.
19406
21679
 
@@ -19958,7 +22231,7 @@ export default function MoveWithKeys() {
19958
22231
 
19959
22232
  # TabDocumentManager: Dock and floating windows
19960
22233
 
19961
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
22234
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
19962
22235
 
19963
22236
  Documents and whole groups float in windows of their own in the page and dock again into the documents' groups or into dock areas around them, which fold to the manager's edge. The mouse, the keys and the code do the same, through the same events.
19964
22237
 
@@ -20839,7 +23112,7 @@ export function customerCard(customer: Customer): ComponentBase {
20839
23112
 
20840
23113
  # TabDocumentManager: New windows
20841
23114
 
20842
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
23115
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
20843
23116
 
20844
23117
  A document, a group or a floating window moves into a browser window of its own, and back. Its content moves with it, nothing is made again, and the new window is a part of the same manager: its tabs, menus, keys and drag work as they do here.
20845
23118
 
@@ -21500,7 +23773,7 @@ export default function WindowLayout() {
21500
23773
 
21501
23774
  # TabDocumentManager: Tablet and phone
21502
23775
 
21503
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
23776
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
21504
23777
 
21505
23778
  On a tablet and a phone a layout of groups, splits and dock areas does not fit as it is. The manager keeps the layout and shows it another way: the same documents, groups and areas, the same saved JSON, the content moved and never made again. It goes by its own width, not by the device; on a touch screen its tabs and buttons get larger.
21506
23779
 
@@ -21781,7 +24054,7 @@ The drawers and sheets are the kit's [Drawer](drawer.md) and [BottomSheet](botto
21781
24054
 
21782
24055
  # TabDocumentManager: A whole workspace
21783
24056
 
21784
- > TabDocumentManager · @motifx-community/ui 0.1.0-beta.0
24057
+ > TabDocumentManager · @motifx-community/ui 0.1.0-beta.2
21785
24058
 
21786
24059
  A whole screen made of the kit's parts: a menu bar, the manager, a DataGrid with everything turned on, forms and a tool docked at the bottom. Each part is the same component it is on its own page; the manager only holds them.
21787
24060
 
@@ -22194,7 +24467,7 @@ export function customerCard(customer: Customer): ComponentBase {
22194
24467
 
22195
24468
  # Scheduler
22196
24469
 
22197
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
24470
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
22198
24471
 
22199
24472
  Appointments over days and hours: day, week, work week and month views, all-day and multi-day bars, appointments at the same time side by side, and "+N more" where a day is full. From an array or a data source, with every setting live.
22200
24473
 
@@ -22790,7 +25063,7 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
22790
25063
 
22791
25064
  # Scheduler: Editing
22792
25065
 
22793
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
25066
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
22794
25067
 
22795
25068
  Appointments are added, moved, resized, copied and deleted with the pointer, the keys and code; every change asks its event first, can wait for a server, and goes back when saving fails.
22796
25069
 
@@ -23339,7 +25612,7 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
23339
25612
 
23340
25613
  # Scheduler: Recurrence and time zones
23341
25614
 
23342
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
25615
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
23343
25616
 
23344
25617
  Appointments that repeat by an RFC 5545 rule, with times left out and occurrences changed apart; a question on what a change reaches; an editor of the rule; and the days on the clock of any time zone, summer time included.
23345
25618
 
@@ -23763,7 +26036,7 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
23763
26036
 
23764
26037
  # Scheduler: Resources and groups
23765
26038
 
23766
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
26039
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
23767
26040
 
23768
26041
  Rooms, people and any other kind of resource: they colour the appointments, split the columns into groups (nested, or under each date), say when each one works and when nothing may be put in.
23769
26042
 
@@ -24469,7 +26742,7 @@ export class SlowAdapter<T extends object, K> extends data.ArrayAdapter<T, K> {
24469
26742
 
24470
26743
  # Scheduler: The appointment form
24471
26744
 
24472
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
26745
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
24473
26746
 
24474
26747
  The appointment form set up without events: which fields, in which order, in groups and tabs; editors of your own; checks per field; fields shown or locked for one appointment only. Or a form of your own.
24475
26748
 
@@ -25104,7 +27377,7 @@ export default function OwnForm() {
25104
27377
 
25105
27378
  # Scheduler: Timeline
25106
27379
 
25107
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
27380
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
25108
27381
 
25109
27382
  A row per resource with the time running along it: a day, a week, a work week or a month. Appointments at the same time stack in their row, and the row grows to fit them.
25110
27383
 
@@ -25740,7 +28013,7 @@ export default function TimelineTemplates() {
25740
28013
 
25741
28014
  # Scheduler: Agenda
25742
28015
 
25743
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
28016
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
25744
28017
 
25745
28018
  The coming days as a list: each day with its appointments in time order, a day with none left out.
25746
28019
 
@@ -26341,7 +28614,7 @@ export default function AgendaTemplates() {
26341
28614
 
26342
28615
  # Scheduler: Big data
26343
28616
 
26344
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
28617
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
26345
28618
 
26346
28619
  Thousands of resources and appointments: the scheduler builds only what is in view, and lays out only what changed.
26347
28620
 
@@ -26598,7 +28871,7 @@ export default function BigWeek() {
26598
28871
 
26599
28872
  # Scheduler: Tablet and phone
26600
28873
 
26601
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
28874
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
26602
28875
 
26603
28876
  On a tablet and a phone the scheduler keeps its appointments, views and date and shows them another way: a phone gets the agenda, a compact bar and sheets from the bottom; a finger lifts, resizes, swipes and pinches.
26604
28877
 
@@ -27266,7 +29539,7 @@ export default function Touch() {
27266
29539
 
27267
29540
  # Scheduler: iCalendar and print
27268
29541
 
27269
- > Scheduler · @motifx-community/ui 0.1.0-beta.0
29542
+ > Scheduler · @motifx-community/ui 0.1.0-beta.2
27270
29543
 
27271
29544
  Appointments out to an iCalendar file and back in (RFC 5545), for Outlook, Google Calendar and Apple Calendar; and the scheduler on paper.
27272
29545
 
@@ -27861,7 +30134,7 @@ export function sampleAppointments(): Meeting[] {
27861
30134
 
27862
30135
  # DataGrid
27863
30136
 
27864
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
30137
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
27865
30138
 
27866
30139
  A grid for data entry and large data: rows in memory or from any adapter of the data layer, a virtual list or pages, sorting, column layout, editing with the kit's editors, new rows with the Tab chain, three save modes, row actions, selection, filters, a search panel, grouping, summaries, a toolbar, lookup columns from other services, copy and paste, export and a layout that is kept — and every feature can be turned off, for the grid or for one column.
27867
30140
 
@@ -28227,7 +30500,7 @@ export default function Pager() {
28227
30500
 
28228
30501
  # DataGrid: Editing
28229
30502
 
28230
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
30503
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
28231
30504
 
28232
30505
  ## Editing and save modes
28233
30506
 
@@ -28768,7 +31041,7 @@ export default function BarActions() {
28768
31041
 
28769
31042
  # DataGrid: Edit forms and popups
28770
31043
 
28771
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
31044
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
28772
31045
 
28773
31046
  ## Edit forms and popups
28774
31047
 
@@ -29174,7 +31447,7 @@ export default function ValidationRules() {
29174
31447
 
29175
31448
  # DataGrid: Filtering and search
29176
31449
 
29177
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
31450
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
29178
31451
 
29179
31452
  ## Filters
29180
31453
 
@@ -29633,7 +31906,7 @@ export function makeCustomers(n: number): Customer[] {
29633
31906
 
29634
31907
  # DataGrid: Lookup columns
29635
31908
 
29636
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
31909
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
29637
31910
 
29638
31911
  ## Lookup columns
29639
31912
 
@@ -30000,7 +32273,7 @@ export default function TextFrom() {
30000
32273
 
30001
32274
  # DataGrid: Grouping and summaries
30002
32275
 
30003
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
32276
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
30004
32277
 
30005
32278
  ## Grouping
30006
32279
 
@@ -30423,7 +32696,7 @@ export default function SummariesServer() {
30423
32696
 
30424
32697
  # DataGrid: Master-detail
30425
32698
 
30426
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
32699
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
30427
32700
 
30428
32701
  ## Master-detail
30429
32702
 
@@ -30753,7 +33026,7 @@ export default function DetailTabs() {
30753
33026
 
30754
33027
  # DataGrid: Bands and adaptive columns
30755
33028
 
30756
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
33029
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
30757
33030
 
30758
33031
  ## Band headers
30759
33032
 
@@ -31074,7 +33347,7 @@ export default function AdaptiveColumns() {
31074
33347
 
31075
33348
  # DataGrid: Selection and export
31076
33349
 
31077
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
33350
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
31078
33351
 
31079
33352
  ## Selection
31080
33353
 
@@ -31677,7 +33950,7 @@ export default function PdfExport() {
31677
33950
 
31678
33951
  # DataGrid: Row drag and drop
31679
33952
 
31680
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
33953
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
31681
33954
 
31682
33955
  ## Reorder rows
31683
33956
 
@@ -32022,7 +34295,7 @@ export default function RowDragBetween() {
32022
34295
 
32023
34296
  # DataGrid: Selecting by dragging
32024
34297
 
32025
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
34298
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
32026
34299
 
32027
34300
  ## Rows
32028
34301
 
@@ -32352,7 +34625,7 @@ export default function CellRanges() {
32352
34625
 
32353
34626
  # DataGrid: Scrolling
32354
34627
 
32355
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
34628
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
32356
34629
 
32357
34630
  ## Scrolling modes
32358
34631
 
@@ -32704,7 +34977,7 @@ export default function InfiniteGroups() {
32704
34977
 
32705
34978
  # DataGrid: Layout and events
32706
34979
 
32707
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
34980
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
32708
34981
 
32709
34982
  ## Toolbar
32710
34983
 
@@ -33248,7 +35521,7 @@ export default function Events() {
33248
35521
 
33249
35522
  # DataGrid: API reference
33250
35523
 
33251
- > DataGrid · @motifx-community/ui 0.1.0-beta.0
35524
+ > DataGrid · @motifx-community/ui 0.1.0-beta.2
33252
35525
 
33253
35526
  ## Columns
33254
35527
 
@@ -33554,7 +35827,7 @@ The rows and their saving are the data layer's: `grid.dataSource` and `grid.chan
33554
35827
 
33555
35828
  ```tsx
33556
35829
  import { reactive } from '@motifx/core';
33557
- import { Button, DataGrid, enStrings, Stack, trStrings, uiLocale } from '@motifx-community/ui';
35830
+ import { Button, DataGrid, Stack, uiLocale } from '@motifx-community/ui';
33558
35831
  import { kitTexts } from '../../../shared/kit-texts';
33559
35832
  import type { Order } from './order';
33560
35833
  import { columns } from './orders';
@@ -33564,7 +35837,7 @@ export default function Localization() {
33564
35837
  const s = reactive({ lang: 'en' });
33565
35838
  const toggle = () => {
33566
35839
  s.lang = s.lang === 'en' ? 'tr' : 'en';
33567
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
35840
+ void uiLocale.use(s.lang);
33568
35841
  };
33569
35842
 
33570
35843
  return (