@wirecore/wirelayer-vue 0.6.0 → 0.7.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 (120) hide show
  1. package/dist/{Checkbox-D9f77jtl.js → Checkbox-D175nhKK.js} +26 -22
  2. package/dist/ContextMenu-BEOEyUa6.js +2235 -0
  3. package/dist/{Highlight-Cg8DvCfq.js → Highlight-uwptdaUw.js} +35 -32
  4. package/dist/{Input-BhnYMKjE.js → Input-Cn5q0yVE.js} +48 -35
  5. package/dist/{Select-DAuYpE1c.js → Select-Bd2Vpr7G.js} +173 -164
  6. package/dist/Slider-Cpv7Vj3B.js +143 -0
  7. package/dist/{Tree-DWxqSrO6.js → Tree-fd9LXqgZ.js} +183 -180
  8. package/dist/chart.js +1 -1
  9. package/dist/components/AngleSlider/AngleSlider.vue.d.ts +2 -0
  10. package/dist/components/AngleSlider/AngleSlider.vue.d.ts.map +1 -1
  11. package/dist/components/Autocomplete/Autocomplete.vue.d.ts +2 -0
  12. package/dist/components/Autocomplete/Autocomplete.vue.d.ts.map +1 -1
  13. package/dist/components/Carousel/Carousel.vue.d.ts +2 -0
  14. package/dist/components/Carousel/Carousel.vue.d.ts.map +1 -1
  15. package/dist/components/CascadeSelect/CascadeSelect.vue.d.ts +2 -0
  16. package/dist/components/CascadeSelect/CascadeSelect.vue.d.ts.map +1 -1
  17. package/dist/components/Checkbox/Checkbox.vue.d.ts +2 -0
  18. package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -1
  19. package/dist/components/ColorInput/ColorInput.vue.d.ts.map +1 -1
  20. package/dist/components/ColorPicker/ColorPicker.vue.d.ts +2 -0
  21. package/dist/components/ColorPicker/ColorPicker.vue.d.ts.map +1 -1
  22. package/dist/components/Combobox/Combobox.vue.d.ts +2 -0
  23. package/dist/components/Combobox/Combobox.vue.d.ts.map +1 -1
  24. package/dist/components/Confirm/ConfirmDialog.vue.d.ts +5 -0
  25. package/dist/components/Confirm/ConfirmDialog.vue.d.ts.map +1 -1
  26. package/dist/components/Confirm/confirm.d.ts +7 -0
  27. package/dist/components/Confirm/confirm.d.ts.map +1 -1
  28. package/dist/components/DatePicker/DatePicker.vue.d.ts +2 -0
  29. package/dist/components/DatePicker/DatePicker.vue.d.ts.map +1 -1
  30. package/dist/components/DatePicker/DatePickerBase.vue.d.ts +2 -0
  31. package/dist/components/DatePicker/DatePickerBase.vue.d.ts.map +1 -1
  32. package/dist/components/DateRangePicker/DateRangePicker.vue.d.ts +2 -0
  33. package/dist/components/DateRangePicker/DateRangePicker.vue.d.ts.map +1 -1
  34. package/dist/components/Dialog/DialogContent.vue.d.ts +2 -0
  35. package/dist/components/Dialog/DialogContent.vue.d.ts.map +1 -1
  36. package/dist/components/Drawer/DrawerContent.vue.d.ts +2 -0
  37. package/dist/components/Drawer/DrawerContent.vue.d.ts.map +1 -1
  38. package/dist/components/DurationInput/DurationInput.vue.d.ts +2 -0
  39. package/dist/components/DurationInput/DurationInput.vue.d.ts.map +1 -1
  40. package/dist/components/IconButton/IconButton.vue.d.ts +2 -0
  41. package/dist/components/IconButton/IconButton.vue.d.ts.map +1 -1
  42. package/dist/components/Knob/Knob.vue.d.ts +2 -0
  43. package/dist/components/Knob/Knob.vue.d.ts.map +1 -1
  44. package/dist/components/Listbox/Listbox.vue.d.ts +2 -0
  45. package/dist/components/Listbox/Listbox.vue.d.ts.map +1 -1
  46. package/dist/components/MonthPicker/MonthPicker.vue.d.ts +2 -0
  47. package/dist/components/MonthPicker/MonthPicker.vue.d.ts.map +1 -1
  48. package/dist/components/MultiSelect/MultiSelect.vue.d.ts +2 -0
  49. package/dist/components/MultiSelect/MultiSelect.vue.d.ts.map +1 -1
  50. package/dist/components/NumberInput/NumberInput.vue.d.ts +2 -0
  51. package/dist/components/NumberInput/NumberInput.vue.d.ts.map +1 -1
  52. package/dist/components/PasswordInput/PasswordInput.vue.d.ts +2 -0
  53. package/dist/components/PasswordInput/PasswordInput.vue.d.ts.map +1 -1
  54. package/dist/components/PinInput/PinInput.vue.d.ts +2 -0
  55. package/dist/components/PinInput/PinInput.vue.d.ts.map +1 -1
  56. package/dist/components/RadioGroup/RadioGroup.vue.d.ts.map +1 -1
  57. package/dist/components/Rating/Rating.vue.d.ts +2 -0
  58. package/dist/components/Rating/Rating.vue.d.ts.map +1 -1
  59. package/dist/components/SegmentedControl/SegmentedControl.vue.d.ts.map +1 -1
  60. package/dist/components/Select/Select.vue.d.ts +2 -0
  61. package/dist/components/Select/Select.vue.d.ts.map +1 -1
  62. package/dist/components/SelectionCard/CheckboxCard.vue.d.ts +2 -0
  63. package/dist/components/SelectionCard/CheckboxCard.vue.d.ts.map +1 -1
  64. package/dist/components/Slider/Slider.vue.d.ts +2 -0
  65. package/dist/components/Slider/Slider.vue.d.ts.map +1 -1
  66. package/dist/components/Switch/Switch.vue.d.ts +2 -0
  67. package/dist/components/Switch/Switch.vue.d.ts.map +1 -1
  68. package/dist/components/TagsInput/TagsInput.vue.d.ts +2 -0
  69. package/dist/components/TagsInput/TagsInput.vue.d.ts.map +1 -1
  70. package/dist/components/TimePicker/TimePicker.vue.d.ts +2 -0
  71. package/dist/components/TimePicker/TimePicker.vue.d.ts.map +1 -1
  72. package/dist/components/TimeRangePicker/TimeRangePicker.vue.d.ts +2 -0
  73. package/dist/components/TimeRangePicker/TimeRangePicker.vue.d.ts.map +1 -1
  74. package/dist/components/Tooltip/Tooltip.vue.d.ts +3 -0
  75. package/dist/components/Tooltip/Tooltip.vue.d.ts.map +1 -1
  76. package/dist/components/TreeSelect/TreeSelect.vue.d.ts +2 -0
  77. package/dist/components/TreeSelect/TreeSelect.vue.d.ts.map +1 -1
  78. package/dist/components/YearPicker/YearPicker.vue.d.ts +2 -0
  79. package/dist/components/YearPicker/YearPicker.vue.d.ts.map +1 -1
  80. package/dist/data-table/DataTable.vue.d.ts +9 -1
  81. package/dist/data-table/DataTable.vue.d.ts.map +1 -1
  82. package/dist/data-table.js +1007 -994
  83. package/dist/editor.js +1 -1
  84. package/dist/form/FormField.vue.d.ts +3 -0
  85. package/dist/form/FormField.vue.d.ts.map +1 -1
  86. package/dist/form.js +7 -4
  87. package/dist/index.d.ts +1 -1
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +5674 -5521
  90. package/dist/label-for-eQvYjsM5.js +8 -0
  91. package/dist/pdf.js +2 -2
  92. package/dist/sources/ActionBar.css +1 -0
  93. package/dist/sources/AppShell.css +1 -0
  94. package/dist/sources/ChatPrompt.css +1 -0
  95. package/dist/sources/Gallery.css +1 -0
  96. package/dist/sources/IconButton.css +1 -0
  97. package/dist/sources/Image.css +1 -0
  98. package/dist/sources/ImageCropper.css +1 -0
  99. package/dist/sources/InlineEdit.css +1 -0
  100. package/dist/sources/Marquee.css +1 -0
  101. package/dist/sources/MegaMenu.css +1 -0
  102. package/dist/sources/Menubar.css +1 -0
  103. package/dist/sources/OrderList.css +1 -0
  104. package/dist/sources/PickList.css +1 -0
  105. package/dist/sources/ScrollTop.css +1 -0
  106. package/dist/{useTree-H8XsFHMk.js → useTree-UhG1TMeM.js} +1 -1
  107. package/dist/utils/label-for.d.ts +3 -0
  108. package/dist/utils/label-for.d.ts.map +1 -0
  109. package/dist/utils/list.d.ts +5 -0
  110. package/dist/utils/list.d.ts.map +1 -1
  111. package/dist/virtual/VirtualSelect.vue.d.ts +2 -0
  112. package/dist/virtual/VirtualSelect.vue.d.ts.map +1 -1
  113. package/dist/virtual.js +207 -197
  114. package/fonts.css +2 -0
  115. package/llms-full.txt +188 -3
  116. package/llms.txt +4 -1
  117. package/package.json +7 -3
  118. package/theme.css +14 -0
  119. package/dist/ContextMenu-C5JKyNlX.js +0 -2209
  120. package/dist/Slider-CyoZc5A8.js +0 -135
