@vmz/ui 0.3.6 → 0.3.7

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 (42) hide show
  1. package/README.md +51 -51
  2. package/package.json +2 -2
  3. package/src/components/Accordion.vmz +94 -94
  4. package/src/components/AppShell.vmz +5 -2
  5. package/src/components/Autocomplete.vmz +154 -154
  6. package/src/components/Badge.vmz +70 -70
  7. package/src/components/Breadcrumb.vmz +72 -72
  8. package/src/components/BulkActions.vmz +51 -51
  9. package/src/components/Button.vmz +213 -211
  10. package/src/components/Callout.vmz +77 -77
  11. package/src/components/Card.vmz +120 -120
  12. package/src/components/Checkbox.vmz +55 -55
  13. package/src/components/CodeBlock.vmz +21 -6
  14. package/src/components/ConsoleShell.vmz +251 -251
  15. package/src/components/DataTable.vmz +194 -194
  16. package/src/components/DatePicker.vmz +674 -674
  17. package/src/components/Dialog.vmz +17 -1
  18. package/src/components/Drawer.vmz +427 -427
  19. package/src/components/Dropdown.vmz +51 -5
  20. package/src/components/Empty.vmz +54 -54
  21. package/src/components/Field.vmz +115 -115
  22. package/src/components/FormItem.vmz +79 -79
  23. package/src/components/Link.vmz +5 -1
  24. package/src/components/List.vmz +102 -102
  25. package/src/components/Menu.vmz +243 -243
  26. package/src/components/Pagination.vmz +71 -69
  27. package/src/components/Popover.vmz +223 -223
  28. package/src/components/Prose.vmz +81 -81
  29. package/src/components/RadioGroup.vmz +124 -124
  30. package/src/components/Segmented.vmz +51 -51
  31. package/src/components/Select.vmz +533 -533
  32. package/src/components/Steps.vmz +103 -103
  33. package/src/components/Switch.vmz +98 -98
  34. package/src/components/Table.vmz +165 -165
  35. package/src/components/Tabs.vmz +110 -110
  36. package/src/components/Tag.vmz +43 -43
  37. package/src/components/TextArea.vmz +118 -118
  38. package/src/components/Timeline.vmz +76 -76
  39. package/src/components/Toc.vmz +74 -74
  40. package/src/components/Tooltip.vmz +58 -58
  41. package/src/components/Tree.vmz +191 -191
  42. package/src/components/Upload.vmz +1299 -1289
