@cocoar/vue-ui 3.1.0 → 3.2.0-beta.11

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 (180) hide show
  1. package/bin/cli.mjs +53 -0
  2. package/dist/components/checkbox/CoarCheckbox.vue.d.ts +1 -1
  3. package/dist/components/checkbox/CoarCheckbox.vue.d.ts.map +1 -1
  4. package/dist/components/code-block/CoarCodeBlock.vue.d.ts +1 -1
  5. package/dist/components/code-block/CoarCodeBlock.vue.d.ts.map +1 -1
  6. package/dist/components/data-list/CoarDataList.vue.d.ts +158 -0
  7. package/dist/components/data-list/CoarDataList.vue.d.ts.map +1 -0
  8. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts +30 -0
  9. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts.map +1 -0
  10. package/dist/components/data-list/data-list-builder.d.ts +288 -0
  11. package/dist/components/data-list/data-list-builder.d.ts.map +1 -0
  12. package/dist/components/data-list/index.d.ts +12 -0
  13. package/dist/components/data-list/index.d.ts.map +1 -0
  14. package/dist/components/data-list/internal/compare.d.ts +14 -0
  15. package/dist/components/data-list/internal/compare.d.ts.map +1 -0
  16. package/dist/components/data-list/internal/reorder-core.d.ts +46 -0
  17. package/dist/components/data-list/internal/reorder-core.d.ts.map +1 -0
  18. package/dist/components/data-list/internal/search.d.ts +16 -0
  19. package/dist/components/data-list/internal/search.d.ts.map +1 -0
  20. package/dist/components/data-list/internal/useDataListLines.d.ts +92 -0
  21. package/dist/components/data-list/internal/useDataListLines.d.ts.map +1 -0
  22. package/dist/components/data-list/internal/useDataListReorder.d.ts +68 -0
  23. package/dist/components/data-list/internal/useDataListReorder.d.ts.map +1 -0
  24. package/dist/components/data-list/internal/useSearchHighlight.d.ts +19 -0
  25. package/dist/components/data-list/internal/useSearchHighlight.d.ts.map +1 -0
  26. package/dist/components/data-list/types.d.ts +185 -0
  27. package/dist/components/data-list/types.d.ts.map +1 -0
  28. package/dist/components/data-list/useDataListModel.d.ts +79 -0
  29. package/dist/components/data-list/useDataListModel.d.ts.map +1 -0
  30. package/dist/components/date-time/_shared/maskito-config.d.ts +7 -2
  31. package/dist/components/date-time/_shared/maskito-config.d.ts.map +1 -1
  32. package/dist/components/date-time/_shared/time-helpers.d.ts +11 -4
  33. package/dist/components/date-time/_shared/time-helpers.d.ts.map +1 -1
  34. package/dist/components/date-time/_shared/use-date-picker-base.d.ts +1 -1
  35. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts +1 -1
  36. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts.map +1 -1
  37. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts +1 -1
  38. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts.map +1 -1
  39. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts +1 -1
  40. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts.map +1 -1
  41. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts +3 -0
  42. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts.map +1 -1
  43. package/dist/components/form-field/CoarFormField.vue.d.ts +1 -1
  44. package/dist/components/form-field/CoarFormField.vue.d.ts.map +1 -1
  45. package/dist/components/icon/CoarIcon.vue.d.ts +2 -2
  46. package/dist/components/icon/CoarIcon.vue.d.ts.map +1 -1
  47. package/dist/components/listbox/CoarListbox.vue.d.ts +7 -0
  48. package/dist/components/listbox/CoarListbox.vue.d.ts.map +1 -1
  49. package/dist/components/number-input/CoarNumberInput.vue.d.ts +1 -1
  50. package/dist/components/number-input/CoarNumberInput.vue.d.ts.map +1 -1
  51. package/dist/components/otp-input/CoarOtpInput.vue.d.ts +1 -1
  52. package/dist/components/otp-input/CoarOtpInput.vue.d.ts.map +1 -1
  53. package/dist/components/password-input/CoarPasswordInput.vue.d.ts +1 -1
  54. package/dist/components/password-input/CoarPasswordInput.vue.d.ts.map +1 -1
  55. package/dist/components/switch/CoarSwitch.vue.d.ts +1 -1
  56. package/dist/components/switch/CoarSwitch.vue.d.ts.map +1 -1
  57. package/dist/components/text-input/CoarTextInput.vue.d.ts +1 -1
  58. package/dist/components/text-input/CoarTextInput.vue.d.ts.map +1 -1
  59. package/dist/composables/dragRegistry.d.ts +12 -0
  60. package/dist/composables/dragRegistry.d.ts.map +1 -1
  61. package/dist/composables/index.d.ts +2 -2
  62. package/dist/composables/index.d.ts.map +1 -1
  63. package/dist/composables/useDragDrop.d.ts +62 -6
  64. package/dist/composables/useDragDrop.d.ts.map +1 -1
  65. package/dist/composables/useVirtualList.d.ts +21 -1
  66. package/dist/composables/useVirtualList.d.ts.map +1 -1
  67. package/dist/index.css +1 -1
  68. package/dist/index.d.ts +4 -2
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +4508 -2039
  71. package/package.json +9 -3
  72. package/skills/cocoar-vue-ui/SKILL.md +244 -0
  73. package/skills/cocoar-vue-ui/references/components/avatar.md +178 -0
  74. package/skills/cocoar-vue-ui/references/components/badge.md +290 -0
  75. package/skills/cocoar-vue-ui/references/components/breadcrumb.md +238 -0
  76. package/skills/cocoar-vue-ui/references/components/button.md +252 -0
  77. package/skills/cocoar-vue-ui/references/components/calendar/agenda-view.md +372 -0
  78. package/skills/cocoar-vue-ui/references/components/calendar/coar-calendar.md +1647 -0
  79. package/skills/cocoar-vue-ui/references/components/calendar/day-view.md +361 -0
  80. package/skills/cocoar-vue-ui/references/components/calendar/index.md +312 -0
  81. package/skills/cocoar-vue-ui/references/components/calendar/month-view.md +486 -0
  82. package/skills/cocoar-vue-ui/references/components/calendar/performance.md +186 -0
  83. package/skills/cocoar-vue-ui/references/components/calendar/timeline-view.md +301 -0
  84. package/skills/cocoar-vue-ui/references/components/calendar/week-view.md +382 -0
  85. package/skills/cocoar-vue-ui/references/components/calendar/work-week-view.md +145 -0
  86. package/skills/cocoar-vue-ui/references/components/calendar/year-view.md +63 -0
  87. package/skills/cocoar-vue-ui/references/components/card.md +151 -0
  88. package/skills/cocoar-vue-ui/references/components/checkbox-group.md +103 -0
  89. package/skills/cocoar-vue-ui/references/components/checkbox.md +279 -0
  90. package/skills/cocoar-vue-ui/references/components/code-block.md +241 -0
  91. package/skills/cocoar-vue-ui/references/components/context-menu.md +355 -0
  92. package/skills/cocoar-vue-ui/references/components/data-grid/checkbox.md +213 -0
  93. package/skills/cocoar-vue-ui/references/components/data-grid/date-columns.md +272 -0
  94. package/skills/cocoar-vue-ui/references/components/data-grid/editing.md +236 -0
  95. package/skills/cocoar-vue-ui/references/components/data-grid/multi-select.md +193 -0
  96. package/skills/cocoar-vue-ui/references/components/data-grid/number.md +147 -0
  97. package/skills/cocoar-vue-ui/references/components/data-grid/select.md +202 -0
  98. package/skills/cocoar-vue-ui/references/components/data-grid/text.md +127 -0
  99. package/skills/cocoar-vue-ui/references/components/data-grid.md +1225 -0
  100. package/skills/cocoar-vue-ui/references/components/data-list.md +2121 -0
  101. package/skills/cocoar-vue-ui/references/components/date-or-time-picker.md +200 -0
  102. package/skills/cocoar-vue-ui/references/components/date-picker.md +203 -0
  103. package/skills/cocoar-vue-ui/references/components/date-time-picker.md +154 -0
  104. package/skills/cocoar-vue-ui/references/components/date-views.md +212 -0
  105. package/skills/cocoar-vue-ui/references/components/dialog.md +148 -0
  106. package/skills/cocoar-vue-ui/references/components/divider.md +157 -0
  107. package/skills/cocoar-vue-ui/references/components/document-viewer/annotations.md +400 -0
  108. package/skills/cocoar-vue-ui/references/components/document-viewer/coar-document-viewer.md +327 -0
  109. package/skills/cocoar-vue-ui/references/components/document-viewer/index.md +234 -0
  110. package/skills/cocoar-vue-ui/references/components/document-viewer/toolbar.md +221 -0
  111. package/skills/cocoar-vue-ui/references/components/drag-drop.md +267 -0
  112. package/skills/cocoar-vue-ui/references/components/dual-listbox.md +449 -0
  113. package/skills/cocoar-vue-ui/references/components/file-explorer/asset-store.md +327 -0
  114. package/skills/cocoar-vue-ui/references/components/file-explorer/in-memory-store.md +176 -0
  115. package/skills/cocoar-vue-ui/references/components/file-explorer/index.md +311 -0
  116. package/skills/cocoar-vue-ui/references/components/file-explorer/use-file-explorer.md +300 -0
  117. package/skills/cocoar-vue-ui/references/components/form-field.md +1025 -0
  118. package/skills/cocoar-vue-ui/references/components/fragment-parser.md +298 -0
  119. package/skills/cocoar-vue-ui/references/components/link.md +235 -0
  120. package/skills/cocoar-vue-ui/references/components/listbox.md +575 -0
  121. package/skills/cocoar-vue-ui/references/components/map/editor.md +448 -0
  122. package/skills/cocoar-vue-ui/references/components/map/index.md +351 -0
  123. package/skills/cocoar-vue-ui/references/components/markdown-diagrams.md +210 -0
  124. package/skills/cocoar-vue-ui/references/components/markdown-editor.md +1478 -0
  125. package/skills/cocoar-vue-ui/references/components/markdown-embeds.md +387 -0
  126. package/skills/cocoar-vue-ui/references/components/markdown-form.md +447 -0
  127. package/skills/cocoar-vue-ui/references/components/markdown.md +276 -0
  128. package/skills/cocoar-vue-ui/references/components/menu.md +380 -0
  129. package/skills/cocoar-vue-ui/references/components/mermaid.md +172 -0
  130. package/skills/cocoar-vue-ui/references/components/navbar.md +147 -0
  131. package/skills/cocoar-vue-ui/references/components/note.md +96 -0
  132. package/skills/cocoar-vue-ui/references/components/notice.md +131 -0
  133. package/skills/cocoar-vue-ui/references/components/number-input.md +215 -0
  134. package/skills/cocoar-vue-ui/references/components/otp-input.md +324 -0
  135. package/skills/cocoar-vue-ui/references/components/page-builder/authoring-contract.md +271 -0
  136. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-builder.md +476 -0
  137. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-renderer.md +677 -0
  138. package/skills/cocoar-vue-ui/references/components/page-builder/custom-elements.md +441 -0
  139. package/skills/cocoar-vue-ui/references/components/page-builder/idp-integration.md +122 -0
  140. package/skills/cocoar-vue-ui/references/components/page-builder/index.md +573 -0
  141. package/skills/cocoar-vue-ui/references/components/pagination.md +150 -0
  142. package/skills/cocoar-vue-ui/references/components/panel-layout.md +372 -0
  143. package/skills/cocoar-vue-ui/references/components/password-input.md +175 -0
  144. package/skills/cocoar-vue-ui/references/components/popconfirm.md +186 -0
  145. package/skills/cocoar-vue-ui/references/components/popover.md +173 -0
  146. package/skills/cocoar-vue-ui/references/components/progress-bar.md +178 -0
  147. package/skills/cocoar-vue-ui/references/components/radio-group.md +225 -0
  148. package/skills/cocoar-vue-ui/references/components/script-editor.md +1271 -0
  149. package/skills/cocoar-vue-ui/references/components/segmented-control.md +238 -0
  150. package/skills/cocoar-vue-ui/references/components/select.md +463 -0
  151. package/skills/cocoar-vue-ui/references/components/sidebar.md +421 -0
  152. package/skills/cocoar-vue-ui/references/components/spinner.md +132 -0
  153. package/skills/cocoar-vue-ui/references/components/switch.md +195 -0
  154. package/skills/cocoar-vue-ui/references/components/table.md +170 -0
  155. package/skills/cocoar-vue-ui/references/components/tabs.md +382 -0
  156. package/skills/cocoar-vue-ui/references/components/tag.md +178 -0
  157. package/skills/cocoar-vue-ui/references/components/text-input.md +256 -0
  158. package/skills/cocoar-vue-ui/references/components/toast.md +160 -0
  159. package/skills/cocoar-vue-ui/references/components/tooltip.md +121 -0
  160. package/skills/cocoar-vue-ui/references/components/transitions.md +193 -0
  161. package/skills/cocoar-vue-ui/references/components/tree.md +2388 -0
  162. package/skills/cocoar-vue-ui/references/components/virtual-list.md +212 -0
  163. package/skills/cocoar-vue-ui/references/components/wizard.md +251 -0
  164. package/skills/cocoar-vue-ui/references/components/zoned-date-time-picker.md +177 -0
  165. package/skills/cocoar-vue-ui/references/foundations/colors.md +708 -0
  166. package/skills/cocoar-vue-ui/references/foundations/design-principles.md +115 -0
  167. package/skills/cocoar-vue-ui/references/foundations/icons.md +381 -0
  168. package/skills/cocoar-vue-ui/references/foundations/localization/formatting.md +530 -0
  169. package/skills/cocoar-vue-ui/references/foundations/localization/setup.md +86 -0
  170. package/skills/cocoar-vue-ui/references/foundations/localization/timezones.md +182 -0
  171. package/skills/cocoar-vue-ui/references/foundations/localization/translations.md +305 -0
  172. package/skills/cocoar-vue-ui/references/foundations/motion.md +549 -0
  173. package/skills/cocoar-vue-ui/references/foundations/spacing.md +330 -0
  174. package/skills/cocoar-vue-ui/references/foundations/theming.md +140 -0
  175. package/skills/cocoar-vue-ui/references/foundations/typography.md +206 -0
  176. package/skills/cocoar-vue-ui/references/guide/error-handling.md +162 -0
  177. package/skills/cocoar-vue-ui/references/guide/getting-started.md +116 -0
  178. package/skills/cocoar-vue-ui/references/guide/migration-page-builder-3.md +207 -0
  179. package/skills/cocoar-vue-ui/references/guide/migration.md +140 -0
  180. package/skills/cocoar-vue-ui/references/guide/theming.md +98 -0