package/fonts.css ADDED
@@ -0,0 +1,2 @@
1
+ /* The WireLayer fonts (Schibsted Grotesk, JetBrains Mono) – part of styles.css and styles-core.css, separate for theme.css */
2
+ @import '@wirecore/wirelayer-tokens/fonts.css';
package/llms-full.txt CHANGED
@@ -161,6 +161,7 @@ Dial for an angle: the needle is the slider (arrow keys, Home/End), drag anywher
161
161
  | read-only? | `boolean` | |
162
162
  | invalid? | `boolean` | |
163
163
  | name? | `string` | |
164
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the angle slider, use a Field or aria-label |
164
165
  | classes? | `RecipeClasses<typeof angleSliderRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
165
166
 
166
167
  | Event | Payload | Description |
@@ -325,6 +326,7 @@ Free text with suggestions: type, arrow keys to pick a suggestion, Enter takes i
325
326
  | invalid? | `boolean` | |
326
327
  | required? | `boolean` | |
327
328
  | name? | `string` | |
329
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
328
330
  | classes? | `RecipeClasses<typeof comboboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
329
331
 
330
332
  | Event | Payload | Description |
@@ -725,6 +727,7 @@ Region "carousel" with slides labelled "Image n of m". Previous/next buttons, on
725
727
  | loop? | `boolean` | |
726
728
  | autoplay? | `boolean \| { delay: number }` | Turns pages by itself (default every 4 s) – always with a pause button (WCAG 2.2.2) |
727
729
  | indicators? | `boolean` | Dots below the slides, one per page |
730
+ | controls-position? | `'bottom' \| 'sides'` | Previous and next: in the row below the slides (`bottom`, default) or beside them, vertically centred (`sides`) |
728
731
  | v-model:page? | `number` | Current page – use with v-model:page |
729
732
  | default-page? | `number` | |
730
733
  | classes? | `RecipeClasses<typeof carouselRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
@@ -763,6 +766,7 @@ Select with cascading levels: a menu whose groups open to the side (arrow right/
763
766
  | size? | `'sm' \| 'md' \| 'lg'` | Height of the field: 32, 40 (default) or 48 px |
764
767
  | 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
768
  | data-source? | `DataSource<CascadeOption<V>>` | Source of the options of lazy levels (`getChildren`) |
769
+ | id? | `string` | Id of the field (the trigger, with `filter` the search field), e.g. for a `<label for>` |
766
770
  | classes? | `RecipeClasses<typeof cascadeSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
767
771
 
768
772
  | Event | Payload | Description |
@@ -976,6 +980,7 @@ Checkbox with label (also indeterminate), works inside Field
976
980
  | required? | `boolean` | |
977
981
  | name? | `string` | |
978
982
  | value? | `string` | |
983
+ | id? | `string` | Id of the check box (the hidden input), e.g. for a `<label for>` |
979
984
  | classes? | `RecipeClasses<typeof checkboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
980
985
 
981
986
  | Event | Payload | Description |
@@ -1006,6 +1011,7 @@ A large card that is one checkbox: title (name), description and price (descript
1006
1011
  | invalid? | `boolean` | |
1007
1012
  | required? | `boolean` | |
1008
1013
  | name? | `string` | |
1014
+ | id? | `string` | Id of the check box (the hidden input), e.g. for a `<label for>` |
1009
1015
  | classes? | `RecipeClasses<typeof selectionCardRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1010
