@wirecore/wirelayer-vue 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/{Checkbox-D9f77jtl.js → Checkbox-DS2qfQK1.js} +28 -30
  2. package/dist/ContextMenu-B6agwyf_.js +2311 -0
  3. package/dist/{Field-B1EsNF84.js → Field-Cqe2BG_x.js} +1 -1
  4. package/dist/{Highlight-Cg8DvCfq.js → Highlight-uwptdaUw.js} +35 -32
  5. package/dist/Input-C5dyvZfJ.js +183 -0
  6. package/dist/{InputStatus-D7kBGlew.js → InputStatus-Cgarj-yu.js} +16 -3
  7. package/dist/{Select-DAuYpE1c.js → Select-CeZbSy6K.js} +137 -112
  8. package/dist/Slider-Cpv7Vj3B.js +143 -0
  9. package/dist/Tree-DgHt0P5P.js +807 -0
  10. package/dist/chart.js +1 -1
  11. package/dist/components/Alert/Alert.vue.d.ts +5 -3
  12. package/dist/components/Alert/Alert.vue.d.ts.map +1 -1
  13. package/dist/components/AngleSlider/AngleSlider.vue.d.ts +2 -0
  14. package/dist/components/AngleSlider/AngleSlider.vue.d.ts.map +1 -1
  15. package/dist/components/Autocomplete/Autocomplete.vue.d.ts +2 -0
  16. package/dist/components/Autocomplete/Autocomplete.vue.d.ts.map +1 -1
  17. package/dist/components/Carousel/Carousel.vue.d.ts +2 -0
  18. package/dist/components/Carousel/Carousel.vue.d.ts.map +1 -1
  19. package/dist/components/CascadeSelect/CascadeSelect.vue.d.ts +2 -0
  20. package/dist/components/CascadeSelect/CascadeSelect.vue.d.ts.map +1 -1
  21. package/dist/components/Checkbox/Checkbox.vue.d.ts +28 -23
  22. package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -1
  23. package/dist/components/ColorInput/ColorInput.vue.d.ts.map +1 -1
  24. package/dist/components/ColorPicker/ColorPicker.vue.d.ts +2 -0
  25. package/dist/components/ColorPicker/ColorPicker.vue.d.ts.map +1 -1
  26. package/dist/components/Combobox/Combobox.vue.d.ts +11 -1
  27. package/dist/components/Combobox/Combobox.vue.d.ts.map +1 -1
  28. package/dist/components/CommandPalette/CommandPalette.vue.d.ts +1 -1
  29. package/dist/components/Confirm/ConfirmDialog.vue.d.ts +5 -0
  30. package/dist/components/Confirm/ConfirmDialog.vue.d.ts.map +1 -1
  31. package/dist/components/Confirm/confirm.d.ts +7 -0
  32. package/dist/components/Confirm/confirm.d.ts.map +1 -1
  33. package/dist/components/ContextMenu/ContextMenu.vue.d.ts +17 -1
  34. package/dist/components/ContextMenu/ContextMenu.vue.d.ts.map +1 -1
  35. package/dist/components/DatePicker/DatePicker.vue.d.ts +2 -0
  36. package/dist/components/DatePicker/DatePicker.vue.d.ts.map +1 -1
  37. package/dist/components/DatePicker/DatePickerBase.vue.d.ts +2 -0
  38. package/dist/components/DatePicker/DatePickerBase.vue.d.ts.map +1 -1
  39. package/dist/components/DateRangePicker/DateRangePicker.vue.d.ts +2 -0
  40. package/dist/components/DateRangePicker/DateRangePicker.vue.d.ts.map +1 -1
  41. package/dist/components/Dialog/Dialog.vue.d.ts +1 -1
  42. package/dist/components/Dialog/DialogContent.vue.d.ts +7 -0
  43. package/dist/components/Dialog/DialogContent.vue.d.ts.map +1 -1
  44. package/dist/components/Drawer/Drawer.vue.d.ts +1 -1
  45. package/dist/components/Drawer/DrawerContent.vue.d.ts +2 -0
  46. package/dist/components/Drawer/DrawerContent.vue.d.ts.map +1 -1
  47. package/dist/components/DurationInput/DurationInput.vue.d.ts +2 -0
  48. package/dist/components/DurationInput/DurationInput.vue.d.ts.map +1 -1
  49. package/dist/components/Fieldset/Fieldset.vue.d.ts +1 -1
  50. package/dist/components/FilterPanel/FilterPanel.vue.d.ts +1 -1
  51. package/dist/components/HoverCard/HoverCard.vue.d.ts +1 -1
  52. package/dist/components/IconButton/IconButton.vue.d.ts +2 -0
  53. package/dist/components/IconButton/IconButton.vue.d.ts.map +1 -1
  54. package/dist/components/Input/Input.vue.d.ts +3 -1
  55. package/dist/components/Input/Input.vue.d.ts.map +1 -1
  56. package/dist/components/Knob/Knob.vue.d.ts +2 -0
  57. package/dist/components/Knob/Knob.vue.d.ts.map +1 -1
  58. package/dist/components/Listbox/Listbox.vue.d.ts +2 -0
  59. package/dist/components/Listbox/Listbox.vue.d.ts.map +1 -1
  60. package/dist/components/MaskInput/MaskInput.vue.d.ts +2 -1
  61. package/dist/components/MaskInput/MaskInput.vue.d.ts.map +1 -1
  62. package/dist/components/Menu/Menu.vue.d.ts +9 -1
  63. package/dist/components/Menu/Menu.vue.d.ts.map +1 -1
  64. package/dist/components/Menu/state.d.ts +22 -0
  65. package/dist/components/Menu/state.d.ts.map +1 -1
  66. package/dist/components/MonthPicker/MonthPicker.vue.d.ts +2 -0
  67. package/dist/components/MonthPicker/MonthPicker.vue.d.ts.map +1 -1
  68. package/dist/components/MultiSelect/MultiSelect.vue.d.ts +2 -0
  69. package/dist/components/MultiSelect/MultiSelect.vue.d.ts.map +1 -1
  70. package/dist/components/NativeSelect/NativeSelect.vue.d.ts +26 -17
  71. package/dist/components/NativeSelect/NativeSelect.vue.d.ts.map +1 -1
  72. package/dist/components/NumberInput/NumberInput.vue.d.ts +3 -1
  73. package/dist/components/NumberInput/NumberInput.vue.d.ts.map +1 -1
  74. package/dist/components/Panel/Panel.vue.d.ts +1 -1
  75. package/dist/components/PasswordInput/PasswordInput.vue.d.ts +11 -3
  76. package/dist/components/PasswordInput/PasswordInput.vue.d.ts.map +1 -1
  77. package/dist/components/PinInput/PinInput.vue.d.ts +2 -0
  78. package/dist/components/PinInput/PinInput.vue.d.ts.map +1 -1
  79. package/dist/components/Popover/Popover.vue.d.ts +1 -1
  80. package/dist/components/Progress/Progress.vue.d.ts +11 -0
  81. package/dist/components/Progress/Progress.vue.d.ts.map +1 -1
  82. package/dist/components/RadioGroup/RadioGroup.vue.d.ts +24 -25
  83. package/dist/components/RadioGroup/RadioGroup.vue.d.ts.map +1 -1
  84. package/dist/components/RadioGroup/RadioGroupItem.vue.d.ts +2 -1
  85. package/dist/components/RadioGroup/RadioGroupItem.vue.d.ts.map +1 -1
  86. package/dist/components/RadioGroup/context.d.ts +4 -0
  87. package/dist/components/RadioGroup/context.d.ts.map +1 -0
  88. package/dist/components/Rating/Rating.vue.d.ts +2 -0
  89. package/dist/components/Rating/Rating.vue.d.ts.map +1 -1
  90. package/dist/components/SegmentedControl/SegmentedControl.vue.d.ts +23 -22
  91. package/dist/components/SegmentedControl/SegmentedControl.vue.d.ts.map +1 -1
  92. package/dist/components/Select/Select.vue.d.ts +11 -1
  93. package/dist/components/Select/Select.vue.d.ts.map +1 -1
  94. package/dist/components/SelectionCard/CheckboxCard.vue.d.ts +2 -0
  95. package/dist/components/SelectionCard/CheckboxCard.vue.d.ts.map +1 -1
  96. package/dist/components/Slider/Slider.vue.d.ts +2 -0
  97. package/dist/components/Slider/Slider.vue.d.ts.map +1 -1
  98. package/dist/components/Switch/Switch.vue.d.ts +2 -0
  99. package/dist/components/Switch/Switch.vue.d.ts.map +1 -1
  100. package/dist/components/TagsInput/TagsInput.vue.d.ts +2 -0
  101. package/dist/components/TagsInput/TagsInput.vue.d.ts.map +1 -1
  102. package/dist/components/Textarea/Textarea.vue.d.ts +3 -1
  103. package/dist/components/Textarea/Textarea.vue.d.ts.map +1 -1
  104. package/dist/components/TimePicker/TimePicker.vue.d.ts +2 -0
  105. package/dist/components/TimePicker/TimePicker.vue.d.ts.map +1 -1
  106. package/dist/components/TimeRangePicker/TimeRangePicker.vue.d.ts +2 -0
  107. package/dist/components/TimeRangePicker/TimeRangePicker.vue.d.ts.map +1 -1
  108. package/dist/components/Tooltip/Tooltip.vue.d.ts +3 -0
  109. package/dist/components/Tooltip/Tooltip.vue.d.ts.map +1 -1
  110. package/dist/components/TreeSelect/TreeSelect.vue.d.ts +2 -0
  111. package/dist/components/TreeSelect/TreeSelect.vue.d.ts.map +1 -1
  112. package/dist/components/YearPicker/YearPicker.vue.d.ts +2 -0
  113. package/dist/components/YearPicker/YearPicker.vue.d.ts.map +1 -1
  114. package/dist/data-table/DataTable.vue.d.ts +9 -1
  115. package/dist/data-table/DataTable.vue.d.ts.map +1 -1
  116. package/dist/data-table.js +1007 -994
  117. package/dist/editor.js +1 -1
  118. package/dist/form/FormField.vue.d.ts +3 -0
  119. package/dist/form/FormField.vue.d.ts.map +1 -1
  120. package/dist/form.js +8 -5
  121. package/dist/index.d.ts +2 -1
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +5834 -5626
  124. package/dist/label-for-eQvYjsM5.js +8 -0
  125. package/dist/pdf.js +3 -3
  126. package/dist/sources/ActionBar.css +1 -0
  127. package/dist/sources/AppShell.css +1 -0
  128. package/dist/sources/ChatPrompt.css +1 -0
  129. package/dist/sources/Gallery.css +1 -0
  130. package/dist/sources/IconButton.css +1 -0
  131. package/dist/sources/Image.css +1 -0
  132. package/dist/sources/ImageCropper.css +1 -0
  133. package/dist/sources/InlineEdit.css +1 -0
  134. package/dist/sources/Marquee.css +1 -0
  135. package/dist/sources/MegaMenu.css +1 -0
  136. package/dist/sources/Menubar.css +1 -0
  137. package/dist/sources/OrderList.css +1 -0
  138. package/dist/sources/PickList.css +1 -0
  139. package/dist/sources/ScrollTop.css +1 -0
  140. package/dist/{useTree-H8XsFHMk.js → useTree-UhG1TMeM.js} +1 -1
  141. package/dist/utils/label-for.d.ts +3 -0
  142. package/dist/utils/label-for.d.ts.map +1 -0
  143. package/dist/utils/list.d.ts +5 -0
  144. package/dist/utils/list.d.ts.map +1 -1
  145. package/dist/utils/text-field.d.ts +16 -0
  146. package/dist/utils/text-field.d.ts.map +1 -0
  147. package/dist/virtual/VirtualSelect.vue.d.ts +2 -0
  148. package/dist/virtual/VirtualSelect.vue.d.ts.map +1 -1
  149. package/dist/virtual.js +207 -197
  150. package/fonts.css +2 -0
  151. package/llms-full.txt +254 -23
  152. package/llms.txt +9 -5
  153. package/package.json +7 -3
  154. package/theme.css +14 -0
  155. package/dist/ContextMenu-C5JKyNlX.js +0 -2209
  156. package/dist/Input-BhnYMKjE.js +0 -168
  157. package/dist/Slider-CyoZc5A8.js +0 -135
  158. package/dist/Tree-DWxqSrO6.js +0 -789