@@ -0,0 +1,252 @@
1
+ <!-- Generated from apps/docs/components/button.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # Button
4
+
5
+ Buttons trigger actions and communicate what will happen when pressed.
6
+
7
+ ```ts
8
+ import { CoarButton } from '@cocoar/vue-ui';
9
+ ```
10
+
11
+ ## Variants
12
+
13
+ Choose the appropriate variant based on the action's importance and context.
14
+
15
+ **Demo — `button/demos/ButtonVariants.vue`**
16
+
17
+ ```vue
18
+ <template>
19
+ <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center;">
20
+ <CoarButton variant="primary">Primary</CoarButton>
21
+ <CoarButton variant="secondary">Secondary</CoarButton>
22
+ <CoarButton variant="tertiary">Tertiary</CoarButton>
23
+ <CoarButton variant="danger">Danger</CoarButton>
24
+ <CoarButton variant="ghost">Ghost</CoarButton>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { CoarButton } from '@cocoar/vue-ui';
30
+ </script>
31
+ ```
32
+
33
+ **When to use each variant:**
34
+
35
+ - **Primary** — Main call-to-action. Use sparingly, typically once per view.
36
+ - **Secondary** — Alternative actions. Pairs well with primary buttons.
37
+ - **Tertiary** — Low-emphasis actions with brand color hint.
38
+ - **Danger** — Destructive actions like delete or remove.
39
+ - **Ghost** — Minimal emphasis, often for cancel or dismiss.
40
+
41
+ ## Sizes
42
+
43
+ Four sizes to fit different contexts and layouts.
44
+
45
+ **Demo — `button/demos/ButtonSizes.vue`**
46
+
47
+ ```vue
48
+ <template>
49
+ <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end;">
50
+ <CoarButton size="xs">Extra Small</CoarButton>
51
+ <CoarButton size="s">Small</CoarButton>
52
+ <CoarButton size="m">Medium</CoarButton>
53
+ <CoarButton size="l">Large</CoarButton>
54
+ </div>
55
+ <p style="margin-top: 8px; font-size: 13px; color: #64748b;">
56
+ <code>xs</code> 27px | <code>s</code> 32px | <code>m</code> 40px | <code>l</code> 48px
57
+ </p>
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { CoarButton } from '@cocoar/vue-ui';
62
+ </script>
63
+ ```
64
+
65
+ ## Icons
66
+
67
+ Add icons before or after the label to enhance meaning.
68
+
69
+ **Demo — `button/demos/ButtonIcons.vue`**
70
+
71
+ ```vue
72
+ <template>
73
+ <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center;">
74
+ <CoarButton icon-start="plus">Add Item</CoarButton>
75
+ <CoarButton variant="secondary" icon-end="chevron-right">Next</CoarButton>
76
+ <CoarButton variant="tertiary" icon-start="clipboard">Download</CoarButton>
77
+ <CoarButton variant="danger" icon-start="trash-2">Delete</CoarButton>
78
+ </div>
79
+ </template>
80
+
81
+ <script setup lang="ts">
82
+ import { CoarButton } from '@cocoar/vue-ui';
83
+ </script>
84
+ ```
85
+
86
+ ## Loading State
87
+
88
+ Show a spinner while an async action is in progress. Click to test.
89
+
90
+ **Demo — `button/demos/ButtonLoading.vue`**
91
+
92
+ ```vue
93
+ <template>
94
+ <div style="display: flex; flex-wrap: wrap; gap: 16px; align-items: center;">
95
+ <div style="display: flex; align-items: center; gap: 8px;">
96
+ <span style="font-size: 13px; color: #64748b; min-width: 100px;">With start icon:</span>
97
+ <CoarButton icon-start="check" :loading="isLoading" @click="simulateLoading">Save Changes</CoarButton>
98
+ </div>
99
+ <div style="display: flex; align-items: center; gap: 8px;">
100
+ <span style="font-size: 13px; color: #64748b; min-width: 100px;">Icon end:</span>
101
+ <CoarButton icon-end="chevron-right" :loading="isLoadingEnd" @click="simulateLoadingEnd">Continue</CoarButton>
102
+ </div>
103
+ </div>
104
+ </template>
105
+
106
+ <script setup lang="ts">
107
+ import { ref } from 'vue';
108
+ import { CoarButton } from '@cocoar/vue-ui';
109
+
110
+ const isLoading = ref(false);
111
+ const isLoadingEnd = ref(false);
112
+
113
+ function simulateLoading() {
114
+ isLoading.value = true;
115
+ setTimeout(() => { isLoading.value = false; }, 2000);
116
+ }
117
+
118
+ function simulateLoadingEnd() {
119
+ isLoadingEnd.value = true;
120
+ setTimeout(() => { isLoadingEnd.value = false; }, 2000);
121
+ }
122
+ </script>
123
+ ```
124
+
125
+ ## Disabled State
126
+
127
+ Disable buttons when actions are not available.
128
+
129
+ **Demo — `button/demos/ButtonDisabled.vue`**
130
+
131
+ ```vue
132
+ <template>
133
+ <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center;">
134
+ <CoarButton :disabled="true">Primary</CoarButton>
135
+ <CoarButton variant="secondary" :disabled="true">Secondary</CoarButton>
136
+ <CoarButton variant="tertiary" :disabled="true">Tertiary</CoarButton>
137
+ <CoarButton variant="danger" :disabled="true">Danger</CoarButton>
138
+ <CoarButton variant="ghost" :disabled="true">Ghost</CoarButton>
139
+ </div>
140
+ </template>
141
+
142
+ <script setup lang="ts">
143
+ import { CoarButton } from '@cocoar/vue-ui';
144
+ </script>
145
+ ```
146
+
147
+ ## Full Width
148
+
149
+ Buttons can expand to fill their container.
150
+
151
+ **Demo — `button/demos/ButtonFullWidth.vue`**
152
+
153
+ ```vue
154
+ <template>
155
+ <div style="max-width: 360px; display: flex; flex-direction: column; gap: 8px;">
156
+ <CoarButton :full-width="true">Full Width Primary</CoarButton>
157
+ <CoarButton variant="secondary" :full-width="true">Full Width Secondary</CoarButton>
158
+ </div>
159
+ </template>
160
+
161
+ <script setup lang="ts">
162
+ import { CoarButton } from '@cocoar/vue-ui';
163
+ </script>
164
+ ```
165
+
166
+ ## Router Integration
167
+
168
+ Pass `to` to render the button as a real `<a href>` link instead of a `<button>`. The button keeps its full visual styling — variants, sizes, icons, loading spinner — but right-click → "Open in new tab", middle-click, and Ctrl/Cmd-click all work as expected via the browser's native link handling. Screenreaders announce "link" instead of "button".
169
+
170
+ ```vue
171
+ <!-- Before — modifier-clicks silently did nothing -->
172
+ <CoarButton variant="primary" @click="router.push('/docs')">
173
+ Open documentation
174
+ </CoarButton>
175
+
176
+ <!-- After — full browser link affordances -->
177
+ <CoarButton variant="primary" to="/docs">
178
+ Open documentation
179
+ </CoarButton>
180
+ ```
181
+
182
+ If `vue-router` is installed and registered (`app.use(router)`), the button renders via `<RouterLink>` and plain clicks trigger SPA navigation. Without a router it falls back to a plain `<a href={String(to)}>` that uses the browser's native navigation — useful for external links.
183
+
184
+ ```vue
185
+ <!-- External link — works with or without vue-router -->
186
+ <CoarButton variant="ghost" iconEnd="external-link" to="https://docs.cocoar.dev">
187
+ Documentation
188
+ </CoarButton>
189
+ ```
190
+
191
+ `@click` still emits on plain click for telemetry and other consumer side-effects. Modifier-clicks (Ctrl/Cmd/Shift/Alt/middle-button) pass through to the browser without SPA navigation, so the user can open the destination in a new tab. `disabled` and `loading` block both navigation and the emit; the `type` attribute is only applied when rendering as `<button>` (it is invalid on `<a>`).
192
+
193
+ > **Info**
194
+ >
195
+ > `vue-router` is declared as an **optional `peerDependenciesMeta`** entry of `@cocoar/vue-ui` — install it if you want SPA routing, omit it for click-emit-only / external-URL use. Apps without a router can use `<CoarButton>` exactly as before; setting `to` to a string URL still gives you a proper `<a href>` for browser navigation.
196
+
197
+ > **Warning: Object `to` without router**
198
+ >
199
+ > Passing an object literal (`:to="{ name: 'docs' }"`) when no router is installed falls back to `String(to)`, producing `href="[object Object]"` — a broken link. The component logs a DEV-only `console.warn` once per component instance to make this loud at dev-time. Pass a string path for the no-router case.
200
+
201
+ ## Accessibility
202
+
203
+ ### Keyboard Navigation
204
+
205
+ | Key | Action |
206
+ |-----|--------|
207
+ | `Tab` | Move focus to button |
208
+ | `Shift + Tab` | Move focus backward |
209
+ | `Enter` | Activate button |
210
+ | `Space` | Activate button |
211
+
212
+ > **Info**
213
+ >
214
+ > Disabled and loading buttons cannot be activated via keyboard.
215
+
216
+ ### Screen Reader Support
217
+
218
+ - Button text or `aria-label` announces on focus
219
+ - Disabled state properly communicated
220
+ - Loading state indicates button is busy
221
+ - Icon-only buttons should include `aria-label`
222
+ - `type` attribute ensures correct form behavior
223
+
224
+ ## API
225
+
226
+ ### Props
227
+
228
+ | Prop | Type | Default | Description |
229
+ |------|------|---------|-------------|
230
+ | `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'danger' \| 'ghost'` | `'primary'` | Button style variant |
231
+ | `size` | `'xs' \| 's' \| 'm' \| 'l'` | `'m'` | Button size |
232
+ | `iconStart` | `string` | `undefined` | Icon name before label |
233
+ | `iconEnd` | `string` | `undefined` | Icon name after label |
234
+ | `loading` | `boolean` | `false` | Show loading spinner |
235
+ | `disabled` | `boolean` | `false` | Disable the button |
236
+ | `fullWidth` | `boolean` | `false` | Expand to fill container |
237
+ | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML button type (ignored when `to` is set — invalid on `<a>`) |
238
+ | `to` | `RouteLocationRaw \| string` | `undefined` | Vue Router target. When set, renders as `<a href>` via `<RouterLink>` (or plain `<a>` if no router is installed). Enables right-click / middle-click / Ctrl+click new-tab behaviour and "Copy link address". See [Router Integration](#router-integration). |
239
+
240
+ ### Events
241
+
242
+ | Event | Payload | Description |
243
+ |-------|---------|-------------|
244
+ | `click` | `MouseEvent` | Emitted when clicked (not when disabled/loading) |
245
+
246
+ ## i18n Keys
247
+
248
+ These keys can be translated via [`@cocoar/vue-localization`](../foundations/localization/translations.md).
249
+
250
+ | Key | Default (English) | Used as |
251
+ |-----|-------------------|---------|
252
+ | `coar.ui.button.loading` | `'Loading'` | Screen reader announcement when `loading` is true |
@@ -0,0 +1,372 @@
1
+ <!-- Generated from apps/docs/components/calendar/agenda-view.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # `<CoarAgendaView>` — Agenda View (Preview)
4
+
5
+ Virtualized chronological list grouped by day. Multi-day events appear on every day they touch (with a `(cont.)` tag from day 2 onwards). The current-day header floats at the top of the surface and is pushed up by the next inline header — same UX as native CSS sticky, but works correctly on top of an absolutely-positioned virtualized surface.
6
+
7
+ ```html
8
+ <CoarAgendaView :builder="builder" />
9
+ ```
10
+
11
+ ## Standalone usage
12
+
13
+ ```ts
14
+ import { ref } from 'vue';
15
+ import { Temporal } from '@js-temporal/polyfill';
16
+ import {
17
+ CoarAgendaView,
18
+ useAgendaView,
19
+ type CalendarEvent,
20
+ } from '@cocoar/vue-calendar';
21
+
22
+ const events = ref<CalendarEvent[]>([
23
+ {
24
+ id: 'standup',
25
+ start: Temporal.ZonedDateTime.from('2026-04-15T09:00:00[UTC]'),
26
+ end: Temporal.ZonedDateTime.from('2026-04-15T09:30:00[UTC]'),
27
+ },
28
+ {
29
+ id: 'devconf',
30
+ start: Temporal.PlainDate.from('2026-04-13'),
31
+ end: Temporal.PlainDate.from('2026-04-16'),
32
+ },
33
+ ]);
34
+ const date = ref('2026-04-15');
35
+
36
+ const { builder, api } = useAgendaView();
37
+ builder
38
+ .events(events)
39
+ .date(date)
40
+ .timezone('UTC')
41
+ .agendaLengthDays(60)
42
+ .showEmptyDays(true);
43
+ ```
44
+
45
+ ```html
46
+ <CoarAgendaView :builder="builder" />
47
+ ```
48
+
49
+ The visible window is derived from `date()` (the cursor — the **first** day) plus `agendaLengthDays()` (how many days forward to render). Use `api.scrollToDate(...)` to jump to any day inside that window.
50
+
51
+ **Demo — `calendar/demos/AgendaViewBasic.vue`**
52
+
53
+ ```vue
54
+ <template>
55
+ <div style="height: 520px; border: 1px solid var(--coar-border-neutral-tertiary); border-radius: var(--coar-radius-xs); overflow: hidden;">
56
+ <CoarAgendaView :builder="builder" />
57
+ </div>
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { ref } from 'vue';
62
+ import {
63
+ CoarAgendaView,
64
+ useAgendaView,
65
+ Temporal,
66
+ type CalendarEvent,
67
+ } from '@cocoar/vue-calendar';
68
+
69
+ const date = ref(Temporal.PlainDate.from('2026-04-13'));
70
+
71
+ // Local helpers — keep event construction terse while still using the
72
+ // article-4 typed shape (PlainDate for all-day, ZonedDateTime for timed).
73
+ const pd = (iso: string) => Temporal.PlainDate.from(iso);
74
+ const zdt = (iso: string, tz = 'Europe/Vienna') =>
75
+ Temporal.ZonedDateTime.from(`${iso}[${tz}]`);
76
+
77
+ const events = ref<CalendarEvent[]>([
78
+ // Multi-day all-day event — appears on every day it touches with
79
+ // a localized "(cont.)" tag from day 2 onwards.
80
+ {
81
+ id: 'devconf',
82
+ start: pd('2026-04-13'),
83
+ end: pd('2026-04-16'),
84
+ meta: { title: 'DevConf — Vienna', color: '#7c3aed' },
85
+ },
86
+ // Single-day all-day.
87
+ {
88
+ id: 'easter-monday',
89
+ start: pd('2026-04-13'),
90
+ meta: { title: 'Easter Monday (PT branch)', color: '#10b981' },
91
+ },
92
+ // Daily standups Mon–Fri.
93
+ ...['2026-04-13', '2026-04-14', '2026-04-15', '2026-04-16', '2026-04-17'].map(
94
+ (d): CalendarEvent => ({
95
+ id: `standup-${d}`,
96
+ start: zdt(`${d}T09:00:00`),
97
+ end: zdt(`${d}T09:30:00`),
98
+ meta: { title: 'Daily standup', color: '#10b981' },
99
+ }),
100
+ ),
101
+ // Wed busy day.
102
+ {
103
+ id: 'design',
104
+ start: zdt('2026-04-15T11:00:00'),
105
+ end: zdt('2026-04-15T12:00:00'),
106
+ meta: { title: 'Design review', color: '#8b5cf6' },
107
+ },
108
+ {
109
+ id: 'lunch',
110
+ start: zdt('2026-04-15T12:00:00'),
111
+ end: zdt('2026-04-15T13:00:00'),
112
+ meta: { title: 'Lunch with Anna', color: '#ef4444' },
113
+ },
114
+ // Fri client demo.
115
+ {
116
+ id: 'fri-demo',
117
+ start: zdt('2026-04-17T15:00:00'),
118
+ end: zdt('2026-04-17T16:30:00'),
119
+ meta: { title: 'Client demo', color: '#dc2626' },
120
+ },
121
+ // Quarterly review crossing the month boundary.
122
+ {
123
+ id: 'qr',
124
+ start: pd('2026-04-29'),
125
+ end: pd('2026-05-02'),
126
+ meta: { title: 'Quarterly review', color: '#2563eb' },
127
+ },
128
+ ]);
129
+
130
+ const { builder } = useAgendaView();
131
+ builder
132
+ .events(events)
133
+ .date(date)
134
+ .timezone('Europe/Vienna')
135
+ .agendaLengthDays(30)
136
+ .onEventDrop(({ event, next }) => {
137
+ const idx = events.value.findIndex((e) => e.id === event.id);
138
+ if (idx < 0) return;
139
+ events.value = [
140
+ ...events.value.slice(0, idx),
141
+ { ...event, start: next.start, ...(next.end ? { end: next.end } : {}) },
142
+ ...events.value.slice(idx + 1),
143
+ ];
144
+ });
145
+ </script>
146
+ ```
147
+
148
+ ## Imperative scroll-to-date + empty days
149
+
150
+ The `api` object returned by `useAgendaView()` exposes `scrollToDate(iso)` for jumping to any day inside the window. Toggle `showEmptyDays(true)` to render headers for days with no events — useful when you want a continuous date strip.
151
+
152
+ **Demo — `calendar/demos/AgendaViewScrollToDate.vue`**
153
+
154
+ ```vue
155
+ <template>
156
+ <div>
157
+ <div class="controls">
158
+ <CoarButton size="sm" @click="api.scrollToDate('2026-04-13')">
159
+ ← DevConf (Apr 13)
160
+ </CoarButton>
161
+ <CoarButton size="sm" @click="api.scrollToDate('2026-04-22')">
162
+ Team offsite (Apr 22)
163
+ </CoarButton>
164
+ <CoarButton size="sm" @click="api.scrollToDate('2026-05-04')">
165
+ Quarterly review (May 4) →
166
+ </CoarButton>
167
+ <label class="toggle">
168
+ <input v-model="empty" type="checkbox" />
169
+ <span>Show empty days</span>
170
+ </label>
171
+ </div>
172
+ <div style="height: 460px; border: 1px solid var(--coar-border-neutral-tertiary); border-radius: var(--coar-radius-xs); overflow: hidden;">
173
+ <CoarAgendaView :builder="builder" />
174
+ </div>
175
+ </div>
176
+ </template>
177
+
178
+ <script setup lang="ts">
179
+ import { ref } from 'vue';
180
+ import { CoarButton } from '@cocoar/vue-ui';
181
+ import {
182
+ CoarAgendaView,
183
+ useAgendaView,
184
+ Temporal,
185
+ type CalendarEvent,
186
+ } from '@cocoar/vue-calendar';
187
+
188
+ const date = ref(Temporal.PlainDate.from('2026-04-01'));
189
+ const empty = ref(false);
190
+
191
+ const pd = (iso: string) => Temporal.PlainDate.from(iso);
192
+ const zdt = (iso: string, tz = 'Europe/Vienna') =>
193
+ Temporal.ZonedDateTime.from(`${iso}[${tz}]`);
194
+
195
+ const events = ref<CalendarEvent[]>([
196
+ {
197
+ id: 'devconf',
198
+ start: pd('2026-04-13'),
199
+ end: pd('2026-04-16'),
200
+ meta: { title: 'DevConf — Vienna', color: '#7c3aed' },
201
+ },
202
+ {
203
+ id: 'team-offsite',
204
+ start: pd('2026-04-22'),
205
+ end: pd('2026-04-25'),
206
+ meta: { title: 'Team offsite', color: '#0891b2' },
207
+ },
208
+ ...['2026-04-13', '2026-04-14', '2026-04-15', '2026-04-16', '2026-04-17',
209
+ '2026-04-20', '2026-04-21', '2026-04-22', '2026-04-23', '2026-04-24'].map(
210
+ (d): CalendarEvent => ({
211
+ id: `standup-${d}`,
212
+ start: zdt(`${d}T09:00:00`),
213
+ end: zdt(`${d}T09:30:00`),
214
+ meta: { title: 'Daily standup', color: '#10b981' },
215
+ }),
216
+ ),
217
+ {
218
+ id: 'qr',
219
+ start: zdt('2026-05-04T10:00:00'),
220
+ end: zdt('2026-05-04T12:00:00'),
221
+ meta: { title: 'Quarterly review', color: '#2563eb' },
222
+ },
223
+ ]);
224
+
225
+ const { builder, api } = useAgendaView();
226
+ builder
227
+ .events(events)
228
+ .date(date)
229
+ .timezone('Europe/Vienna')
230
+ .agendaLengthDays(60)
231
+ .showEmptyDays(() => empty.value);
232
+ </script>
233
+
234
+ <style scoped>
235
+ .controls {
236
+ display: flex;
237
+ flex-wrap: wrap;
238
+ gap: 8px;
239
+ align-items: center;
240
+ margin-bottom: 12px;
241
+ }
242
+ .toggle {
243
+ display: inline-flex;
244
+ align-items: center;
245
+ gap: 6px;
246
+ margin-left: auto;
247
+ font-size: 13px;
248
+ color: var(--coar-text-subtle, #6b7280);
249
+ }
250
+ </style>
251
+ ```
252
+
253
+ ## Inside `<CoarCalendar>`
254
+
255
+ `<CoarCalendar>` and `<CoarAgendaView>` consume the SAME `CalendarBuilder` instance — there's no sub-builder forking. Set agenda-specific config directly on the composer's builder:
256
+
257
+ ```ts
258
+ const { builder } = useCalendar();
259
+ builder
260
+ .agendaLengthDays(60)
261
+ .showEmptyDays(true);
262
+ ```
263
+
264
+ When the active view is agenda, the same builder feeds the embedded `<CoarAgendaView>`. View-specific settings simply have no effect outside their view.
265
+
266
+ ## `useAgendaView<TMeta>()`
267
+
268
+ ```ts
269
+ function useAgendaView<TMeta>(): {
270
+ builder: CalendarBuilder<TMeta>;
271
+ api: CalendarApi<TMeta>;
272
+ };
273
+ ```
274
+
275
+ Returns a fresh standalone builder + its imperative api.
276
+
277
+ ## Builder setters
278
+
279
+ ### Universal (every builder)
280
+
281
+ Same universal surface as the [composer](./coar-calendar.md#api-reference). Highlights for the agenda view:
282
+
283
+ | Setter | Notes |
284
+ |---|---|
285
+ | `eventRenderer(r)` | Replaces the default time + title row content. |
286
+ | `onDateClick(fn)` | Fires on day-group header click. |
287
+ | `onEventClick(fn)` / `onEventDoubleClick(fn)` | Per-row interaction. |
288
+
289
+ ### Agenda specific
290
+
291
+ | Setter | Argument | Default | Notes |
292
+ |---|---|---|---|
293
+ | `agendaLengthDays(n)` | `MaybeRefOrGetter<number>` | `30` | How many days the visible window covers, starting from `date()`. |
294
+ | `showEmptyDays(b)` | `MaybeRefOrGetter<boolean>` | `false` | When `true`, empty days render a header in italic-grey. When `false`, only days with events appear. |
295
+
296
+ ## Time labels
297
+
298
+ The time column follows one rule, shared with the Month List surface and with the SwiftUI port:
299
+
300
+ | Event | Label |
301
+ |---|---|
302
+ | all-day (`PlainDate` start) | the localised `All day` label |
303
+ | timed with `end` | `start – end`, both in the display zone (en dash, U+2013) |
304
+ | timed without `end` (point event) | the start time only |
305
+
306
+ Formatting goes through `buildFormatOptions` (C6): `locale`, `timeStyle` and `hour12` apply to both ends of the span.
307
+
308
+ ## Multi-day events & continuation tags
309
+
310
+ A multi-day event appears on every day it touches. The first day shows the event normally; subsequent days show it dimmed with a localised `(cont.)` tag appended to the title. Both rows are interactive — clicking either dispatches `onEventClick` with the same event.
311
+
312
+ ## Floating sticky header
313
+
314
+ Because the virtualized surface absolutely-positions every item, native `position: sticky` can't pin them. The agenda renders a separate **floating** day-header overlay above the surface that:
315
+
316
+ - shows the most recent header at-or-before `scrollTop`,
317
+ - gets pushed up by the next inline header crossing into its region (continuous swap, no snap),
318
+ - is reserved as a sibling of the surface so it doesn't scroll with the rows.
319
+
320
+ There's nothing to configure — it's automatic.
321
+
322
+ ## Imperative API
323
+
324
+ ```ts
325
+ interface CalendarApi<TMeta> {
326
+ goTo(iso: string): void;
327
+ goToToday(): void;
328
+ next(): void; // ±agendaLengthDays
329
+ prev(): void;
330
+ getVisibleRange(): ViewWindow | null;
331
+ getVisibleEvents(): CalendarEvent<TMeta>[];
332
+ scrollToDate(iso: string): void; // Agenda only
333
+ refresh(): void;
334
+ refreshRange(start: string, end: string): void;
335
+ readonly loading: Readonly<Ref<boolean>>;
336
+ readonly visibleRange: Readonly<Ref<ViewWindow | null>>;
337
+ readonly gridReady: Readonly<Ref<boolean>>;
338
+ }
339
+ ```
340
+
341
+ ## `<CoarAgendaView>` props + slots
342
+
343
+ | Prop | Type | Description |
344
+ |---|---|---|
345
+ | `builder` | `CalendarBuilder` | **Required.** From `useAgendaView()` (or share the one from `useCalendar()`). |
346
+ | `estimatedItemSize` | `number` | Height estimate for the variable-size virtualization. Default `64`. |
347
+ | `overscan` | `number` | Items beyond the viewport rendered each direction. Default `5`. |
348
+
349
+ | Slot | Scope | Purpose |
350
+ |---|---|---|
351
+ | `event` | `{ event, item }` | Per-row renderer. `item` is the full `AgendaEventItem` (event + `isContinuation` flag). |
352
+ | `dayGroupHeader` | `{ date, item, isToday }` | Per-day header renderer (same component renders the inline + floating overlay). |
353
+ | `empty` | — | Empty state. Shown only when the list draws nothing — no events in the window, `showEmptyDays` off — and no load is in flight. No default; without the slot the surface stays blank. Rendered as a non-interactive overlay so the list stays mounted. Inside `<CoarCalendar>` use the `agendaEmpty` slot. |
354
+ | `weekStripStart` | `WeekStripSlotScope` | Day agenda only. Content at the start of the seven-day week strip, e.g. a previous-week button. |
355
+ | `weekStripEnd` | `WeekStripSlotScope` | Day agenda only. Content at the end of the week strip, e.g. a next-week button. |
356
+
357
+ ### Day agenda week strip
358
+
359
+ `view="dayAgenda"` renders a seven-day strip above the list; tapping a day moves the builder cursor. The strip has two slots for host controls at either end. Both receive the same `WeekStripSlotScope`: `cursor` (selected day), `weekStart` / `weekEnd` (the strip's window), `goTo(date)` and `shiftWeek(n)` — `-1` pages to the previous week, `1` to the next. The slot content sizes itself; the seven day buttons take the remaining width.
360
+
361
+ ```vue
362
+ <CoarAgendaView :builder="builder" view="dayAgenda">
363
+ <template #weekStripStart="{ shiftWeek }">
364
+ <button type="button" aria-label="Vorige Woche" @click="shiftWeek(-1)">‹</button>
365
+ </template>
366
+ <template #weekStripEnd="{ shiftWeek }">
367
+ <button type="button" aria-label="Nächste Woche" @click="shiftWeek(1)">›</button>
368
+ </template>
369
+ </CoarAgendaView>
370
+ ```
371
+
372
+ Inside `<CoarCalendar>` the same slots exist under the same names and reach the day agenda when it is the active view.