1016
 
1011
1017
  | Event | Payload | Description |
@@ -1225,6 +1231,7 @@ Colour field: the button opens a panel with area, hue (and opacity) slider, hex
1225
1231
  | read-only? | `boolean` | |
1226
1232
  | invalid? | `boolean` | |
1227
1233
  | name? | `string` | |
1234
+ | id? | `string` | Id of the field (the button), e.g. for a `<label for>` |
1228
1235
  | classes? | `RecipeClasses<typeof colorPickerRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1229
1236
 
1230
1237
  | Event | Payload | Description |
@@ -1299,6 +1306,7 @@ Text field with suggestions (autocomplete): type to filter, arrow keys to choose
1299
1306
  | 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
1307
  | min-search-length? | `number` | Fewest characters typed before the data source is asked |
1301
1308
  | page-size? | `number` | Options per request of the data source (default 50) |
1309
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
1302
1310
  | classes? | `RecipeClasses<typeof comboboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1303
1311
 
1304
1312
  | Event | Payload | Description |
@@ -1463,6 +1471,8 @@ Place once in the app; ask with `await confirm({ title, … })` or `await prompt
1463
1471
  | Prop | Type | Description |
1464
1472
  | --- | --- | --- |
1465
1473
  | close-label? | `string` | Accessible name of the close button |
1474
+ | confirm-button? | `ConfirmButtonOptions` | Look of the confirm button in every request (default: size sm, `primary`, `danger` for status danger) |
1475
+ | cancel-button? | `ConfirmButtonOptions` | Look of the cancel button in every request (default: size sm, `outline`) |
1466
1476
  | classes? | `RecipeClasses<typeof dialogRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
1467
1477
 
1468
1478
 
@@ -1645,6 +1655,8 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1645
1655
  | v-model:page? | `number` | Current page (1-based) – use with v-model:page |
1646
1656
  | v-model:first? | `number` | Index of the first row of the current page (0-based) – instead of `page`, use with v-model:first |
1647
1657
  | paginator-position? | `'top' \| 'bottom'` | Pagination below (default) or above the table |
1658
+ | paginator-edges? | `boolean` | Buttons to the first and the last page in the pagination |
1659
+ | paginator-align? | `DataTablePaginatorAlign` | Pagination row: rows per page at the start, pages at the end (`between`, default) – or both together |
1648
1660
  | v-model:sorting? | `DataTableSort \| DataTableSort[] \| null` | Current sorting – use with v-model:sorting; an array in the multiple mode |
1649
1661
  | default-sorting? | `DataTableSort \| DataTableSort[] \| null` | Sorting at the start, without v-model |
1650
1662
  | sort-mode? | `'single' \| 'multiple'` | `multiple`: Shift+click (or the column menu) sorts by further columns |