package/llms-full.txt CHANGED
@@ -139,6 +139,10 @@ Message box with status colour, icon, title and text; role="alert" for errors an
139
139
  | --- | --- | --- |
140
140
  | @dismiss | – | |
141
141
 
142
+ | Slot | Slot props | Description |
143
+ | --- | --- | --- |
144
+ | #default | – | The message text |
145
+ | #actions | – | Buttons in the message, e.g. "Unlock" or "Reconnect" – beside the text, below it when there is little room |
142
146
 
143
147
  ### AngleSlider
144
148
 
@@ -161,6 +165,7 @@ Dial for an angle: the needle is the slider (arrow keys, Home/End), drag anywher
161
165
  | read-only? | `boolean` | |
162
166
  | invalid? | `boolean` | |
163
167
  | name? | `string` | |
168
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the angle slider, use a Field or aria-label |
164
169
  | classes? | `RecipeClasses<typeof angleSliderRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
165
170
 
166
171
  | Event | Payload | Description |
@@ -325,6 +330,7 @@ Free text with suggestions: type, arrow keys to pick a suggestion, Enter takes i
325
330
  | invalid? | `boolean` | |
326
331
  | required? | `boolean` | |
327
332
  | name? | `string` | |
333
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
328
334
  | classes? | `RecipeClasses<typeof comboboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
329
335
 
330
336
  | Event | Payload | Description |
@@ -725,6 +731,7 @@ Region "carousel" with slides labelled "Image n of m". Previous/next buttons, on
725
731
  | loop? | `boolean` | |
726
732
  | autoplay? | `boolean \| { delay: number }` | Turns pages by itself (default every 4 s) – always with a pause button (WCAG 2.2.2) |
727
733
  | indicators? | `boolean` | Dots below the slides, one per page |
734
+ | controls-position? | `'bottom' \| 'sides'` | Previous and next: in the row below the slides (`bottom`, default) or beside them, vertically centred (`sides`) |
728
735
  | v-model:page? | `number` | Current page – use with v-model:page |
729
736
  | default-page? | `number` | |
730
737
  | classes? | `RecipeClasses<typeof carouselRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
@@ -763,6 +770,7 @@ Select with cascading levels: a menu whose groups open to the side (arrow right/
763
770
  | size? | `'sm' \| 'md' \| 'lg'` | Height of the field: 32, 40 (default) or 48 px |
764
771
  | load-children? | `(option: CascadeOption<V>, request: { signal: AbortSignal }) => Promise<CascadeOption<V>[]>` | Loads the options of a level (`hasChildren: true`) when it opens; the signal aborts it |
765
772
  | data-source? | `DataSource<CascadeOption<V>>` | Source of the options of lazy levels (`getChildren`) |
773
+ | id? | `string` | Id of the field (the trigger, with `filter` the search field), e.g. for a `<label for>` |
766
774
  | classes? | `RecipeClasses<typeof cascadeSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
767
775
 
768
776
  | Event | Payload | Description |
@@ -969,18 +977,19 @@ Checkbox with label (also indeterminate), works inside Field
969
977
 
970
978
  | Prop | Type | Description |
971
979
  | --- | --- | --- |
972
- | v-model:checked? | `CheckedState` | Controlled state – use with v-model:checked |
973
- | default-checked? | `CheckedState` | |
980
+ | v-model:checked? | `C` | Controlled state – use with v-model:checked |
981
+ | default-checked? | `C` | |
974
982
  | disabled? | `boolean` | |
975
983
  | invalid? | `boolean` | |
976
984
  | required? | `boolean` | |
977
985
  | name? | `string` | |
978
986
  | value? | `string` | |
987
+ | id? | `string` | Id of the check box (the hidden input), e.g. for a `<label for>` |
979
988
  | classes? | `RecipeClasses<typeof checkboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
980
989
 
981
990
  | Event | Payload | Description |
982
991
  | --- | --- | --- |
983
- | v-model:checked | `checked: CheckedState` | |
992
+ | v-model:checked | `checked: C` | |
984
993
 
985
994
 
986
995
  ### CheckboxCard
@@ -1006,6 +1015,7 @@ A large card that is one checkbox: title (name), description and price (descript
1006
1015
  | invalid? | `boolean` | |
1007
1016
  | required? | `boolean` | |
1008
1017
  | name? | `string` | |
1018
+ | id? | `string` | Id of the check box (the hidden input), e.g. for a `<label for>` |
1009
1019
  | classes? | `RecipeClasses<typeof selectionCardRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1010
1020
 
1011
1021
  | Event | Payload | Description |
@@ -1225,6 +1235,7 @@ Colour field: the button opens a panel with area, hue (and opacity) slider, hex
1225
1235
  | read-only? | `boolean` | |
1226
1236
  | invalid? | `boolean` | |