@@ -1,211 +1,213 @@
1
- <template>
2
- <a v-if="href" data-vmz-ui="button" data-vmz-motion="control" data-vmz-motion-token="motion.control" :data-variant="variant" :data-size="size" :data-block="block ? 'true' : 'false'" :href="href" :target="target" :rel="rel" @click="onDomClick" class="vmz-ui-btn">
3
- <span v-if="loading" aria-hidden="true" class="vmz-ui-btn__spinner" />
4
- <slot />
5
- </a>
6
- <button v-else :type="type" data-vmz-ui="button" data-vmz-motion="control" data-vmz-motion-token="motion.control" :data-variant="variant" :data-size="size" :data-block="block ? 'true' : 'false'" :data-loading="loading ? 'true' : 'false'" :disabled="disabled" :aria-busy="loading ? 'true' : 'false'" :aria-haspopup="ariaHaspopup" :aria-controls="ariaControls" @click="onDomClick" class="vmz-ui-btn">
7
- <span v-if="loading" aria-hidden="true" class="vmz-ui-btn__spinner" />
8
- <slot />
9
- </button>
10
- </template>
11
- <style>
12
- .vmz-ui-btn {
13
- display: inline-flex;
14
- align-items: center;
15
- justify-content: center;
16
- gap: 0.375rem;
17
- min-height: var(--vmz-control-height, 2rem);
18
- padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
19
- border: 1px solid transparent;
20
- border-radius: var(--vmz-radius-md, 6px);
21
- font: inherit;
22
- font-size: 0.875rem;
23
- font-weight: 500;
24
- line-height: 1.5715;
25
- white-space: nowrap;
26
- cursor: pointer;
27
- background: var(--vmz-action-primary-background);
28
- color: var(--vmz-action-primary-foreground);
29
- outline: none;
30
- box-shadow: 0 2px 0 color-mix(in srgb, var(--vmz-action-primary-background) 12%, transparent);
31
- transition:
32
- background-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
33
- border-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
34
- color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
35
- box-shadow var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
36
- }
37
-
38
- .vmz-ui-btn[data-size="small"] {
39
- min-height: var(--vmz-control-height-sm, 1.5rem);
40
- padding: 0 0.625rem;
41
- font-size: 0.8125rem;
42
- }
43
- .vmz-ui-btn[data-size="large"] {
44
- min-height: var(--vmz-control-height-lg, 2.5rem);
45
- padding: 0.4375rem 1.125rem;
46
- font-size: 1rem;
47
- }
48
- .vmz-ui-btn[data-block="true"] {
49
- width: 100%;
50
- }
51
- .vmz-ui-btn[data-loading="true"] {
52
- cursor: wait;
53
- }
54
- .vmz-ui-btn__spinner {
55
- width: 1em;
56
- height: 1em;
57
- border: 1.5px solid currentColor;
58
- border-right-color: transparent;
59
- border-radius: 50%;
60
- opacity: 0.8;
61
- animation: vmz-btn-spin 0.7s linear infinite;
62
- }
63
- @keyframes vmz-btn-spin {
64
- to {
65
- transform: rotate(360deg);
66
- }
67
- }
68
-
69
- .vmz-ui-btn:hover:not(:disabled) {
70
- background: var(--vmz-action-primary-hover);
71
- }
72
-
73
- .vmz-ui-btn:active:not(:disabled) {
74
- background: var(--vmz-action-primary-active);
75
- transform: translateY(0.5px);
76
- }
77
-
78
- .vmz-ui-btn[data-variant="secondary"] {
79
- background: var(--vmz-action-secondary-background);
80
- color: var(--vmz-action-secondary-foreground);
81
- border-color: var(--vmz-action-secondary-border);
82
- box-shadow: none;
83
- }
84
- .vmz-ui-btn[data-variant="default"] {
85
- background: var(--vmz-surface-paper);
86
- color: var(--vmz-text-ink);
87
- border-color: var(--vmz-line-default);
88
- box-shadow: none;
89
- }
90
- .vmz-ui-btn[data-variant="default"]:hover:not(:disabled) {
91
- color: var(--vmz-action-primary-hover);
92
- border-color: var(--vmz-action-primary-hover);
93
- background: var(--vmz-surface-paper);
94
- }
95
- .vmz-ui-btn[data-variant="text"],
96
- .vmz-ui-btn[data-variant="link"] {
97
- min-height: auto;
98
- padding: 0.25rem 0.5rem;
99
- border-color: transparent;
100
- background: transparent;
101
- color: var(--vmz-action-primary-background);
102
- box-shadow: none;
103
- }
104
- .vmz-ui-btn[data-variant="dashed"] {
105
- background: var(--vmz-surface-paper);
106
- color: var(--vmz-text-ink);
107
- border: 1px dashed var(--vmz-line-default);
108
- box-shadow: none;
109
- }
110
-
111
- .vmz-ui-btn[data-variant="secondary"]:hover:not(:disabled) {
112
- background: var(--vmz-action-secondary-hover);
113
- }
114
-
115
- .vmz-ui-btn[data-variant="secondary"]:active:not(:disabled) {
116
- background: var(--vmz-action-secondary-hover);
117
- border-color: var(--vmz-action-primary-active);
118
- }
119
-
120
- .vmz-ui-btn[data-variant="ghost"] {
121
- background: transparent;
122
- color: var(--vmz-text-ink);
123
- border-color: transparent;
124
- }
125
-
126
- .vmz-ui-btn[data-variant="ghost"]:hover:not(:disabled) {
127
- background: color-mix(in srgb, var(--vmz-surface-mist) 85%, transparent);
128
- }
129
-
130
- .vmz-ui-btn[data-variant="ghost"]:active:not(:disabled) {
131
- background: var(--vmz-surface-mist);
132
- }
133
-
134
- .vmz-ui-btn[data-variant="danger"] {
135
- background: var(--vmz-status-danger-accent);
136
- color: var(--vmz-action-primary-foreground);
137
- border-color: transparent;
138
- }
139
-
140
- .vmz-ui-btn[data-variant="danger"]:hover:not(:disabled) {
141
- background: color-mix(in srgb, var(--vmz-status-danger-accent) 82%, var(--vmz-text-ink));
142
- }
143
-
144
- .vmz-ui-btn[data-variant="danger"]:active:not(:disabled) {
145
- background: var(--vmz-status-danger-foreground);
146
- }
147
-
148
- .vmz-ui-btn:focus-visible {
149
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
150
- }
151
-
152
- .vmz-ui-btn[data-variant="default"]:focus-visible,
153
- .vmz-ui-btn[data-variant="dashed"]:focus-visible,
154
- .vmz-ui-btn[data-variant="secondary"]:focus-visible,
155
- .vmz-ui-btn[data-variant="ghost"]:focus-visible,
156
- .vmz-ui-btn[data-variant="text"]:focus-visible,
157
- .vmz-ui-btn[data-variant="link"]:focus-visible {
158
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
159
- }
160
-
161
- .vmz-ui-btn:disabled {
162
- opacity: 0.55;
163
- cursor: not-allowed;
164
- box-shadow: none;
165
- transform: none;
166
- }
167
-
168
- :where([data-density="compact"]) .vmz-ui-btn {
169
- padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
170
- }
171
-
172
- :where([data-density="dense"]) .vmz-ui-btn {
173
- padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
174
- }
175
-
176
- @media (prefers-reduced-motion: reduce) {
177
- .vmz-ui-btn {
178
- transition: none;
179
- }
180
- .vmz-ui-btn:active:not(:disabled) {
181
- transform: none;
182
- }
183
- }
184
- </style>
185
- <script client>
186
- /**
187
- * VMZ UI — Button (variants + motion control feedback).
188
- * Colors / motion come only from Style Theme semantic tokens — never brand hex.
189
- * Variants: primary | secondary | ghost | danger
190
- */
191
- export default class Button {
192
- /** @type {'contents'} Direct host: no layout box (`ui-direct-host-box`). */
193
- static __vmzHostBox = "contents";
194
- public type: string = "button";
195
- public variant: string = "primary";
196
- public disabled: boolean = false;
197
- public loading: boolean = false;
198
- public block: boolean = false;
199
- public size: string = "middle";
200
- public href: string = "";
201
- public target: string = "";
202
- public rel: string = "";
203
- public ariaHaspopup: string = "";
204
- public ariaControls: string = "";
205
- public onClick: ((e: Event) => void) | null = null;
206
- onDomClick(e: Event) {
207
- this.emit("click", e);
208
- if (typeof this.onClick === "function") this.onClick(e);
209
- }
210
- }
211
- </script>
1
+ <template>
2
+ <a v-if="href" data-vmz-ui="button" data-vmz-motion="control" data-vmz-motion-token="motion.control" :data-variant="variant" :data-size="size" :data-block="block ? 'true' : 'false'" :href="href" :target="target" :rel="rel" @click="onDomClick" class="vmz-ui-btn">
3
+ <span v-if="loading" aria-hidden="true" class="vmz-ui-btn__spinner" />
4
+ <slot />
5
+ </a>
6
+ <button v-else :type="type" data-vmz-ui="button" data-vmz-motion="control" data-vmz-motion-token="motion.control" :data-variant="variant" :data-size="size" :data-block="block ? 'true' : 'false'" :data-loading="loading ? 'true' : 'false'" :disabled="disabled" :aria-busy="loading ? 'true' : 'false'" :aria-haspopup="ariaHaspopup" :aria-controls="ariaControls" @click="onDomClick" class="vmz-ui-btn">
7
+ <span v-if="loading" aria-hidden="true" class="vmz-ui-btn__spinner" />
8
+ <slot />
9
+ </button>
10
+ </template>
11
+ <style>
12
+ .vmz-ui-btn {
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ gap: 0.375rem;
17
+ /* Inline control: never stretch when the parent is a flex column (shells, card bodies). */
18
+ width: fit-content;
19
+ min-height: var(--vmz-control-height, 2rem);
20
+ padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
21
+ border: 1px solid transparent;
22
+ border-radius: var(--vmz-radius-md, 6px);
23
+ font: inherit;
24
+ font-size: 0.875rem;
25
+ font-weight: 500;
26
+ line-height: 1.5715;
27
+ white-space: nowrap;
28
+ cursor: pointer;
29
+ background: var(--vmz-action-primary-background);
30
+ color: var(--vmz-action-primary-foreground);
31
+ outline: none;
32
+ box-shadow: 0 2px 0 color-mix(in srgb, var(--vmz-action-primary-background) 12%, transparent);
33
+ transition:
34
+ background-color var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
35
+ border-color var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
36
+ color var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
37
+ box-shadow var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
38
+ }
39
+
40
+ .vmz-ui-btn[data-size="small"] {
41
+ min-height: var(--vmz-control-height-sm, 1.5rem);
42
+ padding: 0 0.625rem;
43
+ font-size: 0.8125rem;
44
+ }
45
+ .vmz-ui-btn[data-size="large"] {
46
+ min-height: var(--vmz-control-height-lg, 2.5rem);
47
+ padding: 0.4375rem 1.125rem;
48
+ font-size: 1rem;
49
+ }
50
+ .vmz-ui-btn[data-block="true"] {
51
+ width: 100%;
52
+ }
53
+ .vmz-ui-btn[data-loading="true"] {
54
+ cursor: wait;
55
+ }
56
+ .vmz-ui-btn__spinner {
57
+ width: 1em;
58
+ height: 1em;
59
+ border: 1.5px solid currentColor;
60
+ border-right-color: transparent;
61
+ border-radius: 50%;
62
+ opacity: 0.8;
63
+ animation: vmz-btn-spin 0.7s linear infinite;
64
+ }
65
+ @keyframes vmz-btn-spin {
66
+ to {
67
+ transform: rotate(360deg);
68
+ }
69
+ }
70
+
71
+ .vmz-ui-btn:hover:not(:disabled) {
72
+ background: var(--vmz-action-primary-hover);
73
+ }
74
+
75
+ .vmz-ui-btn:active:not(:disabled) {
76
+ background: var(--vmz-action-primary-active);
77
+ transform: translateY(0.5px);
78
+ }
79
+
80
+ .vmz-ui-btn[data-variant="secondary"] {
81
+ background: var(--vmz-action-secondary-background);
82
+ color: var(--vmz-action-secondary-foreground);
83
+ border-color: var(--vmz-action-secondary-border);
84
+ box-shadow: none;
85
+ }
86
+ .vmz-ui-btn[data-variant="default"] {
87
+ background: var(--vmz-surface-paper);
88
+ color: var(--vmz-text-ink);
89
+ border-color: var(--vmz-line-default);
90
+ box-shadow: none;
91
+ }
92
+ .vmz-ui-btn[data-variant="default"]:hover:not(:disabled) {
93
+ color: var(--vmz-action-primary-hover);
94
+ border-color: var(--vmz-action-primary-hover);
95
+ background: var(--vmz-surface-paper);
96
+ }
97
+ .vmz-ui-btn[data-variant="text"],
98
+ .vmz-ui-btn[data-variant="link"] {
99
+ min-height: auto;
100
+ padding: 0.25rem 0.5rem;
101
+ border-color: transparent;
102
+ background: transparent;
103
+ color: var(--vmz-action-primary-background);
104
+ box-shadow: none;
105
+ }
106
+ .vmz-ui-btn[data-variant="dashed"] {
107
+ background: var(--vmz-surface-paper);
108
+ color: var(--vmz-text-ink);
109
+ border: 1px dashed var(--vmz-line-default);
110
+ box-shadow: none;
111
+ }
112
+
113
+ .vmz-ui-btn[data-variant="secondary"]:hover:not(:disabled) {
114
+ background: var(--vmz-action-secondary-hover);
115
+ }
116
+
117
+ .vmz-ui-btn[data-variant="secondary"]:active:not(:disabled) {
118
+ background: var(--vmz-action-secondary-hover);
119
+ border-color: var(--vmz-action-primary-active);
120
+ }
121
+
122
+ .vmz-ui-btn[data-variant="ghost"] {
123
+ background: transparent;
124
+ color: var(--vmz-text-ink);
125
+ border-color: transparent;
126
+ }
127
+
128
+ .vmz-ui-btn[data-variant="ghost"]:hover:not(:disabled) {
129
+ background: color-mix(in srgb, var(--vmz-surface-mist) 85%, transparent);
130
+ }
131
+
132
+ .vmz-ui-btn[data-variant="ghost"]:active:not(:disabled) {
133
+ background: var(--vmz-surface-mist);
134
+ }
135
+
136
+ .vmz-ui-btn[data-variant="danger"] {
137
+ background: var(--vmz-status-danger-accent);
138
+ color: var(--vmz-action-primary-foreground);
139
+ border-color: transparent;
140
+ }
141
+
142
+ .vmz-ui-btn[data-variant="danger"]:hover:not(:disabled) {
143
+ background: color-mix(in srgb, var(--vmz-status-danger-accent) 82%, var(--vmz-text-ink));
144
+ }
145
+
146
+ .vmz-ui-btn[data-variant="danger"]:active:not(:disabled) {
147
+ background: var(--vmz-status-danger-foreground);
148
+ }
149
+
150
+ .vmz-ui-btn:focus-visible {
151
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
152
+ }
153
+
154
+ .vmz-ui-btn[data-variant="default"]:focus-visible,
155
+ .vmz-ui-btn[data-variant="dashed"]:focus-visible,
156
+ .vmz-ui-btn[data-variant="secondary"]:focus-visible,
157
+ .vmz-ui-btn[data-variant="ghost"]:focus-visible,
158
+ .vmz-ui-btn[data-variant="text"]:focus-visible,
159
+ .vmz-ui-btn[data-variant="link"]:focus-visible {
160
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
161
+ }
162
+
163
+ .vmz-ui-btn:disabled {
164
+ opacity: 0.55;
165
+ cursor: not-allowed;
166
+ box-shadow: none;
167
+ transform: none;
168
+ }
169
+
170
+ :where([data-density="compact"]) .vmz-ui-btn {
171
+ padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
172
+ }
173
+
174
+ :where([data-density="dense"]) .vmz-ui-btn {
175
+ padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
176
+ }
177
+
178
+ @media (prefers-reduced-motion: reduce) {
179
+ .vmz-ui-btn {
180
+ transition: none;
181
+ }
182
+ .vmz-ui-btn:active:not(:disabled) {
183
+ transform: none;
184
+ }
185
+ }
186
+ </style>
187
+ <script client>
188
+ /**
189
+ * VMZ UI — Button (variants + motion control feedback).
190
+ * Colors / motion come only from Style Theme semantic tokens — never brand hex.
191
+ * Variants: primary | secondary | ghost | danger
192
+ */
193
+ export default class Button {
194
+ /** @type {'contents'} Direct host: no layout box (`ui-direct-host-box`). */
195
+ static __vmzHostBox = "contents";
196
+ public type: string = "button";
197
+ public variant: string = "primary";
198
+ public disabled: boolean = false;
199
+ public loading: boolean = false;
200
+ public block: boolean = false;
201
+ public size: string = "middle";
202
+ public href: string = "";
203
+ public target: string = "";
204
+ public rel: string = "";
205
+ public ariaHaspopup: string = "";
206
+ public ariaControls: string = "";
207
+ public onClick: ((e: Event) => void) | null = null;
208
+ onDomClick(e: Event) {
209
+ this.emit("click", e);
210
+ if (typeof this.onClick === "function") this.onClick(e);
211
+ }
212
+ }
213
+ </script>
@@ -1,77 +1,77 @@
1
- <template>
2
- <aside data-vmz-ui="callout" :data-tone="tone" :role="roleName" class="vmz-ui-callout">
3
- <p v-if="title" class="vmz-ui-callout__title">
4
- {{ title }}
5
- </p>
6
- <p v-if="description" class="vmz-ui-callout__description">
7
- {{ description }}
8
- </p>
9
- <div class="vmz-ui-callout__body">
10
- <slot />
11
- </div>
12
- </aside>
13
- </template>
14
- <style>
15
- .vmz-ui-callout {
16
- display: flex;
17
- flex-direction: column;
18
- gap: 0.5rem;
19
- padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
20
- border: 1px solid var(--vmz-status-info-accent);
21
- border-left-width: 1px;
22
- border-radius: var(--vmz-radius-md, 6px);
23
- background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
24
- color: var(--vmz-status-info-foreground);
25
- }
26
-
27
- .vmz-ui-callout[data-tone="info"] {
28
- border-color: var(--vmz-status-info-accent);
29
- background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
30
- color: var(--vmz-status-info-foreground);
31
- }
32
-
33
- .vmz-ui-callout[data-tone="success"] {
34
- border-color: var(--vmz-status-success-accent);
35
- background: color-mix(in srgb, var(--vmz-status-success-accent) 10%, var(--vmz-surface-paper));
36
- color: var(--vmz-status-success-foreground);
37
- }
38
-
39
- .vmz-ui-callout[data-tone="warning"] {
40
- border-color: var(--vmz-status-warning-accent);
41
- background: color-mix(in srgb, var(--vmz-status-warning-accent) 10%, var(--vmz-surface-paper));
42
- color: var(--vmz-status-warning-foreground);
43
- }
44
-
45
- .vmz-ui-callout[data-tone="danger"] {
46
- border-color: var(--vmz-status-danger-accent);
47
- background: color-mix(in srgb, var(--vmz-status-danger-accent) 10%, var(--vmz-surface-paper));
48
- color: var(--vmz-status-danger-foreground);
49
- }
50
-
51
- .vmz-ui-callout__title {
52
- margin: 0;
53
- font-family: var(--vmz-font-display);
54
- font-weight: 700;
55
- }
56
-
57
- .vmz-ui-callout__description {
58
- margin: 0;
59
- line-height: 1.5;
60
- }
61
-
62
- .vmz-ui-callout__body:empty {
63
- display: none;
64
- }
65
- </style>
66
- <script client>
67
- /**
68
- * VMZ UI — Callout (Document/Product composition).
69
- * Inline guidance block for prose; shares status.* tones with Alert.
70
- */
71
- export default class Callout {
72
- public title: string = "";
73
- public description: string = "";
74
- public tone: string = "info";
75
- public roleName: string = "note";
76
- }
77
- </script>
1
+ <template>
2
+ <aside data-vmz-ui="callout" :data-tone="tone" :role="roleName" class="vmz-ui-callout">
3
+ <p v-if="title" class="vmz-ui-callout__title">
4
+ {{ title }}
5
+ </p>
6
+ <p v-if="description" class="vmz-ui-callout__description">
7
+ {{ description }}
8
+ </p>
9
+ <div class="vmz-ui-callout__body">
10
+ <slot />
11
+ </div>
12
+ </aside>
13
+ </template>
14
+ <style>
15
+ .vmz-ui-callout {
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: 0.5rem;
19
+ padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
20
+ border: 1px solid var(--vmz-status-info-accent);
21
+ border-left-width: 1px;
22
+ border-radius: var(--vmz-radius-md, 6px);
23
+ background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
24
+ color: var(--vmz-status-info-foreground);
25
+ }
26
+
27
+ .vmz-ui-callout[data-tone="info"] {
28
+ border-color: var(--vmz-status-info-accent);
29
+ background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
30
+ color: var(--vmz-status-info-foreground);
31
+ }
32
+
33
+ .vmz-ui-callout[data-tone="success"] {
34
+ border-color: var(--vmz-status-success-accent);
35
+ background: color-mix(in srgb, var(--vmz-status-success-accent) 10%, var(--vmz-surface-paper));
36
+ color: var(--vmz-status-success-foreground);
37
+ }
38
+
39
+ .vmz-ui-callout[data-tone="warning"] {
40
+ border-color: var(--vmz-status-warning-accent);
41
+ background: color-mix(in srgb, var(--vmz-status-warning-accent) 10%, var(--vmz-surface-paper));
42
+ color: var(--vmz-status-warning-foreground);
43
+ }
44
+
45
+ .vmz-ui-callout[data-tone="danger"] {
46
+ border-color: var(--vmz-status-danger-accent);
47
+ background: color-mix(in srgb, var(--vmz-status-danger-accent) 10%, var(--vmz-surface-paper));
48
+ color: var(--vmz-status-danger-foreground);
49
+ }
50
+
51
+ .vmz-ui-callout__title {
52
+ margin: 0;
53
+ font-family: var(--vmz-font-display);
54
+ font-weight: 700;
55
+ }
56
+
57
+ .vmz-ui-callout__description {
58
+ margin: 0;
59
+ line-height: 1.5;
60
+ }
61
+
62
+ .vmz-ui-callout__body:empty {
63
+ display: none;
64
+ }
65
+ </style>
66
+ <script client>
67
+ /**
68
+ * VMZ UI — Callout (Document/Product composition).
69
+ * Inline guidance block for prose; shares status.* tones with Alert.
70
+ */
71
+ export default class Callout {
72
+ public title: string = "";
73
+ public description: string = "";
74
+ public tone: string = "info";
75
+ public roleName: string = "note";
76
+ }
77
+ </script>