@@ -1670,6 +1682,7 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1670
1682
  | v-model:expanded? | `string[]` | Expanded rows (ids) – use with v-model:expanded; also the rows with open details (#expansion) |
1671
1683
  | default-expanded? | `string[]` | |
1672
1684
  | expand-label? | `(row: T, index: number) => string` | Names the expand button of a row |
1685
+ | row-expandable? | `(row: T) => boolean` | Whether a row has details (#expansion) – rows without get no expand button (default: all rows) |
1673
1686
  | 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
1687
  | v-model:advanced-filter-value? | `ConditionGroup` | The condition tree of the advanced filter (controlled together with onAdvancedFilterValueChange) |
1675
1688
  | search? | `boolean` | Search field above the table: filters over all columns (v-model:global-filter) |
@@ -1710,6 +1723,7 @@ Data table on TanStack Table: sorting (also by several columns), search, filter
1710
1723
  | v-model:size? | `'sm' \| 'md' \| 'lg'` | Row height – use with v-model:size (`densityToggle`) |
1711
1724
  | density-toggle? | `boolean` | Menu above the table to change the row height |
1712
1725
  | gridlines? | `boolean` | Lines between the columns |
1726
+ | bordered? | `boolean` | A border around the whole table |
1713
1727
  | striped? | `boolean` | Every other row tinted |
1714
1728
  | fullscreen-toggle? | `boolean` | Button above the table to show it on the whole screen |
1715
1729
  | scroll-height? | `string` | Fixed height (CSS length): the table scrolls inside, header and footer stay visible |
@@ -1855,6 +1869,7 @@ Date field: type the digits one after another (the separators come from the loca
1855
1869
  | time-zone? | `string` | IANA zone ("Europe/Berlin") of a date with time: shown and typed in the zone, the value gets its offset |
1856
1870
  | show-time-zone? | `boolean` | Short zone name after the time ("CEST") |
1857
1871
  | responsive? | `boolean` | On narrow screens the calendar opens as a sheet at the bottom |
1872
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
1858
1873
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
1859
1874
 
1860
1875
  | Event | Payload | Description |
@@ -1903,6 +1918,7 @@ Start and end in one field ("10/20/2026 – 10/24/2026"); the calendar picks sta
1903
1918
  | time-zone? | `string` | IANA zone ("Europe/Berlin") with withTime: shown and typed in the zone, the values get its offset |
1904
1919
  | show-time-zone? | `boolean` | Short zone name after the times ("CEST") |
1905
1920
  | responsive? | `boolean` | On narrow screens the calendar opens as a sheet at the bottom |
1921
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
1906
1922
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
1907
1923
 
1908
1924
  | Event | Payload | Description |
@@ -1980,6 +1996,7 @@ The modal window of a Dialog: title, description, focus trap, Escape closes
1980
1996
  | Prop | Type | Description |
1981
1997
  | --- | --- | --- |
1982
1998
  | title | `string` | |
1999
+ | hide-title? | `boolean` | The title only for screen readers – it still names the dialog (e.g. a video in a dialog) |
1983
2000
  | description? | `string` | |
1984
2001
  | icon? | `Component` | Icon component in the coloured box at the top |
1985
2002
  | status? | `DialogStatus` | |
@@ -2123,6 +2140,7 @@ The panel of a Drawer, sliding in from a side; title, focus trap, Escape closes
2123
2140
  | Prop | Type | Description |
2124
2141
  | --- | --- | --- |
2125
2142
  | title | `string` | |
2143
+ | hide-title? | `boolean` | The title only for screen readers – it still names the drawer (e.g. a video in a dialog) |
2126
2144
  | description? | `string` | |
2127
2145
  | placement? | `DrawerPlacement` | |
2128
2146
  | 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 +2187,7 @@ Duration field: hours and minutes (optional days and seconds) as spin buttons
2169
2187
  | name? | `string` | |
2170
2188
  | size? | `'sm' \| 'md' \| 'lg'` | |
2171
2189
  | clearable? | `boolean` | Clear button in the field while it has a value |
2190
+ | id? | `string` | Id of the field (the group of parts); a `<label for>` cannot name it, use a Field or aria-label |
2172
2191
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the field (see the datePicker recipe) |
2173
2192
 
2174
2193
  | Event | Payload | Description |
@@ -2593,6 +2612,7 @@ Label, helper text, error, aria-invalid and aria-describedby come from Field
2593
2612
  | required? | `boolean` | |
2594
2613
  | optional? | `boolean` | "(optional)" after the label |
2595
2614
  | disabled? | `boolean` | |
2615
+ | classes? | `RecipeClasses<typeof fieldRecipe>` | Extra classes per part of the Field, e.g. { label: "…" } (see the field recipe) |
2596
2616
 
2597
2617
  | Slot | Slot props | Description |
2598
2618
  | --- | --- | --- |
@@ -2867,6 +2887,7 @@ Button with only an icon; the label is its accessible name, optionally with a co
2867
2887
  | size? | `ButtonSize` | `xs` is 24px – the minimum target size (WCAG 2.5.8) |
2868
2888
  | shape? | `ButtonShape` | Corner shape: `pill` (round, default), `rounded` or `square` |
2869
2889
  | disabled? | `boolean` | |
2890
+ | loading? | `boolean` | Shows a spinner instead of the icon and ignores clicks; stays focusable (aria-disabled + aria-busy) |
2870
2891
  | type? | `'button' \| 'submit' \| 'reset'` | |
2871
2892
  | badge? | `number \| boolean` | Counter (number > 0) or dot (true) in the top-right corner |
2872
2893
  | 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). |
@@ -3189,6 +3210,7 @@ Dial (270°): a slider – arrow keys, Page Up/Down, Home/End, or drag around th
3189
3210
  | size? | `'sm' \| 'md' \| 'lg'` | |
3190
3211
  | disabled? | `boolean` | |
3191
3212
  | name? | `string` | |
3213
+ | id? | `string` | Id of the dial (the slider); a `<label for>` cannot name it, use `label`, a Field or aria-label |
3192
3214
  | classes? | `RecipeClasses<typeof knobRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3193
3215
 
3194
3216
  | Event | Payload | Description |
@@ -3280,6 +3302,7 @@ Always visible list (role="listbox"): arrow keys move, Enter/Space choose, typin
3280
3302
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
3281
3303
  | page-size? | `number` | Options per request of the data source (default 50) |
3282
3304
  | draggable-items? | `boolean` | The options can be dragged (`draggable`, `data-value` is the key) – lists that exchange items (PickList) |
3305
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the list box, use a Field or aria-label |
3283
3306
  | classes? | `RecipeClasses<typeof listboxRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3284
3307
 
3285
3308
  | Event | Payload | Description |
@@ -3677,6 +3700,7 @@ Month field ("10.2026"): type the digits in one go, or pick from the month grid;
3677
3700
  | placeholder? | `string` | Text of the empty field, shown until it gets the focus – no replacement for a label |
3678
3701
  | size? | `'sm' \| 'md' \| 'lg'` | |
3679
3702
  | clearable? | `boolean` | Clear button in the field while it has a value |
3703
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
3680
3704
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
3681
3705
 
3682
3706
  | Event | Payload | Description |
@@ -3726,6 +3750,7 @@ Select with several values: the list stays open while choosing, Space/Enter togg
3726
3750
  | 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
3751
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
3728
3752
  | page-size? | `number` | Options per request of the data source (default 50) |
3753
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
3729
3754
  | classes? | `RecipeClasses<typeof multiSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3730
3755
 
3731
3756
  | Event | Payload | Description |
@@ -3882,6 +3907,7 @@ Number field with − / + buttons, arrow keys and locale formatting ("1,234.5")
3882
3907
  | loading? | `boolean` | Shows a spinner in the field and marks it busy (aria-busy) |
3883
3908
  | clearable? | `boolean` | Shows a button that empties the field while it has a value |
3884
3909
  | clear-label? | `string` | Accessible name of the clear button (default "Clear input") |
3910
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
3885
3911
  | classes? | `RecipeClasses<typeof numberInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
3886
3912
 
3887
3913
  | Event | Payload | Description |
@@ -4112,6 +4138,7 @@ Password field with a button that shows/hides the password (named "Show/Hide pas
4112
4138
  | clearable? | `boolean` | Shows a button that empties the field while it has a value |
4113
4139
  | clear-label? | `string` | Accessible name of the clear button (default "Clear input") |
4114
4140
  | default-value? | `string` | Initial value without v-model |
4141
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
4115
4142
  | classes? | `RecipeClasses<typeof passwordInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4116
4143
 
4117
4144
  | Event | Payload | Description |
@@ -4291,6 +4318,7 @@ Code input (OTP, PIN): one box per character, typing moves on, pasting fills all
4291
4318
  | invalid? | `boolean` | |
4292
4319
  | disabled? | `boolean` | |
4293
4320
  | name? | `string` | |
4321
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the PIN input, use a Field or aria-label |
4294
4322
  | classes? | `RecipeClasses<typeof pinInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4295
4323
 
4296
4324
  | Event | Payload | Description |
@@ -4560,6 +4588,7 @@ Star rating: a radio group – arrow keys change the value, each star reads "3 s
4560
4588
  | label? | `string` | Visible label, also the group's accessible name |
4561
4589
  | size? | `'sm' \| 'md' \| 'lg'` | |
4562
4590
  | name? | `string` | |
4591
+ | id? | `string` | Id of the root element; a `<label for>` cannot name the rating, use a Field or aria-label |
4563
4592
  | classes? | `RecipeClasses<typeof ratingRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4564
4593
 
4565
4594
  | Event | Payload | Description |
@@ -4902,6 +4931,7 @@ Dropdown list for one option: arrow keys, typeahead, Escape; native select hidde
4902
4931
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
4903
4932
  | page-size? | `number` | Options per request of the data source (default 50) |
4904
4933
  | standalone? | `boolean` | Not labelled by a surrounding Field – for a second control inside it (e.g. PhoneInput's country) |
4934
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
4905
4935
  | classes? | `RecipeClasses<typeof selectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
4906
4936
 
4907
4937
  | Event | Payload | Description |
@@ -5089,6 +5119,7 @@ Range: "Price, Minimum" / "Price, Maximum"
5089
5119
  | label | `string` | Visible label, also the accessible name of the thumbs |
5090
5120
  | thumb-labels? | `readonly string[]` | Names of the thumbs of a range slider, read after the label |
5091
5121
  | show-value? | `boolean` | Shows the formatted value next to the label |
5122
+ | hide-label? | `boolean` | The label for screen readers only – it stays the accessible name of the thumbs |
5092
5123
  | format-value? | `(value: number) => string` | Formats the shown and announced value, e.g. (v) => `${v} %` |
5093
5124
  | disabled? | `boolean` | |
5094
5125
  | name? | `string` | |
@@ -5407,7 +5438,7 @@ Sticks to the top or bottom edge while its container scrolls
5407
5438
 
5408
5439
  ### Switch
5409
5440
 
5410
- Ark renders a plain checkbox; role="switch" makes screen readers announce it as a switch
5441
+ Without a text the label is left out: Ark names the input by it, an empty one would hide a <label for>
5411
5442
 
5412
5443
  - Import: `import { Switch } from '@wirecore/wirelayer-vue'`
5413
5444
  - Category: Forms
@@ -5429,6 +5460,7 @@ Ark renders a plain checkbox; role="switch" makes screen readers announce it as
5429
5460
  | required? | `boolean` | |
5430
5461
  | name? | `string` | |
5431
5462
  | value? | `string` | Value of the switch – inside a SwitchGroup its state comes from the group's value |
5463
+ | id? | `string` | Id of the switch (the hidden input), e.g. for a `<label for>` |
5432
5464
  | classes? | `RecipeClasses<typeof switchControlRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5433
5465
 
5434
5466
  | Event | Payload | Description |
@@ -5583,6 +5615,7 @@ Free entries: Enter or "," adds, Backspace on the empty field selects the last e
5583
5615
  | has-more? | `boolean` | More suggestions can be loaded: scrolling to the end of the list emits loadMore |
5584
5616
  | 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
5617
  | min-search-length? | `number` | Fewest characters the typed text needs before the data source is asked (default 1) |
5618
+ | id? | `string` | Id of the input, e.g. for a `<label for>` |
5586
5619
  | classes? | `RecipeClasses<typeof tagsInputRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5587
5620
 
5588
5621
  | Event | Payload | Description |
@@ -5716,6 +5749,7 @@ Time field: type the digits one after another ("1430"), arrow keys change hour o
5716
5749
  | time-zone? | `string` | IANA zone ("Europe/Berlin"): the time is typed in the zone, the value gets its offset ("14:30+02:00") |
5717
5750
  | reference-date? | `string` | Day whose offset applies with timeZone (ISO, default today) |
5718
5751
  | show-time-zone? | `boolean` | Short zone name after the time ("CEST") |
5752
+ | id? | `string` | Id of the field – the (first) time gets it; a `<label for>` cannot name it, use a Field or aria-label |
5719
5753
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5720
5754
 
5721
5755
  | Event | Payload | Description |
@@ -5747,6 +5781,7 @@ Start and end time in one field ("09:00 – 17:30"): typing runs on from start t
5747
5781
  | name? | `string` | Sent as name[0] and name[1] |
5748
5782
  | size? | `'sm' \| 'md' \| 'lg'` | |
5749
5783
  | clearable? | `boolean` | Clear button in the field while it has a value |
5784
+ | id? | `string` | Id of the field – the (first) time gets it; a `<label for>` cannot name it, use a Field or aria-label |
5750
5785
  | classes? | `RecipeClasses<typeof datePickerRecipe>` | Extra classes per part of the component (see the datePicker recipe) |
5751
5786
 
5752
5787
  | Event | Payload | Description |
@@ -5862,6 +5897,7 @@ No element of its own: the trigger is the slotted element
5862
5897
  | close-delay? | `number` | Delay before closing (ms); default 150 or that of the TooltipGroup |
5863
5898
  | interactive? | `boolean` | The pointer can move onto the tooltip without it closing (WCAG 1.4.13) |
5864
5899
  | follow-cursor? | `boolean` | Follows the mouse pointer over the trigger |
5900
+ | close-on-scroll? | `boolean` | Closes when the page (or a container around the trigger) scrolls – false keeps it open while scrolling |
5865
5901
  | disabled? | `boolean` | Never opens (e.g. Truncate while the text fits) – the trigger stays the same element |
5866
5902
  | classes? | `RecipeClasses<typeof tooltipRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
5867
5903
 
@@ -6020,6 +6056,7 @@ Select whose options are a tree: the button opens the tree in a panel, choosing
6020
6056
  | size? | `'sm' \| 'md' \| 'lg'` | Height of the field: 32, 40 (default) or 48 px |
6021
6057
  | 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
6058
  | data-source? | `DataSource<TreeNode>` | Source of the children of lazy nodes (`getChildren`) |
6059
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
6023
6060
  | classes? | `RecipeClasses<typeof treeSelectRecipe>` | Extra classes per part of the component, e.g. { base: "…" } (see the recipe) |
6024
6061
 
6025
6062
  | Event | Payload | Description |
@@ -6122,6 +6159,7 @@ Select for any number of items – only the visible options are rendered.
6122
6159
  | 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
6160
  | page-size? | `number` | Items per request of the data source (default 50) |
6124
6161
  | min-search-length? | `number` | Fewest characters the search needs before the data source is asked |
6162
+ | id? | `string` | Id of the field (the trigger), e.g. for a `<label for>` |
6125
6163
 
6126
6164
  | Event | Payload | Description |
6127
6165
  | --- | --- | --- |
@@ -6297,6 +6335,7 @@ Year field ("2026"): type the digits, or pick from the year grid; range: start
6297
6335
  | placeholder? | `string` | Text of the empty field, shown until it gets the focus – no replacement for a label |
6298
6336
  | size? | `'sm' \| 'md' \| 'lg'` | |
6299
6337
  | clearable? | `boolean` | Clear button in the field while it has a value |
6338
+ | id? | `string` | Id of the field – the (first) date gets it; a `<label for>` cannot name it, use a Field or aria-label |
6300
6339
  | classes? | `RecipeClasses<typeof datePicker>` | Extra classes per part of the date field, e.g. { control: "…" } (the calendar: RecipesProvider) |
6301
6340
 
6302
6341
  | Event | Payload | Description |
@@ -6503,6 +6542,29 @@ that render components, such as `confirm` or the DataTable feature `dateInput`,
6503
6542
  components warn in the console when the classes of a recipe they render are missing. Recipes you call yourself
6504
6543
  (`card()`) are not checked – add their files along with the import.
6505
6544
 
6545
+ **With Vite** (Vue, React, Nuxt, Astro) the plugin `@wirecore/wirelayer-recipes/vite` adds these files itself: it reads
6546
+ the imports from `@wirecore/wirelayer-*` in your source files and adds the files of the imported components and recipes
6547
+ to the CSS file that imports `theme.css` (or `styles-core.css`). Put it before Tailwind's plugin:
6548
+
6549
+ ```ts
6550
+ // vite.config.ts (Nuxt: vite.plugins in nuxt.config.ts, Astro: vite.plugins in astro.config.mjs)
6551
+ import tailwindcss from '@tailwindcss/vite';
6552
+ import { wirelayer } from '@wirecore/wirelayer-recipes/vite';
6553
+
6554
+ export default { plugins: [wirelayer(), tailwindcss()] };
6555
+ ```
6556
+
6557
+ ```css
6558
+ @import 'tailwindcss';
6559
+ @import '@wirecore/wirelayer-vue/theme.css'; /* the plugin adds the sources files here */
6560
+ @import '@wirecore/wirelayer-vue/fonts.css'; /* the WireLayer fonts – leave it out with a font of your own */
6561
+ ```
6562
+
6563
+ `theme.css` is the theme without fonts and without component classes: an app with its own font
6564
+ (`@theme { --font-sans: … }`) does not bundle Schibsted Grotesk and JetBrains Mono. Components the plugin cannot see –
6565
+ registered globally (`app.component(…)`) or imported automatically – trigger the warning above; import their files by
6566
+ hand. Next.js does not use Vite: there, list the files or use `styles.css`.
6567
+
6506
6568
  ### Usage
6507
6569
 
6508
6570
  ```vue
@@ -6535,9 +6597,13 @@ import { ArrowRight } from 'lucide-react';
6535
6597
  // nuxt.config.ts
6536
6598
  import tailwindcss from '@tailwindcss/vite';
6537
6599
 
6600
+ import { wirelayer } from '@wirecore/wirelayer-recipes/vite';
6601
+
6538
6602
  export default defineNuxtConfig({
6539
- css: ['~/assets/main.css'], // @import 'tailwindcss'; @import '@wirecore/wirelayer-vue/styles.css';
6540
- vite: { plugins: [tailwindcss()] },
6603
+ // main.css: @import 'tailwindcss'; @import '@wirecore/wirelayer-vue/theme.css';
6604
+ // @import '@wirecore/wirelayer-vue/fonts.css'; – or styles.css with all classes, without the plugin
6605
+ css: ['~/assets/main.css'],
6606
+ vite: { plugins: [wirelayer(), tailwindcss()] },
6541
6607
  });
6542
6608
  ```
6543
6609
 
@@ -6620,6 +6686,31 @@ Every component consists of named parts of its recipe (`base`, `icon`, `row`, `t
6620
6686
  The names are the exports of the recipes (`button`, `iconButton`, `dataTable` …) and are checked by TypeScript, as are
6621
6687
  the variants and parts. Your own components use the same through `useRecipe('button', button)`.
6622
6688
 
6689
+ `variants` adds classes for single values of a variant, `compoundVariants` for combinations – instead of selectors on
6690
+ the recipe's own classes, which break when they change:
6691
+
6692
+ ```ts
6693
+ const recipes: RecipeConfig = {
6694
+ // only the medium size: 42px high, 16px text
6695
+ button: {
6696
+ variants: { size: { md: { base: 'h-[2.625rem] text-base' } } },
6697
+ compoundVariants: [{ size: ['sm', 'md'], shape: 'rounded', classes: { base: 'rounded-md' } }],
6698
+ },
6699
+ input: { variants: { size: { md: { base: 'h-[2.625rem]' } }, invalid: { true: { base: 'border-2' } } } },
6700
+ };
6701
+ ```
6702
+
6703
+ Per part the classes come in this order: `classes`, the matching `variants` and `compoundVariants`, the states of the
6704
+ recipe, the overrides of states (`invalid: { true: … }`), and last the class passed to the component. Inner providers
6705
+ extend outer ones (classes of the same value are joined, the inner ones win).
6706
+
6707
+ Classes from a provider or `classes` change the look, not the states: the classes of an active state variant
6708
+ (`invalid`, `success`, `disabled`, `readOnly`, `current`, `selected`, `checked`, `loading`) are added after them, so a
6709
+ field with `classes: { base: 'border-line-2' }` still turns red when it is invalid. States that the components mark as
6710
+ attributes (`data-invalid:`, `data-disabled:`, `data-[state=checked]:`) win through their selector anyway. Only the
6711
+ class passed to the component itself (`class`/`className`) comes after the states – the way out when a single field
6712
+ should look different in every state.
6713
+
6623
6714
  ### Hooks and composables
6624
6715
 
6625
6716
  Around 40 hooks (React) and composables (Vue) with the same names and the same logic – for your own components and
@@ -6998,6 +7089,56 @@ WireLayer is licensed under the MIT license. The fonts shipped with `@wirecore/w
6998
7089
  JetBrains Mono) are licensed under the SIL Open Font License 1.1 (`dist/fonts/OFL.txt`). Optional peer dependencies such
6999
7090
  as `pdfjs-dist` (Apache-2.0), Chart.js, Tiptap and Shiki are installed by the app itself – with their own licenses.
7000
7091
 
7092
+ ### Components and APIs side by side
7093
+
7094
+ | PrimeVue | WireLayer |
7095
+ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
7096
+ | `<Button label icon="pi pi-x">` | the label as slot text, `:leading-icon` with a Lucide component (`@lucide/vue`) |
7097
+ | `severity` / `text` / `outlined` | `color` – or `variant="text"` / `variant="outline"` |
7098
+ | Icon button + `v-tooltip` | `<Tooltip content><IconButton :icon label /></Tooltip>` – `label` is the accessible name (often the tooltip text) |
7099
+ | `Button :loading` | `loading` on `Button` and `IconButton` (stays focusable, ignores clicks) |
7100
+ | `Card` with `#title`/`#content` | `Card` with the default slot and an own heading |
7101
+ | `InputText`, `Password`, `InputNumber`, `InputChips`, `SelectButton`, `RadioButton` | `Input`, `PasswordInput`, `NumberInput`, `TagsInput`, `SegmentedControl`, `RadioGroup` + `RadioGroupItem` |
7102
+ | `IconField` + `InputIcon` | `Input :leading-icon` |
7103
+ | `Select :options optionLabel optionValue` | `Select :items item-label item-value` (object values: `value-key`) |
7104
+ | `Message severity` | `Alert status` (`error` → `danger`) |
7105
+ | `Tag` | `Badge` |
7106
+ | `Dialog v-model:visible header` | `Dialog v-model:open` + `DialogContent title size` (`hide-title` keeps the title for screen readers only) |
7107
+ | `Toolbar` as a container | a plain `div` – WireLayer's `Toolbar` is `role="toolbar"` (one tab stop, arrow keys) |
7108
+ | `useToast().add({ severity, summary, detail, life })` | `toast({ type, title, description, duration })`, `<Toaster />` once in the app |
7109
+ | `useConfirm().require({ … })` | `await confirm({ title, description, … })`, `<ConfirmDialog />` once in the app |
7110
+ | `DataTable` + `Column` | `DataTable :columns` (column objects), `#cell-<id>`, `#expansion`, `v-model:page-size` |
7111
+ | `expandedRows` with a row toggler on some rows | `#expansion` + `row-expandable` |
7112
+ | `paginatorTemplate` (first/last page) | `paginator-edges`, `paginator-align` |
7113
+ | `showGridlines` (with the outer border) | `gridlines` + `bordered` |
7114
+ | `FilterMatchMode`, `filters` | `v-model:global-filter`, column `filter`/`filterOptions`, `filter-display="row"` |
7115
+ | `@primevue/forms` + `zodResolver` | TanStack Form with Zod directly as a Standard Schema, `FormField` + `bindInput`/`bindValue` |
7116
+ | `pt` (pass-through) | `classes` per part, `RecipesProvider` for all components below it |
7117
+ | Theme preset (`definePreset`) | `--wc-*` tokens, `defineTheme`, the component variables (_Foundations › Themes_) |
7118
+ | `darkModeSelector` (a class) | `data-mode` on `<html>` |
7119
+ | `tailwindcss-primeui` (`bg-surface-*`, `text-muted-color`) | semantic tokens: `bg-card`, `bg-bg-2`, `text-muted`, `border-line` … |
7120
+
7121
+ ### Pitfalls
7122
+
7123
+ - **An empty choice is `null`, not `''`.** For PrimeVue's Select `''` means "nothing chosen"; WireLayer's Select treats
7124
+ `''` as a value (it warns in development that it is not among the items). Use `null`.
7125
+ - **TanStack fields start with `''`.** A required text in Zod therefore needs `.min(1)` – `z.string()` alone accepts
7126
+ the empty field.
7127
+ - **Fonts:** set your own with `@theme { --font-sans: … }`. Import `theme.css` instead of `styles.css` (with the
7128
+ sources files, or the Vite plugin `@wirecore/wirelayer-recipes/vite`) so the WireLayer fonts are not bundled
7129
+ (_Getting started › Welcome › Smaller CSS_).
7130
+ - **Card spacing:** `Card` puts a `gap` between its direct children – wrap content that should sit tight in one
7131
+ element.
7132
+ - **Overrides go per part and per variant.** `classes: { base: 'rounded-md' }` reaches every size; only the medium size
7133
+ with `variants: { size: { md: { base: '…' } } }` – no selectors on the recipe's own classes. States such as `invalid`
7134
+ stay visible over such classes; only `class` on the component itself replaces them.
7135
+ - **Sizes and corners in one place:** the height, text and corners of buttons and fields per size, the corners of
7136
+ rounded buttons, the padding of cards and the backdrop of dialogs are CSS variables (`--wc-control-h-md` …).
7137
+ - **Labels:** wrap a control in `Field` (it links label, description and error). A native `<label for>` works with the
7138
+ control's own `id`; date fields, sliders and groups need `Field` or `aria-label`.
7139
+ - **Brand colours:** `checkTheme` lists the pairs below WCAG AA, `suggestThemeFixes` the nearest colours (and `on-*`
7140
+ colours) that meet them – an orange `primary` with white text, common in PrimeVue themes, does not.
7141
+
7001
7142
  ### Custom theme
7002
7143
 
7003
7144
  A theme overrides any colors per mode. `themeToCss` generates the CSS for it,
@@ -7023,3 +7164,47 @@ writeFileSync('brand.css', themeToCss(brand));
7023
7164
  ```
7024
7165
 
7025
7166
  All bundled themes pass this check in both modes.
7167
+
7168
+ When a pair misses its contrast, `suggestThemeFixes` says how to fix it: per pair the nearest variant of a colour that
7169
+ meets it – its lightness moved in OKLCH, the hue kept – and, where text sits on the colour, a light or dark `on-*`
7170
+ colour. A suggestion never breaks a pair that passed:
7171
+
7172
+ ```ts
7173
+ import { suggestThemeFixes } from '@wirecore/wirelayer-tokens';
7174
+
7175
+ suggestThemeFixes(brand);
7176
+ // [{ name: 'primary: text-on-primary on bg-primary', mode: 'light', ratio: 2.6, min: 4.5,
7177
+ // color: { token: 'primary', value: '#a35c00', ratio: 4.5 },
7178
+ // on: { token: 'on-primary', value: '#050505', ratio: 8.1 } }, …]
7179
+ ```
7180
+
7181
+ ### Component sizes and shapes
7182
+
7183
+ Besides the colors, a few measures that a brand usually changes are CSS variables. Without them every component looks as
7184
+ before – their defaults are the values of the recipes. Set them on `:root` (all pages), on a `[data-theme]` or on any
7185
+ element (that part of the page):
7186
+
7187
+ ```css
7188
+ :root {
7189
+ --wc-control-h-md: 2.625rem; /* buttons and fields of the medium size: 42px */
7190
+ --wc-control-text-md: 1rem;
7191
+ --wc-control-radius-md: 0.375rem;
7192
+ --wc-button-radius: 0.375rem;
7193
+ --wc-card-p: 1.25rem;
7194
+ --wc-backdrop: rgb(0 0 0 / 0.4);
7195
+ }
7196
+ ```
7197
+
7198
+ | Variable | Default | Applies to |
7199
+ | ----------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7200
+ | `--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) |
7201
+ | `--wc-control-radius-sm` / `-md` / `-lg` | `6px` / `8px` / `10px` | Corners of the fields above and of Textarea (not of buttons) |
7202
+ | `--wc-control-text-sm` / `-md` / `-lg` | `13px` / `15px` / `16px` | Text in the fields above and in Textarea |
7203
+ | `--wc-button-radius` | `8px` | Corners of Button and IconButton with `shape="rounded"` (`pill` and `square` stay) |
7204
+ | `--wc-card-p` | `1.5rem` | Padding of Card |
7205
+ | `--wc-backdrop` | `rgb(0 0 0 / 0.6)` | Dimming behind Dialog, Drawer and ConfirmDialog |
7206
+ | `--radius-card` / `--radius-panel` / `--radius-popup` | `20px` / `28px` / `12px` | Corners of cards, panels and popups (menus, lists, popovers) |
7207
+ | `--wc-dialog-w` | by `size` | Width of a DialogContent |
7208
+
7209
+ The rest – the padding of a dialog or of table cells, the size of a single variant – is set per part with `classes` or
7210
+ `RecipesProvider` (_Getting started › Welcome › Customizing_). The React Native components keep their fixed sizes.
package/llms.txt CHANGED
@@ -182,7 +182,7 @@ Full API (props, events, slots, examples) in llms-full.txt next to this file. MC
182
182
  - [Select](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-select--playground): Dropdown list for one option: arrow keys, typeahead, Escape; native select hidden for forms (`@wirecore/wirelayer-vue`)
183
183
  - [SignaturePad](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-signaturepad--playground): Signature field (role="application"): draw with mouse, pen or finger; "Undo" removes the last stroke. With typedAlternative the name can be typed instead – the field shows it in a handwriting font. (`@wirecore/wirelayer-vue`)
184
184
  - [Slider](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-slider--playground): Range: "Price, Minimum" / "Price, Maximum" (`@wirecore/wirelayer-vue`)
185
- - [Switch](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-switch--playground): Ark renders a plain checkbox; role="switch" makes screen readers announce it as a switch (`@wirecore/wirelayer-vue`)
185
+ - [Switch](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-switch--playground): Without a text the label is left out: Ark names the input by it, an empty one would hide a <label for> (`@wirecore/wirelayer-vue`)
186
186
  - [SwitchGroup](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-switchgroup--playground): role="group" named by its label, described by helper and error text; Switches with a value inside (`@wirecore/wirelayer-vue`)
187
187
  - [TagsInput](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-tagsinput--playground): Free entries: Enter or "," adds, Backspace on the empty field selects the last entry (again removes it), arrow keys move between entries; additions and removals are announced. With suggestions the field is a combobox: Arrow down opens them, Enter adds the highlighted one. (`@wirecore/wirelayer-vue`)
188
188
  - [Textarea](https://wirecore.github.io/WireLayer/?path=/story/vue_forms-textarea--auto-resize): Multi-line text field, optionally growing with the text (autoResize) and with a counter; works inside Field (`@wirecore/wirelayer-vue`)
@@ -308,4 +308,7 @@ Full API (props, events, slots, examples) in llms-full.txt next to this file. MC
308
308
  - React Native (Expo)
309
309
  - HTML and server templates
310
310
  - License
311
+ - Components and APIs side by side
312
+ - Pitfalls
311
313
  - Custom theme
314
+ - Component sizes and shapes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecore/wirelayer-vue",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "WireLayer components for Vue 3",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -55,12 +55,16 @@
55
55
  },
56
56
  "./styles.css": "./styles.css",
57
57
  "./styles-core.css": "./styles-core.css",
58
+ "./theme.css": "./theme.css",
59
+ "./fonts.css": "./fonts.css",
58
60
  "./sources/*": "./dist/sources/*"
59
61
  },
60
62
  "files": [
61
63
  "dist",
62
64
  "styles.css",
63
65
  "styles-core.css",
66
+ "theme.css",
67
+ "fonts.css",
64
68
  "llms.txt",
65
69
  "llms-full.txt"
66
70
  ],
@@ -162,8 +166,8 @@
162
166
  "@ark-ui/vue": "^5.39.3",
163
167
  "@internationalized/date": "^3.12.4",
164
168
  "@lucide/vue": "^1.59.0",
165
- "@wirecore/wirelayer-recipes": "^0.5.0",
166
- "@wirecore/wirelayer-tokens": "^0.3.0"
169
+ "@wirecore/wirelayer-recipes": "^0.6.0",
170
+ "@wirecore/wirelayer-tokens": "^0.4.0"
167
171
  },
168
172
  "devDependencies": {
169
173
  "@storybook/addon-a11y": "^10.6.2",
package/theme.css ADDED
@@ -0,0 +1,14 @@
1
+ /*
2
+ * WireLayer theme without fonts and without the classes of the components – for an app with its own font
3
+ * (@theme { --font-sans: … }) and the classes of the components it uses: by hand, or with the Vite plugin
4
+ * (@wirecore/wirelayer-recipes/vite) that adds them to this file:
5
+ * @import 'tailwindcss';
6
+ * @import '@wirecore/wirelayer-vue/theme.css';
7
+ * @import '@wirecore/wirelayer-vue/fonts.css'; (the WireLayer fonts, if you want them)
8
+ */
9
+ @import '@wirecore/wirelayer-tokens/theme.css';
10
+
11
+ /* Lets the components warn in development when the classes of a recipe they render were not imported */
12
+ :root {
13
+ --wc-recipe-sources: 1;
14
+ }