1227
1237
  | name? | `string` | |
1238
+ | id? | `string` | Id of the field (the button), e.g. for a `<label for>` |
1228
1239
  | classes? | `RecipeClasses<typeof colorPickerRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1229
1240
 
1230
1241
  | Event | Payload | Description |
@@ -1299,6 +1310,9 @@ Text field with suggestions (autocomplete): type to filter, arrow keys to choose
1299
1310
  | data-source? | `DataSource<T>` | Loads the options for the typed text (after a typing pause, outdated answers dropped; pages while scrolling); `getItemsByKeys` gives the label of a chosen value that is not loaded |
1300
1311
  | min-search-length? | `number` | Fewest characters typed before the data source is asked |
1301
1312
  | page-size? | `number` | Options per request of the data source (default 50) |
1313
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
1314
+ | v-model:open? | `boolean` | Whether the list is open – use with v-model:open, or listen to update:open |
1315
+ | stop-key-propagation? | `boolean` | Keeps the keys the open list handles itself (Enter choosing, Escape closing, Tab leaving) from bubbling up – e.g. in a dialog with window shortcuts for Enter (save) and Escape (cancel) |
1302
1316
  | classes? | `RecipeClasses<typeof comboboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1303
1317
 
1304
1318
  | Event | Payload | Description |
@@ -1307,6 +1321,7 @@ Text field with suggestions (autocomplete): type to filter, arrow keys to choose
1307
1321
  | @input-value-change | `inputValue: string` | Every change of the text (typing, choosing, clearing) |
1308
1322
  | @filter-change | `text: string` | Typed text – e.g. to load matching items from a server (manualFilter) |
1309
1323
  | @load-more | – | The end of the list was scrolled into view (hasMore) |
1324
+ | v-model:open | `open: boolean` | The list opened or closed |
1310
1325
 
1311
1326
  | Slot | Slot props | Description |
1312
1327
  | --- | --- | --- |
@@ -1463,6 +1478,8 @@ Place once in the app; ask with `await confirm({ title, … })` or `await prompt
1463
1478
  | Prop | Type | Description |
1464
1479
  | --- | --- | --- |
1465
1480
  | close-label? | `string` | Accessible name of the close button |
1481
+ | confirm-button? | `ConfirmButtonOptions` | Look of the confirm button in every request (default: size sm, `primary`, `danger` for status danger) |
1482
+ | cancel-button? | `ConfirmButtonOptions` | Look of the cancel button in every request (default: size sm, `outline`) |
1466
1483
  | classes? | `RecipeClasses<typeof dialogRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1467
1484
 
1468
1485
 
