@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.
- package/bin/cli.mjs +53 -0
- package/dist/components/checkbox/CoarCheckbox.vue.d.ts +1 -1
- package/dist/components/checkbox/CoarCheckbox.vue.d.ts.map +1 -1
- package/dist/components/code-block/CoarCodeBlock.vue.d.ts +1 -1
- package/dist/components/code-block/CoarCodeBlock.vue.d.ts.map +1 -1
- package/dist/components/data-list/CoarDataList.vue.d.ts +158 -0
- package/dist/components/data-list/CoarDataList.vue.d.ts.map +1 -0
- package/dist/components/data-list/CoarDataListToolbar.vue.d.ts +30 -0
- package/dist/components/data-list/CoarDataListToolbar.vue.d.ts.map +1 -0
- package/dist/components/data-list/data-list-builder.d.ts +288 -0
- package/dist/components/data-list/data-list-builder.d.ts.map +1 -0
- package/dist/components/data-list/index.d.ts +12 -0
- package/dist/components/data-list/index.d.ts.map +1 -0
- package/dist/components/data-list/internal/compare.d.ts +14 -0
- package/dist/components/data-list/internal/compare.d.ts.map +1 -0
- package/dist/components/data-list/internal/reorder-core.d.ts +46 -0
- package/dist/components/data-list/internal/reorder-core.d.ts.map +1 -0
- package/dist/components/data-list/internal/search.d.ts +16 -0
- package/dist/components/data-list/internal/search.d.ts.map +1 -0
- package/dist/components/data-list/internal/useDataListLines.d.ts +92 -0
- package/dist/components/data-list/internal/useDataListLines.d.ts.map +1 -0
- package/dist/components/data-list/internal/useDataListReorder.d.ts +68 -0
- package/dist/components/data-list/internal/useDataListReorder.d.ts.map +1 -0
- package/dist/components/data-list/internal/useSearchHighlight.d.ts +19 -0
- package/dist/components/data-list/internal/useSearchHighlight.d.ts.map +1 -0
- package/dist/components/data-list/types.d.ts +185 -0
- package/dist/components/data-list/types.d.ts.map +1 -0
- package/dist/components/data-list/useDataListModel.d.ts +79 -0
- package/dist/components/data-list/useDataListModel.d.ts.map +1 -0
- package/dist/components/date-time/_shared/maskito-config.d.ts +7 -2
- package/dist/components/date-time/_shared/maskito-config.d.ts.map +1 -1
- package/dist/components/date-time/_shared/time-helpers.d.ts +11 -4
- package/dist/components/date-time/_shared/time-helpers.d.ts.map +1 -1
- package/dist/components/date-time/_shared/use-date-picker-base.d.ts +1 -1
- package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts +1 -1
- package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts.map +1 -1
- package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts +1 -1
- package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts.map +1 -1
- package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts +1 -1
- package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts.map +1 -1
- package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts +3 -0
- package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts.map +1 -1
- package/dist/components/form-field/CoarFormField.vue.d.ts +1 -1
- package/dist/components/form-field/CoarFormField.vue.d.ts.map +1 -1
- package/dist/components/icon/CoarIcon.vue.d.ts +2 -2
- package/dist/components/icon/CoarIcon.vue.d.ts.map +1 -1
- package/dist/components/listbox/CoarListbox.vue.d.ts +7 -0
- package/dist/components/listbox/CoarListbox.vue.d.ts.map +1 -1
- package/dist/components/number-input/CoarNumberInput.vue.d.ts +1 -1
- package/dist/components/number-input/CoarNumberInput.vue.d.ts.map +1 -1
- package/dist/components/otp-input/CoarOtpInput.vue.d.ts +1 -1
- package/dist/components/otp-input/CoarOtpInput.vue.d.ts.map +1 -1
- package/dist/components/password-input/CoarPasswordInput.vue.d.ts +1 -1
- package/dist/components/password-input/CoarPasswordInput.vue.d.ts.map +1 -1
- package/dist/components/switch/CoarSwitch.vue.d.ts +1 -1
- package/dist/components/switch/CoarSwitch.vue.d.ts.map +1 -1
- package/dist/components/text-input/CoarTextInput.vue.d.ts +1 -1
- package/dist/components/text-input/CoarTextInput.vue.d.ts.map +1 -1
- package/dist/composables/dragRegistry.d.ts +12 -0
- package/dist/composables/dragRegistry.d.ts.map +1 -1
- package/dist/composables/index.d.ts +2 -2
- package/dist/composables/index.d.ts.map +1 -1
- package/dist/composables/useDragDrop.d.ts +62 -6
- package/dist/composables/useDragDrop.d.ts.map +1 -1
- package/dist/composables/useVirtualList.d.ts +21 -1
- package/dist/composables/useVirtualList.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4508 -2039
- package/package.json +9 -3
- package/skills/cocoar-vue-ui/SKILL.md +244 -0
- package/skills/cocoar-vue-ui/references/components/avatar.md +178 -0
- package/skills/cocoar-vue-ui/references/components/badge.md +290 -0
- package/skills/cocoar-vue-ui/references/components/breadcrumb.md +238 -0
- package/skills/cocoar-vue-ui/references/components/button.md +252 -0
- package/skills/cocoar-vue-ui/references/components/calendar/agenda-view.md +372 -0
- package/skills/cocoar-vue-ui/references/components/calendar/coar-calendar.md +1647 -0
- package/skills/cocoar-vue-ui/references/components/calendar/day-view.md +361 -0
- package/skills/cocoar-vue-ui/references/components/calendar/index.md +312 -0
- package/skills/cocoar-vue-ui/references/components/calendar/month-view.md +486 -0
- package/skills/cocoar-vue-ui/references/components/calendar/performance.md +186 -0
- package/skills/cocoar-vue-ui/references/components/calendar/timeline-view.md +301 -0
- package/skills/cocoar-vue-ui/references/components/calendar/week-view.md +382 -0
- package/skills/cocoar-vue-ui/references/components/calendar/work-week-view.md +145 -0
- package/skills/cocoar-vue-ui/references/components/calendar/year-view.md +63 -0
- package/skills/cocoar-vue-ui/references/components/card.md +151 -0
- package/skills/cocoar-vue-ui/references/components/checkbox-group.md +103 -0
- package/skills/cocoar-vue-ui/references/components/checkbox.md +279 -0
- package/skills/cocoar-vue-ui/references/components/code-block.md +241 -0
- package/skills/cocoar-vue-ui/references/components/context-menu.md +355 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/checkbox.md +213 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/date-columns.md +272 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/editing.md +236 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/multi-select.md +193 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/number.md +147 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/select.md +202 -0
- package/skills/cocoar-vue-ui/references/components/data-grid/text.md +127 -0
- package/skills/cocoar-vue-ui/references/components/data-grid.md +1225 -0
- package/skills/cocoar-vue-ui/references/components/data-list.md +2121 -0
- package/skills/cocoar-vue-ui/references/components/date-or-time-picker.md +200 -0
- package/skills/cocoar-vue-ui/references/components/date-picker.md +203 -0
- package/skills/cocoar-vue-ui/references/components/date-time-picker.md +154 -0
- package/skills/cocoar-vue-ui/references/components/date-views.md +212 -0
- package/skills/cocoar-vue-ui/references/components/dialog.md +148 -0
- package/skills/cocoar-vue-ui/references/components/divider.md +157 -0
- package/skills/cocoar-vue-ui/references/components/document-viewer/annotations.md +400 -0
- package/skills/cocoar-vue-ui/references/components/document-viewer/coar-document-viewer.md +327 -0
- package/skills/cocoar-vue-ui/references/components/document-viewer/index.md +234 -0
- package/skills/cocoar-vue-ui/references/components/document-viewer/toolbar.md +221 -0
- package/skills/cocoar-vue-ui/references/components/drag-drop.md +267 -0
- package/skills/cocoar-vue-ui/references/components/dual-listbox.md +449 -0
- package/skills/cocoar-vue-ui/references/components/file-explorer/asset-store.md +327 -0
- package/skills/cocoar-vue-ui/references/components/file-explorer/in-memory-store.md +176 -0
- package/skills/cocoar-vue-ui/references/components/file-explorer/index.md +311 -0
- package/skills/cocoar-vue-ui/references/components/file-explorer/use-file-explorer.md +300 -0
- package/skills/cocoar-vue-ui/references/components/form-field.md +1025 -0
- package/skills/cocoar-vue-ui/references/components/fragment-parser.md +298 -0
- package/skills/cocoar-vue-ui/references/components/link.md +235 -0
- package/skills/cocoar-vue-ui/references/components/listbox.md +575 -0
- package/skills/cocoar-vue-ui/references/components/map/editor.md +448 -0
- package/skills/cocoar-vue-ui/references/components/map/index.md +351 -0
- package/skills/cocoar-vue-ui/references/components/markdown-diagrams.md +210 -0
- package/skills/cocoar-vue-ui/references/components/markdown-editor.md +1478 -0
- package/skills/cocoar-vue-ui/references/components/markdown-embeds.md +387 -0
- package/skills/cocoar-vue-ui/references/components/markdown-form.md +447 -0
- package/skills/cocoar-vue-ui/references/components/markdown.md +276 -0
- package/skills/cocoar-vue-ui/references/components/menu.md +380 -0
- package/skills/cocoar-vue-ui/references/components/mermaid.md +172 -0
- package/skills/cocoar-vue-ui/references/components/navbar.md +147 -0
- package/skills/cocoar-vue-ui/references/components/note.md +96 -0
- package/skills/cocoar-vue-ui/references/components/notice.md +131 -0
- package/skills/cocoar-vue-ui/references/components/number-input.md +215 -0
- package/skills/cocoar-vue-ui/references/components/otp-input.md +324 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/authoring-contract.md +271 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-builder.md +476 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-renderer.md +677 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/custom-elements.md +441 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/idp-integration.md +122 -0
- package/skills/cocoar-vue-ui/references/components/page-builder/index.md +573 -0
- package/skills/cocoar-vue-ui/references/components/pagination.md +150 -0
- package/skills/cocoar-vue-ui/references/components/panel-layout.md +372 -0
- package/skills/cocoar-vue-ui/references/components/password-input.md +175 -0
- package/skills/cocoar-vue-ui/references/components/popconfirm.md +186 -0
- package/skills/cocoar-vue-ui/references/components/popover.md +173 -0
- package/skills/cocoar-vue-ui/references/components/progress-bar.md +178 -0
- package/skills/cocoar-vue-ui/references/components/radio-group.md +225 -0
- package/skills/cocoar-vue-ui/references/components/script-editor.md +1271 -0
- package/skills/cocoar-vue-ui/references/components/segmented-control.md +238 -0
- package/skills/cocoar-vue-ui/references/components/select.md +463 -0
- package/skills/cocoar-vue-ui/references/components/sidebar.md +421 -0
- package/skills/cocoar-vue-ui/references/components/spinner.md +132 -0
- package/skills/cocoar-vue-ui/references/components/switch.md +195 -0
- package/skills/cocoar-vue-ui/references/components/table.md +170 -0
- package/skills/cocoar-vue-ui/references/components/tabs.md +382 -0
- package/skills/cocoar-vue-ui/references/components/tag.md +178 -0
- package/skills/cocoar-vue-ui/references/components/text-input.md +256 -0
- package/skills/cocoar-vue-ui/references/components/toast.md +160 -0
- package/skills/cocoar-vue-ui/references/components/tooltip.md +121 -0
- package/skills/cocoar-vue-ui/references/components/transitions.md +193 -0
- package/skills/cocoar-vue-ui/references/components/tree.md +2388 -0
- package/skills/cocoar-vue-ui/references/components/virtual-list.md +212 -0
- package/skills/cocoar-vue-ui/references/components/wizard.md +251 -0
- package/skills/cocoar-vue-ui/references/components/zoned-date-time-picker.md +177 -0
- package/skills/cocoar-vue-ui/references/foundations/colors.md +708 -0
- package/skills/cocoar-vue-ui/references/foundations/design-principles.md +115 -0
- package/skills/cocoar-vue-ui/references/foundations/icons.md +381 -0
- package/skills/cocoar-vue-ui/references/foundations/localization/formatting.md +530 -0
- package/skills/cocoar-vue-ui/references/foundations/localization/setup.md +86 -0
- package/skills/cocoar-vue-ui/references/foundations/localization/timezones.md +182 -0
- package/skills/cocoar-vue-ui/references/foundations/localization/translations.md +305 -0
- package/skills/cocoar-vue-ui/references/foundations/motion.md +549 -0
- package/skills/cocoar-vue-ui/references/foundations/spacing.md +330 -0
- package/skills/cocoar-vue-ui/references/foundations/theming.md +140 -0
- package/skills/cocoar-vue-ui/references/foundations/typography.md +206 -0
- package/skills/cocoar-vue-ui/references/guide/error-handling.md +162 -0
- package/skills/cocoar-vue-ui/references/guide/getting-started.md +116 -0
- package/skills/cocoar-vue-ui/references/guide/migration-page-builder-3.md +207 -0
- package/skills/cocoar-vue-ui/references/guide/migration.md +140 -0
- 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.
|