@@ -1512,13 +1529,18 @@ Opens at the pointer on right click, on touch screens with a long press (and wit
1512
1529
  - Import: `import { ContextMenu } from '@wirecore/wirelayer-vue'`
1513
1530
  - Category: Overlays
1514
1531
  - Example: https://wirecore.github.io/WireLayer/?path=/story/vue_overlays-contextmenu--playground
1515
- - Also takes the props of: MenuItemOptions
1532
+ - Also takes the props of: MenuItemOptions, MenuBehaviorOptions
1516
1533
 
1517
1534
  | Prop | Type | Description |
1518
1535
  | --- | --- | --- |
1519
1536
  | items | `readonly MenuEntry[]` | Items, groups, separators, checkbox items, radio groups and submenus – as in Menu |
1520
1537
  | label? | `string` | Accessible name of the menu – without it the menu is named by the area's content |
1521
1538
  | link-as? | `Component \| string` | Component for link items, e.g. RouterLink or NuxtLink (gets `to` for items with `to`, else `href`); default <a> |
1539
+ | v-model:open? | `boolean` | Whether the menu is open – use with v-model:open, or listen to update:open (e.g. to pause list shortcuts) |
1540
+ | close-on-scroll? | `boolean` | Closes when the page (or a container) scrolls |
1541
+ | close-on-resize? | `boolean` | Closes when the window is resized |
1542
+ | close-on-blur? | `boolean` | Closes when the window loses the focus (switching to another window) |
1543
+ | highlight-first? | `boolean` | Highlights the first item when the menu opens, so Enter takes it (as in desktop context menus) |
1522
1544
  | classes? | `RecipeClasses<typeof menuRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1523
1545
 
1524
1546
  | Event | Payload | Description |
@@ -1526,6 +1548,8 @@ Opens at the pointer on right click, on touch screens with a long press (and wit
1526
1548
  | @select | `value: string` | |
1527
1549
  | @checked-change | `value: string, checked: boolean` | A checkbox item was switched |
1528
1550
  | @value-change | `name: string, value: string` | A radio group got a new value |
1551
+ | v-model:open | `open: boolean` | |
1552
+ | @before-open | `target: Element` | A right click, long press or the menu key is opening the menu, on this element (e.g. the row under the pointer – select it before the menu shows) |
1529
1553
 
1530
1554
  | Slot | Slot props | Description |
1531
1555
  | --- | --- | --- |
@@ -1645,6 +1669,8 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1645
1669
  | v-model:page? | `number` | Current page (1-based) – use with v-model:page |
1646
1670
  | v-model:first? | `number` | Index of the first row of the current page (0-based) – instead of `page`, use with v-model:first |
1647
1671
  | paginator-position? | `'top' \| 'bottom'` | Pagination below (default) or above the table |
1672
+ | paginator-edges? | `boolean` | Buttons to the first and the last page in the pagination |
1673
+ | paginator-align? | `DataTablePaginatorAlign` | Pagination row: rows per page at the start, pages at the end (`between`, default) – or both together |
1648
1674
  | v-model:sorting? | `DataTableSort \| DataTableSort[] \| null` | Current sorting – use with v-model:sorting; an array in the multiple mode |
1649
1675
  | default-sorting? | `DataTableSort \| DataTableSort[] \| null` | Sorting at the start, without v-model |
1650
1676
  | sort-mode? | `'single' \| 'multiple'` | `multiple`: Shift+click (or the column menu) sorts by further columns |
@@ -1670,6 +1696,7 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1670
1696
  | v-model:expanded? | `string[]` | Expanded rows (ids) – use with v-model:expanded; also the rows with open details (#expansion) |
1671
1697
  | default-expanded? | `string[]` | |
1672
1698
  | expand-label? | `(row: T, index: number) => string` | Names the expand button of a row |
1699
+ | row-expandable? | `(row: T) => boolean` | Whether a row has details (#expansion) – rows without get no expand button (default: all rows) |
1673
1700
  | advanced-filter? | `boolean \| ConditionField[]` | Advanced filter: the rows pass a condition tree (nested and/or rules; v-model:advanced-filter-value). `true` offers every column with a filter type; or pass the fields. A toolbar button opens the editor from the `#advancedFilter` slot above the table – usually `ConditionBuilder` from `@wirecore/wirelayer-blocks-vue`; without it there is no button (the tree still filters). A server filters instead: `dataSource` gets the tree as `condition`, with `manual` the parent applies it |
1674
1701
  | v-model:advanced-filter-value? | `ConditionGroup` | The condition tree of the advanced filter (controlled together with onAdvancedFilterValueChange) |
1675
1702
  | search? | `boolean` | Search field above the table: filters over all columns (v-model:global-filter) |
@@ -1710,6 +1737,7 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1710
1737
  | v-model:size? | `'sm' \| 'md' \| 'lg'` | Row height – use with v-model:size (`densityToggle`) |
1711
1738
  | density-toggle? | `boolean` | Menu above the table to change the row height |
1712
1739
  | gridlines? | `boolean` | Lines between the columns |
1740
+ | bordered? | `boolean` | A border around the whole table |
1713
1741
  | striped? | `boolean` | Every other row tinted |
1714
1742
  | fullscreen-toggle? | `boolean` | Button above the table to show it on the whole screen |
1715
1743
  | scroll-height? | `string` | Fixed height (CSS length): the table scrolls inside, header and footer stay visible |
@@ -1855,6 +1883,7 @@ Date field: type the digits one after another (the separators come from the loca
1855
1883
  | time-zone? | `string` | IANA zone ("Europe/Berlin") of a date with time: shown and typed in the zone, the value gets its offset |
1856
1884
  | show-time-zone? | `boolean` | Short zone name after the time ("CEST") |
1857
1885
  | responsive? | `boolean` | On narrow screens the calendar opens as a sheet at the bottom |
1886
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
1858
1887
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
1859
1888
 
1860
1889
  | Event | Payload | Description |
@@ -1903,6 +1932,7 @@ Start and end in one field ("10/20/2026 – 10/24/2026"); the calendar picks sta
1903
1932
  | time-zone? | `string` | IANA zone ("Europe/Berlin") with withTime: shown and typed in the zone, the values get its offset |
1904
1933
  | show-time-zone? | `boolean` | Short zone name after the times ("CEST") |
1905
1934
  | responsive? | `boolean` | On narrow screens the calendar opens as a sheet at the bottom |
1935
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
1906
1936
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
1907
1937
 
1908
1938
  | Event | Payload | Description |
@@ -1980,6 +2010,8 @@ The modal window of a Dialog: title, description, focus trap, Escape closes
1980
2010
  | Prop | Type | Description |
1981
2011
  | --- | --- | --- |
1982
2012
  | title | `string` | |
2013
+ | hide-title? | `boolean` | The title only for screen readers – it still names the dialog (e.g. a video in a dialog) |
2014
+ | title-position? | `'body' \| 'header'` | `body` (default): the title below the header row; `header`: in the row of the close button, after a smaller icon, the header separated by a line (as on the Drawer) |
1983
2015
  | description? | `string` | |
1984
2016
  | icon? | `Component` | Icon component in the coloured box at the top |
1985
2017
  | status? | `DialogStatus` | |
@@ -2123,6 +2155,7 @@ The panel of a Drawer, sliding in from a side; title, focus trap, Escape closes
2123
2155
  | Prop | Type | Description |
2124
2156
  | --- | --- | --- |
2125
2157
  | title | `string` | |
2158
+ | hide-title? | `boolean` | The title only for screen readers – it still names the drawer (e.g. a video in a dialog) |
2126
2159
  | description? | `string` | |
2127
2160
  | placement? | `DrawerPlacement` | |
2128
2161
  | size? | `OverlaySize` | Width (left/right: sm 320px, md 420px, lg 560px, xl 720px) or height (top/bottom: 30–85 % of the screen); `full` covers the whole screen. Without it 420px wide or as high as the content |
@@ -2169,6 +2202,7 @@ Duration field: hours and minutes (optional days and seconds) as spin buttons
2169
2202
  | name? | `string` | |
2170
2203
  | size? | `'sm' \| 'md' \| 'lg'` | |
2171
2204
  | clearable? | `boolean` | Clear button in the field while it has a value |
2205
+ | id? | `string` | Id of the field (the group of parts); a `<label for>` cannot name it, use a Field or aria-label |
2172
2206
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the field (see the datePicker recipe) |
2173
2207
 
2174
2208
  | Event | Payload | Description |
@@ -2593,6 +2627,7 @@ Label, helper text, error, aria-invalid and aria-describedby come from Field
2593
2627
  | required? | `boolean` | |
2594
2628
  | optional? | `boolean` | "(optional)" after the label |
2595
2629
  | disabled? | `boolean` | |
2630
+ | classes? | `RecipeClasses<typeof fieldRecipe>` | Extra classes per part of the Field, e.g. { label: "…" } (see the field recipe) |
2596
2631
 
2597
2632
  | Slot | Slot props | Description |
2598
2633
  | --- | --- | --- |
@@ -2867,6 +2902,7 @@ Button with only an icon; the label is its accessible name, optionally with a co
2867
2902
  | size? | `ButtonSize` | `xs` is 24px – the minimum target size (WCAG 2.5.8) |
2868
2903
  | shape? | `ButtonShape` | Corner shape: `pill` (round, default), `rounded` or `square` |
2869
2904
  | disabled? | `boolean` | |
2905
+ | loading? | `boolean` | Shows a spinner instead of the icon and ignores clicks; stays focusable (aria-disabled + aria-busy) |
2870
2906
  | type? | `'button' \| 'submit' \| 'reset'` | |
2871
2907
  | badge? | `number \| boolean` | Counter (number > 0) or dot (true) in the top-right corner |
2872
2908
  | badge-label? | `(count: string \| null) => string` | Appended to the accessible name while a badge is shown, e.g. "Notifications, 4 new". Receives the visible counter text ("4", "99+") or null for the dot – the visible text must stay part of the name (WCAG 2.5.3). |
@@ -2998,7 +3034,7 @@ Shows a value as a button; activating it swaps in the editor (Escape closes it)
2998
3034
 
2999
3035
  ### Input
3000
3036
 
3001
- Text field with sizes, leading icon, prefix and suffix; works inside Field
3037
+ Text field with sizes, leading icon, prefix and suffix; works inside Field. `ref` reaches the native input (focus, select, setSelectionRange)
3002
3038
 
3003
3039
  - Import: `import { Input } from '@wirecore/wirelayer-vue'`
3004
3040
 
@@ -3017,6 +3053,7 @@ Text field with sizes, leading icon, prefix and suffix; works inside Field
3017
3053
  | leading-icon? | `Component` | Icon component rendered inside the field, before the text |
3018
3054
  | prefix? | `string` | Static text segment before the input, e.g. `https://` |
3019
3055
  | suffix? | `string` | Static text segment after the input, e.g. `.de` |
3056
+ | mono? | `boolean` | Monospace font of the theme (JetBrains Mono) – for paths, tokens, codes, URLs and keys |
3020
3057
  | classes? | `RecipeClasses<typeof inputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3021
3058
 
3022
3059
  | Event | Payload | Description |
@@ -3189,6 +3226,7 @@ Dial (270°): a slider – arrow keys, Page Up/Down, Home/End, or drag around th
3189
3226
  | size? | `'sm' \| 'md' \| 'lg'` | |
3190
3227
  | disabled? | `boolean` | |
3191
3228
  | name? | `string` | |
3229
+ | id? | `string` | Id of the dial (the slider); a `<label for>` cannot name it, use `label`, a Field or aria-label |
3192
3230
  | classes? | `RecipeClasses<typeof knobRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3193
3231
 
3194
3232
  | Event | Payload | Description |
@@ -3280,6 +3318,7 @@ Always visible list (role="listbox"): arrow keys move, Enter/Space choose, typin
3280
3318
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
3281
3319
  | page-size? | `number` | Options per request of the data source (default 50) |
3282
3320
  | draggable-items? | `boolean` | The options can be dragged (`draggable`, `data-value` is the key) – lists that exchange items (PickList) |
3321
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the list box, use a Field or aria-label |
3283
3322
  | classes? | `RecipeClasses<typeof listboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3284
3323
 
3285
3324
  | Event | Payload | Description |
@@ -3530,7 +3569,7 @@ The trigger is the slotted element (e.g. a Button or IconButton)
3530
3569
  - Import: `import { Menu } from '@wirecore/wirelayer-vue'`
3531
3570
  - Category: Overlays
3532
3571
  - Example: https://wirecore.github.io/WireLayer/?path=/story/vue_overlays-menu--playground
3533
- - Also takes the props of: MenuItemOptions
3572
+ - Also takes the props of: MenuItemOptions, MenuBehaviorOptions
3534
3573
 
3535
3574
  | Prop | Type | Description |
3536
3575
  | --- | --- | --- |
@@ -3543,6 +3582,10 @@ The trigger is the slotted element (e.g. a Button or IconButton)
3543
3582
  | placement? | `PopoverPlacement` | Side of the trigger the menu opens on, e.g. `bottom-end` for a menu at the right edge (default bottom-start) |
3544
3583
  | arrow? | `boolean` | Arrow pointing at the trigger, as on the Popover |
3545
3584
  | link-as? | `Component \| string` | Component for link items, e.g. RouterLink or NuxtLink (gets `to` for items with `to`, else `href`); default <a> |
3585
+ | close-on-scroll? | `boolean` | Closes when the page (or a container) scrolls – e.g. for a menu opened at a point |
3586
+ | close-on-resize? | `boolean` | Closes when the window is resized |
3587
+ | close-on-blur? | `boolean` | Closes when the window loses the focus (switching to another window) |
3588
+ | highlight-first? | `boolean` | Highlights the first item also when the menu opens by pointer, so Enter takes it (as in desktop menus) |
3546
3589
  | classes? | `RecipeClasses<typeof menuRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3547
3590
 
3548
3591
  | Event | Payload | Description |
@@ -3677,6 +3720,7 @@ Month field ("10.2026"): type the digits in one go, or pick from the month grid;
3677
3720
  | placeholder? | `string` | Text of the empty field, shown until it gets the focus – no replacement for a label |
3678
3721
  | size? | `'sm' \| 'md' \| 'lg'` | |
3679
3722
  | clearable? | `boolean` | Clear button in the field while it has a value |
3723
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
3680
3724
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
3681
3725
 
3682
3726
  | Event | Payload | Description |
@@ -3726,6 +3770,7 @@ Select with several values: the list stays open while choosing, Space/Enter togg
3726
3770
  | data-source? | `DataSource<T>` | Loads the options when the list opens (pages while scrolling; with `filter` the search asks it, after a typing pause, outdated answers dropped); `getItemsByKeys` gives the labels of chosen values that are not loaded |
3727
3771
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
3728
3772
  | page-size? | `number` | Options per request of the data source (default 50) |
3773
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
3729
3774
  | classes? | `RecipeClasses<typeof multiSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3730
3775
 
3731
3776
  | Event | Payload | Description |
@@ -3750,8 +3795,8 @@ The browser's select: its own keyboard and mobile pickers; inside a Field it is
3750
3795
 
3751
3796
  | Prop | Type | Description |
3752
3797
  | --- | --- | --- |
3753
- | items | `readonly NativeSelectOption[]` | |
3754
- | v-model? (modelValue) | `string` | Chosen value – use with v-model |
3798
+ | items | `readonly NativeSelectOption<V>[]` | |
3799
+ | v-model? (modelValue) | `V \| ''` | Chosen value – use with v-model; the placeholder option gives an empty string |
3755
3800
  | placeholder? | `string` | First, empty option, e.g. "Please choose" |
3756
3801
  | size? | `Size` | |
3757
3802
  | invalid? | `boolean` | |
@@ -3760,7 +3805,7 @@ The browser's select: its own keyboard and mobile pickers; inside a Field it is
3760
3805
 
3761
3806
  | Event | Payload | Description |
3762
3807
  | --- | --- | --- |
3763
- | v-model | `value: string` | |
3808
+ | v-model | `value: V \| ''` | |
3764
3809
 
3765
3810
 
3766
3811
  ### NavigationMenu
@@ -3847,7 +3892,7 @@ A number in the format of the locale ("€1,234.50")
3847
3892
 
3848
3893
  ### NumberInput
3849
3894
 
3850
- Number field with − / + buttons, arrow keys and locale formatting ("1,234.5")
3895
+ Number field with − / + buttons, arrow keys and locale formatting ("1,234.5"); `ref` reaches the native input
3851
3896
 
3852
3897
  - Import: `import { NumberInput } from '@wirecore/wirelayer-vue'`
3853
3898
  - Category: Forms
@@ -3882,6 +3927,7 @@ Number field with − / + buttons, arrow keys and locale formatting ("1,234.5")
3882
3927
  | loading? | `boolean` | Shows a spinner in the field and marks it busy (aria-busy) |
3883
3928
  | clearable? | `boolean` | Shows a button that empties the field while it has a value |
3884
3929
  | clear-label? | `string` | Accessible name of the clear button (default "Clear input") |
3930
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
3885
3931
  | classes? | `RecipeClasses<typeof numberInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3886
3932
 
3887
3933
  | Event | Payload | Description |
@@ -4086,7 +4132,7 @@ Card with a heading (and actions); toggleable: the heading holds a button with a
4086
4132
 
4087
4133
  ### PasswordInput
4088
4134
 
4089
- Password field with a button that shows/hides the password (named "Show/Hide password")
4135
+ Password field with a button that shows/hides the password (named "Show/Hide password"); `ref` reaches the native input
4090
4136
 
4091
4137
  - Import: `import { PasswordInput } from '@wirecore/wirelayer-vue'`
4092
4138
  - Category: Forms
@@ -4105,13 +4151,15 @@ Password field with a button that shows/hides the password (named "Show/Hide pas
4105
4151
  | name? | `string` | |
4106
4152
  | default-visible? | `boolean` | Initially show the password in plain text |
4107
4153
  | v-model:visible? | `boolean` | Whether the password is shown in plain text – use with v-model:visible |
4108
- | autocomplete? | `'current-password' \| 'new-password'` | |
4154
+ | autocomplete? | `'current-password' \| 'new-password' \| 'off' \| 'one-time-code'` | `current-password` (default) or `new-password` for the browser's password manager; `off` or `one-time-code` for secrets it should not offer to save (tokens, passphrases, master passwords, one-time codes) |
4109
4155
  | strength? | `boolean` | Strength meter below the field – for choosing a new password |
4110
4156
  | requirements? | `readonly PasswordRequirement[]` | Checklist below the field, updated while typing: each rule with its state (icon and text), linked to the input as its description |
4111
4157
  | loading? | `boolean` | Shows a spinner in the field and marks it busy (aria-busy) |
4112
4158
  | clearable? | `boolean` | Shows a button that empties the field while it has a value |
4113
4159
  | clear-label? | `string` | Accessible name of the clear button (default "Clear input") |
4114
4160
  | default-value? | `string` | Initial value without v-model |
4161
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
4162
+ | mono? | `boolean` | Monospace font of the theme (JetBrains Mono) – for tokens, passphrases and keys |
4115
4163
  | classes? | `RecipeClasses<typeof passwordInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4116
4164
 
4117
4165
  | Event | Payload | Description |
@@ -4291,6 +4339,7 @@ Code input (OTP, PIN): one box per character, typing moves on, pasting fills all
4291
4339
  | invalid? | `boolean` | |
4292
4340
  | disabled? | `boolean` | |
4293
4341
  | name? | `string` | |
4342
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the PIN input, use a Field or aria-label |
4294
4343
  | classes? | `RecipeClasses<typeof pinInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4295
4344
 
4296
4345
  | Event | Payload | Description |
@@ -4380,6 +4429,10 @@ Ark names the progressbar after its value; the label is the name, the value its
4380
4429
  | striped? | `boolean` | Diagonal stripes on the filled part |
4381
4430
  | animated? | `boolean` | Moving stripes (only without reduced motion) |
4382
4431
  | orientation? | `'horizontal' \| 'vertical'` | Vertical bar (fills the height of its parent) |
4432
+ | size? | `'xs' \| 'md'` | `xs`: a thin bar with small text, e.g. in a list or a status bar |
4433
+ | status? | `'info' \| 'success' \| 'warn' \| 'danger'` | Colour of the filled part by its state, e.g. `danger` for a failed transfer |
4434
+ | hide-label? | `boolean` | The label only for screen readers – it still names the progress bar |
4435
+ | bar-text? | `string` | Short text in the bar, e.g. "42 %", "waiting" or "failed" (a taller bar; horizontal, without segments or steps) – screen readers get it after the value |
4383
4436
  | classes? | `RecipeClasses<typeof progressRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4384
4437
 
4385
4438
 
@@ -4507,8 +4560,8 @@ One choice out of several (role="radiogroup", arrow keys), horizontal or vertica
4507
4560
 
4508
4561
  | Prop | Type | Description |
4509
4562
  | --- | --- | --- |
4510
- | v-model? (modelValue) | `string \| null` | Selected value – use with v-model |
4511
- | default-value? | `string \| null` | |
4563
+ | v-model? (modelValue) | `V \| null` | Selected value – use with v-model; numbers when the items have number values |
4564
+ | default-value? | `V \| null` | |
4512
4565
  | label? | `string` | Visible group label (otherwise pass aria-label – or place the group in a Field with a label) |
4513
4566
  | orientation? | `RadioGroupOrientation` | |
4514
4567
  | columns? | `number` | Cards in a grid with this many columns (one column on small screens) – for RadioCard |
@@ -4520,7 +4573,7 @@ One choice out of several (role="radiogroup", arrow keys), horizontal or vertica
4520
4573
 
4521
4574
  | Event | Payload | Description |
4522
4575
  | --- | --- | --- |
4523
- | v-model | `value: string \| null` | |
4576
+ | v-model | `value: V \| null` | |
4524
4577
 
4525
4578
 
4526
4579
  ### RadioGroupItem
@@ -4534,7 +4587,7 @@ One option of a RadioGroup
4534
4587
 
4535
4588
  | Prop | Type | Description |
4536
4589
  | --- | --- | --- |
4537
- | value | `string` | |
4590
+ | value | `string \| number` | Value of the option – a number makes the group's v-model a number |
4538
4591
  | disabled? | `boolean` | |
4539
4592
  | classes? | `RecipeClasses<typeof radioGroupRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4540
4593
 
@@ -4560,6 +4613,7 @@ Star rating: a radio group – arrow keys change the value, each star reads "3 s
4560
4613
  | label? | `string` | Visible label, also the group's accessible name |
4561
4614
  | size? | `'sm' \| 'md' \| 'lg'` | |
4562
4615
  | name? | `string` | |
4616
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the rating, use a Field or aria-label |
4563
4617
  | classes? | `RecipeClasses<typeof ratingRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4564
4618
 
4565
4619
  | Event | Payload | Description |
@@ -4835,8 +4889,8 @@ Few exclusive options as a segmented switch (radio group)
4835
4889
 
4836
4890
  | Prop | Type | Description |
4837
4891
  | --- | --- | --- |
4838
- | v-model? (modelValue) | `string \| null` | Selected value – use with v-model |
4839
- | default-value? | `string` | |
4892
+ | v-model? (modelValue) | `V \| null` | Selected value – use with v-model |
4893
+ | default-value? | `V` | |
4840
4894
  | label? | `string` | Accessible name of the group (visually hidden) – inside a Field with a label, the Field's label names it |
4841
4895
  | size? | `SegmentedControlSize` | |
4842
4896
  | disabled? | `boolean` | |
@@ -4845,7 +4899,7 @@ Few exclusive options as a segmented switch (radio group)
4845
4899
 
4846
4900
  | Event | Payload | Description |
4847
4901
  | --- | --- | --- |
4848
- | v-model | `value: string \| null` | |
4902
+ | v-model | `value: V \| null` | |
4849
4903
 
4850
4904
 
4851
4905
  ### SegmentedControlItem
@@ -4902,6 +4956,9 @@ Dropdown list for one option: arrow keys, typeahead, Escape; native select hidde
4902
4956
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
4903
4957
  | page-size? | `number` | Options per request of the data source (default 50) |
4904
4958
  | standalone? | `boolean` | Not labelled by a surrounding Field – for a second control inside it (e.g. PhoneInput's country) |
4959
+ | v-model:open? | `boolean` | Whether the list is open – use with v-model:open, or listen to update:open |
4960
+ | stop-key-propagation? | `boolean` | Keeps the keys the list handles itself (Enter choosing or opening, Escape closing, Tab leaving) from bubbling up – e.g. in a dialog with window shortcuts for Enter (save) and Escape (cancel) |
4961
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
4905
4962
  | classes? | `RecipeClasses<typeof selectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4906
4963
 
4907
4964
  | Event | Payload | Description |
@@ -4909,6 +4966,7 @@ Dropdown list for one option: arrow keys, typeahead, Escape; native select hidde
4909
4966
  | v-model | `value: V \| null` | |
4910
4967
  | @filter-change | `text: string` | Text of the search field (filter) – e.g. to load matching items from a server (manualFilter) |
4911
4968
  | @load-more | – | The end of the list was scrolled into view (hasMore) |
4969
+ | v-model:open | `open: boolean` | The list opened or closed |
4912
4970
 
4913
4971
  | Slot | Slot props | Description |
4914
4972
  | --- | --- | --- |
@@ -5089,6 +5147,7 @@ Range: "Price, Minimum" / "Price, Maximum"
5089
5147
  | label | `string` | Visible label, also the accessible name of the thumbs |
5090
5148
  | thumb-labels? | `readonly string[]` | Names of the thumbs of a range slider, read after the label |
5091
5149
  | show-value? | `boolean` | Shows the formatted value next to the label |
5150
+ | hide-label? | `boolean` | The label for screen readers only – it stays the accessible name of the thumbs |
5092
5151
  | format-value? | `(value: number) => string` | Formats the shown and announced value, e.g. (v) => `${v} %` |
5093
5152
  | disabled? | `boolean` | |
5094
5153
  | name? | `string` | |
@@ -5407,7 +5466,7 @@ Sticks to the top or bottom edge while its container scrolls
5407
5466
 
5408
5467
  ### Switch
5409
5468
 
5410
- Ark renders a plain checkbox; role="switch" makes screen readers announce it as a switch
5469
+ Without a text the label is left out: Ark names the input by it, an empty one would hide a <label for>
5411
5470
 
5412
5471
  - Import: `import { Switch } from '@wirecore/wirelayer-vue'`
5413
5472
  - Category: Forms
@@ -5429,6 +5488,7 @@ Ark renders a plain checkbox; role="switch" makes screen readers announce it as
5429
5488
  | required? | `boolean` | |
5430
5489
  | name? | `string` | |
5431
5490
  | value? | `string` | Value of the switch – inside a SwitchGroup its state comes from the group's value |
5491
+ | id? | `string` | Id of the switch (the hidden input), e.g. for a `<label for>` |
5432
5492
  | classes? | `RecipeClasses<typeof switchControlRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5433
5493
 
5434
5494
  | Event | Payload | Description |
@@ -5583,6 +5643,7 @@ Free entries: Enter or "," adds, Backspace on the empty field selects the last e
5583
5643
  | has-more? | `boolean` | More suggestions can be loaded: scrolling to the end of the list emits loadMore |
5584
5644
  | data-source? | `DataSource<string>` | Suggestions from a server instead of `suggestions`: asked with the typed text after a typing pause (outdated answers dropped), more while scrolling |
5585
5645
  | min-search-length? | `number` | Fewest characters the typed text needs before the data source is asked (default 1) |
5646
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
5586
5647
  | classes? | `RecipeClasses<typeof tagsInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5587
5648
 
5588
5649
  | Event | Payload | Description |
@@ -5594,7 +5655,7 @@ Free entries: Enter or "," adds, Backspace on the empty field selects the last e
5594
5655
 
5595
5656
  ### Textarea
5596
5657
 
5597
- Multi-line text field, optionally growing with the text (autoResize) and with a counter; works inside Field
5658
+ Multi-line text field, optionally growing with the text (autoResize) and with a counter; works inside Field. `ref` reaches the native textarea
5598
5659
 
5599
5660
  - Import: `import { Textarea } from '@wirecore/wirelayer-vue'`
5600
5661
  - Category: Forms
@@ -5616,6 +5677,7 @@ Multi-line text field, optionally growing with the text (autoResize) and with a
5616
5677
  | loading? | `boolean` | Shows a spinner in the corner and marks the field busy (aria-busy) |
5617
5678
  | clearable? | `boolean` | Shows a button that empties the field while it has text |
5618
5679
  | clear-label? | `string` | Accessible name of the clear button (default "Clear input") |
5680
+ | mono? | `boolean` | Monospace font of the theme (JetBrains Mono) – for keys, codes and logs |
5619
5681
  | classes? | `RecipeClasses<typeof textareaRecipe> & RecipeClasses<typeof textareaPartsRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipes textarea and textareaParts) |
5620
5682
 
5621
5683
  | Event | Payload | Description |
@@ -5716,6 +5778,7 @@ Time field: type the digits one after another ("1430"), arrow keys change hour o
5716
5778
  | time-zone? | `string` | IANA zone ("Europe/Berlin"): the time is typed in the zone, the value gets its offset ("14:30+02:00") |
5717
5779
  | reference-date? | `string` | Day whose offset applies with timeZone (ISO, default today) |
5718
5780
  | show-time-zone? | `boolean` | Short zone name after the time ("CEST") |
5781
+ | id? | `string` | Id of the field – the (first) time gets it; a `<label for>` cannot name it, use a Field or aria-label |
5719
5782
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5720
5783
 
5721
5784
  | Event | Payload | Description |
@@ -5747,6 +5810,7 @@ Start and end time in one field ("09:00 – 17:30"): typing runs on from start t
5747
5810
  | name? | `string` | Sent as name[0] and name[1] |
5748
5811
  | size? | `'sm' \| 'md' \| 'lg'` | |
5749
5812
  | clearable? | `boolean` | Clear button in the field while it has a value |
5813
+ | id? | `string` | Id of the field – the (first) time gets it; a `<label for>` cannot name it, use a Field or aria-label |
5750
5814
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the component (see the datePicker recipe) |
5751
5815
 
5752
5816
  | Event | Payload | Description |
@@ -5862,6 +5926,7 @@ No element of its own: the trigger is the slotted element
5862
5926
  | close-delay? | `number` | Delay before closing (ms); default 150 or that of the TooltipGroup |
5863
5927
  | interactive? | `boolean` | The pointer can move onto the tooltip without it closing (WCAG 1.4.13) |
5864
5928
  | follow-cursor? | `boolean` | Follows the mouse pointer over the trigger |
5929
+ | close-on-scroll? | `boolean` | Closes when the page (or a container around the trigger) scrolls – false keeps it open while scrolling |
5865
5930
  | disabled? | `boolean` | Never opens (e.g. Truncate while the text fits) – the trigger stays the same element |
5866
5931
  | classes? | `RecipeClasses<typeof tooltipRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5867
5932
 
@@ -6020,6 +6085,7 @@ Select whose options are a tree: the button opens the tree in a panel, choosing
6020
6085
  | size? | `'sm' \| 'md' \| 'lg'` | Height of the field: 32, 40 (default) or 48 px |
6021
6086
  | load-children? | `(node: TreeNode, request: { signal: AbortSignal }) => Promise<TreeNode[]>` | Loads the children of lazy nodes (`hasChildren: true`) when they open; they are kept while the field lives |
6022
6087
  | data-source? | `DataSource<TreeNode>` | Source of the children of lazy nodes (`getChildren`) |
6088
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
6023
6089
  | classes? | `RecipeClasses<typeof treeSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
6024
6090
 
6025
6091
  | Event | Payload | Description |
@@ -6122,6 +6188,7 @@ Select for any number of items – only the visible options are rendered.
6122
6188
  | data-source? | `DataSource<T>` | Loads the items from a server instead of `items`: the first page when it opens, more while scrolling, the search field asks the server (after a typing pause); labels of chosen values that are not loaded come from `getItemsByKeys` |
6123
6189
  | page-size? | `number` | Items per request of the data source (default 50) |
6124
6190
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
6191
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
6125
6192
 
6126
6193
  | Event | Payload | Description |
6127
6194
  | --- | --- | --- |
@@ -6297,6 +6364,7 @@ Year field ("2026"): type the digits, or pick from the year grid; range: start
6297
6364
  | placeholder? | `string` | Text of the empty field, shown until it gets the focus – no replacement for a label |
6298
6365
  | size? | `'sm' \| 'md' \| 'lg'` | |
6299
6366
  | clearable? | `boolean` | Clear button in the field while it has a value |
6367
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
6300
6368
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
6301
6369
 
6302
6370
  | Event | Payload | Description |
@@ -6503,6 +6571,29 @@ that render components, such as `confirm` or the DataTable feature `dateInput`,
6503
6571
  components warn in the console when the classes of a recipe they render are missing. Recipes you call yourself
6504
6572
  (`card()`) are not checked – add their files along with the import.
6505
6573
 
6574
+ **With Vite** (Vue, React, Nuxt, Astro) the plugin `@wirecore/wirelayer-recipes/vite` adds these files itself: it reads
6575
+ the imports from `@wirecore/wirelayer-*` in your source files and adds the files of the imported components and recipes
6576
+ to the CSS file that imports `theme.css` (or `styles-core.css`). Put it before Tailwind's plugin:
6577
+
6578
+ ```ts
6579
+ // vite.config.ts (Nuxt: vite.plugins in nuxt.config.ts, Astro: vite.plugins in astro.config.mjs)
6580
+ import tailwindcss from '@tailwindcss/vite';
6581
+ import { wirelayer } from '@wirecore/wirelayer-recipes/vite';
6582
+
6583
+ export default { plugins: [wirelayer(), tailwindcss()] };
6584
+ ```
6585
+
6586
+ ```css
6587
+ @import 'tailwindcss';
6588
+ @import '@wirecore/wirelayer-vue/theme.css'; /* the plugin adds the sources files here */
6589
+ @import '@wirecore/wirelayer-vue/fonts.css'; /* the WireLayer fonts – leave it out with a font of your own */
6590
+ ```
6591
+
6592
+ `theme.css` is the theme without fonts and without component classes: an app with its own font
6593
+ (`@theme { --font-sans: … }`) does not bundle Schibsted Grotesk and JetBrains Mono. Components the plugin cannot see –
6594
+ registered globally (`app.component(…)`) or imported automatically – trigger the warning above; import their files by
6595
+ hand. Next.js does not use Vite: there, list the files or use `styles.css`.
6596
+
6506
6597
  ### Usage
6507
6598
 
6508
6599
  ```vue
@@ -6535,9 +6626,13 @@ import { ArrowRight } from 'lucide-react';
6535
6626
  // nuxt.config.ts
6536
6627
  import tailwindcss from '@tailwindcss/vite';
6537
6628
 
6629
+ import { wirelayer } from '@wirecore/wirelayer-recipes/vite';
6630
+
6538
6631
  export default defineNuxtConfig({
6539
- css: ['~/assets/main.css'], // @import 'tailwindcss'; @import '@wirecore/wirelayer-vue/styles.css';
6540
- vite: { plugins: [tailwindcss()] },
6632
+ // main.css: @import 'tailwindcss'; @import '@wirecore/wirelayer-vue/theme.css';
6633
+ // @import '@wirecore/wirelayer-vue/fonts.css'; – or styles.css with all classes, without the plugin
6634
+ css: ['~/assets/main.css'],
6635
+ vite: { plugins: [wirelayer(), tailwindcss()] },
6541
6636
  });
6542
6637
  ```
6543
6638
 
@@ -6620,6 +6715,31 @@ Every component consists of named parts of its recipe (`base`, `icon`, `row`, `t
6620
6715
  The names are the exports of the recipes (`button`, `iconButton`, `dataTable` …) and are checked by TypeScript, as are
6621
6716
  the variants and parts. Your own components use the same through `useRecipe('button', button)`.
6622
6717
 
6718
+ `variants` adds classes for single values of a variant, `compoundVariants` for combinations – instead of selectors on
6719
+ the recipe's own classes, which break when they change:
6720
+
6721
+ ```ts
6722
+ const recipes: RecipeConfig = {
6723
+ // only the medium size: 42px high, 16px text
6724
+ button: {
6725
+ variants: { size: { md: { base: 'h-[2.625rem] text-base' } } },
6726
+ compoundVariants: [{ size: ['sm', 'md'], shape: 'rounded', classes: { base: 'rounded-md' } }],
6727
+ },
6728
+ input: { variants: { size: { md: { base: 'h-[2.625rem]' } }, invalid: { true: { base: 'border-2' } } } },
6729
+ };
6730
+ ```
6731
+
6732
+ Per part the classes come in this order: `classes`, the matching `variants` and `compoundVariants`, the states of the
6733
+ recipe, the overrides of states (`invalid: { true: … }`), and last the class passed to the component. Inner providers
6734
+ extend outer ones (classes of the same value are joined, the inner ones win).
6735
+
6736
+ Classes from a provider or `classes` change the look, not the states: the classes of an active state variant
6737
+ (`invalid`, `success`, `disabled`, `readOnly`, `current`, `selected`, `checked`, `loading`) are added after them, so a
6738
+ field with `classes: { base: 'border-line-2' }` still turns red when it is invalid. States that the components mark as
6739
+ attributes (`data-invalid:`, `data-disabled:`, `data-[state=checked]:`) win through their selector anyway. Only the
6740
+ class passed to the component itself (`class`/`className`) comes after the states – the way out when a single field
6741
+ should look different in every state.
6742
+
6623
6743
  ### Hooks and composables
6624
6744
 
6625
6745
  Around 40 hooks (React) and composables (Vue) with the same names and the same logic – for your own components and
@@ -6998,6 +7118,73 @@ WireLayer is licensed under the MIT license. The fonts shipped with `@wirecore/w
6998
7118
  JetBrains Mono) are licensed under the SIL Open Font License 1.1 (`dist/fonts/OFL.txt`). Optional peer dependencies such
6999
7119
  as `pdfjs-dist` (Apache-2.0), Chart.js, Tiptap and Shiki are installed by the app itself – with their own licenses.
7000
7120
 
7121
+ ### Components and APIs side by side
7122
+
7123
+ | PrimeVue | WireLayer |
7124
+ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
7125
+ | `<Button label icon="pi pi-x">` | the label as slot text, `:leading-icon` with a Lucide component (`@lucide/vue`) |
7126
+ | `severity` / `text` / `outlined` | `color` – or `variant="text"` / `variant="outline"` |
7127
+ | Icon button + `v-tooltip` | `<Tooltip content><IconButton :icon label /></Tooltip>` – `label` is the accessible name (often the tooltip text) |
7128
+ | `Button :loading` | `loading` on `Button` and `IconButton` (stays focusable, ignores clicks) |
7129
+ | `Card` with `#title`/`#content` | `Card` with the default slot and an own heading |
7130
+ | `InputText`, `Password`, `InputNumber`, `InputChips`, `SelectButton`, `RadioButton` | `Input`, `PasswordInput`, `NumberInput`, `TagsInput`, `SegmentedControl`, `RadioGroup` + `RadioGroupItem` |
7131
+ | `IconField` + `InputIcon` | `Input :leading-icon` |
7132
+ | `Select :options optionLabel optionValue` | `Select :items item-label item-value` (object values: `value-key`) |
7133
+ | `Message severity` | `Alert status` (`error` → `danger`) |
7134
+ | `Tag` | `Badge` |
7135
+ | `Dialog v-model:visible header` | `Dialog v-model:open` + `DialogContent title size` (`hide-title` keeps the title for screen readers only) |
7136
+ | `Toolbar` as a container | a plain `div` – WireLayer's `Toolbar` is `role="toolbar"` (one tab stop, arrow keys) |
7137
+ | `useToast().add({ severity, summary, detail, life })` | `toast({ type, title, description, duration })`, `<Toaster />` once in the app |
7138
+ | `useConfirm().require({ … })` | `await confirm({ title, description, … })`, `<ConfirmDialog />` once in the app |
7139
+ | `DataTable` + `Column` | `DataTable :columns` (column objects), `#cell-<id>`, `#expansion`, `v-model:page-size` |
7140
+ | `expandedRows` with a row toggler on some rows | `#expansion` + `row-expandable` |
7141
+ | `paginatorTemplate` (first/last page) | `paginator-edges`, `paginator-align` |
7142
+ | `showGridlines` (with the outer border) | `gridlines` + `bordered` |
7143
+ | `FilterMatchMode`, `filters` | `v-model:global-filter`, column `filter`/`filterOptions`, `filter-display="row"` |
7144
+ | `@primevue/forms` + `zodResolver` | TanStack Form with Zod directly as a Standard Schema, `FormField` + `bindInput`/`bindValue` |
7145
+ | `pt` (pass-through) | `classes` per part, `RecipesProvider` for all components below it |
7146
+ | Theme preset (`definePreset`) | `--wc-*` tokens, `defineTheme`, the component variables (_Foundations › Themes_) |
7147
+ | `darkModeSelector` (a class) | `data-mode` on `<html>` |
7148
+ | `tailwindcss-primeui` (`bg-surface-*`, `text-muted-color`) | semantic tokens: `bg-card`, `bg-bg-2`, `text-muted`, `border-line` … |
7149
+
7150
+ ### Pitfalls
7151
+
7152
+ - **An empty choice is `null`, not `''`.** For PrimeVue's Select `''` means "nothing chosen"; WireLayer's Select treats
7153
+ `''` as a value (it warns in development that it is not among the items). Use `null`.
7154
+ - **TanStack fields start with `''`.** A required text in Zod therefore needs `.min(1)` – `z.string()` alone accepts
7155
+ the empty field.
7156
+ - **Fonts:** set your own with `@theme { --font-sans: … }`. Import `theme.css` instead of `styles.css` (with the
7157
+ sources files, or the Vite plugin `@wirecore/wirelayer-recipes/vite`) so the WireLayer fonts are not bundled
7158
+ (_Getting started › Welcome › Smaller CSS_).
7159
+ - **Card spacing:** `Card` puts a `gap` between its direct children – wrap content that should sit tight in one
7160
+ element.
7161
+ - **Overrides go per part and per variant.** `classes: { base: 'rounded-md' }` reaches every size; only the medium size
7162
+ with `variants: { size: { md: { base: '…' } } }` – no selectors on the recipe's own classes. States such as `invalid`
7163
+ stay visible over such classes; only `class` on the component itself replaces them.
7164
+ - **Sizes and corners in one place:** the height, text and corners of buttons and fields per size, the corners of
7165
+ rounded buttons, the padding of cards and the backdrop of dialogs are CSS variables (`--wc-control-h-md` …).
7166
+ - **Labels:** wrap a control in `Field` (it links label, description and error). A native `<label for>` works with the
7167
+ control's own `id`; date fields, sliders and groups need `Field` or `aria-label`.
7168
+ - **Brand colours:** `checkTheme` lists the pairs below WCAG AA, `suggestThemeFixes` the nearest colours (and `on-*`
7169
+ colours) that meet them – an orange `primary` with white text, common in PrimeVue themes, does not.
7170
+
7171
+ ### Desktop apps (dense UI, many dialogs)
7172
+
7173
+ - **Focus from code:** the text fields expose `focus()`, `select()`, `setSelectionRange()` and the native input
7174
+ (`element`) through a template ref – no `$el.querySelector('input')`. In a dialog, mark the first field with
7175
+ `data-autofocus`: a `focus()` in `onMounted` is overridden by the dialog's focus trap.
7176
+ - **Window shortcuts in dialogs:** Enter/Escape listeners on `window` also get the keys of an open list. `Select` and
7177
+ `Combobox` take `stop-key-propagation` and report `v-model:open`; `ContextMenu` reports `v-model:open` and the
7178
+ right-clicked element (`@before-open`).
7179
+ - **Menus at a point:** `close-on-scroll`, `close-on-resize`, `close-on-blur`, and `highlight-first` so Enter takes the
7180
+ first item.
7181
+ - **Closable tabs** are built in: `TabsTrigger closable @close` – the close button is not nested in the tab, Delete
7182
+ closes the focused tab and the focus moves to its neighbour.
7183
+ - **Typed values:** `RadioGroup`, `SegmentedControl` and `NativeSelect` keep the type of the bound value (unions,
7184
+ numbers); `Checkbox` with a boolean model gives booleans.
7185
+ - **Compact parts:** `Progress size="xs"` with `hide-label`, `bar-text` and `status`; `Alert #actions`; `mono` on text
7186
+ fields; `DialogContent title-position="header"` puts the title next to the close button.
7187
+
7001
7188
  ### Custom theme
7002
7189
 
7003
7190
  A theme overrides any colors per mode. `themeToCss` generates the CSS for it,
@@ -7023,3 +7210,47 @@ writeFileSync('brand.css', themeToCss(brand));
7023
7210
  ```
7024
7211
 
7025
7212
  All bundled themes pass this check in both modes.
7213
+
7214
+ When a pair misses its contrast, `suggestThemeFixes` says how to fix it: per pair the nearest variant of a colour that
7215
+ meets it – its lightness moved in OKLCH, the hue kept – and, where text sits on the colour, a light or dark `on-*`
7216
+ colour. A suggestion never breaks a pair that passed:
7217
+
7218
+ ```ts
7219
+ import { suggestThemeFixes } from '@wirecore/wirelayer-tokens';
7220
+
7221
+ suggestThemeFixes(brand);
7222
+ // [{ name: 'primary: text-on-primary on bg-primary', mode: 'light', ratio: 2.6, min: 4.5,
7223
+ // color: { token: 'primary', value: '#a35c00', ratio: 4.5 },
7224
+ // on: { token: 'on-primary', value: '#050505', ratio: 8.1 } }, …]
7225
+ ```
7226
+
7227
+ ### Component sizes and shapes
7228
+
7229
+ Besides the colors, a few measures that a brand usually changes are CSS variables. Without them every component looks as
7230
+ before – their defaults are the values of the recipes. Set them on `:root` (all pages), on a `[data-theme]` or on any
7231
+ element (that part of the page):
7232
+
7233
+ ```css
7234
+ :root {
7235
+ --wc-control-h-md: 2.625rem; /* buttons and fields of the medium size: 42px */
7236
+ --wc-control-text-md: 1rem;
7237
+ --wc-control-radius-md: 0.375rem;
7238
+ --wc-button-radius: 0.375rem;
7239
+ --wc-card-p: 1.25rem;
7240
+ --wc-backdrop: rgb(0 0 0 / 0.4);
7241
+ }
7242
+ ```
7243
+
7244
+ | Variable | Default | Applies to |
7245
+ | ----------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7246
+ | `--wc-control-h-sm` / `-md` / `-lg` | `2rem` / `2.5rem` / `3rem` | Height of the sizes sm, md, lg: Button, IconButton, Input, NativeSelect, Select, MultiSelect, Combobox, NumberInput, PasswordInput, the date and time fields, ColorPicker, TagsInput (minimum) |
7247
+ | `--wc-control-radius-sm` / `-md` / `-lg` | `6px` / `8px` / `10px` | Corners of the fields above and of Textarea (not of buttons) |
7248
+ | `--wc-control-text-sm` / `-md` / `-lg` | `13px` / `15px` / `16px` | Text in the fields above and in Textarea |
7249
+ | `--wc-button-radius` | `8px` | Corners of Button and IconButton with `shape="rounded"` (`pill` and `square` stay) |
7250
+ | `--wc-card-p` | `1.5rem` | Padding of Card |
7251
+ | `--wc-backdrop` | `rgb(0 0 0 / 0.6)` | Dimming behind Dialog, Drawer and ConfirmDialog |
7252
+ | `--radius-card` / `--radius-panel` / `--radius-popup` | `20px` / `28px` / `12px` | Corners of cards, panels and popups (menus, lists, popovers) |
7253
+ | `--wc-dialog-w` | by `size` | Width of a DialogContent |
7254
+
7255
+ The rest – the padding of a dialog or of table cells, the size of a single variant – is set per part with `classes` or
7256
+ `RecipesProvider` (_Getting started › Welcome › Customizing_). The React Native components keep their fixed sizes.