@vmz/ui 0.3.6 → 0.3.8

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 (68) hide show
  1. package/README.md +53 -51
  2. package/contracts/token-requirements.v0.json +58 -1
  3. package/package.json +5 -2
  4. package/presets/web-surface.v0.json +14 -12
  5. package/src/components/Accordion.vmz +127 -94
  6. package/src/components/Alert.vmz +125 -28
  7. package/src/components/AppShell.vmz +125 -57
  8. package/src/components/Autocomplete.vmz +261 -154
  9. package/src/components/Avatar.vmz +20 -12
  10. package/src/components/Badge.vmz +62 -70
  11. package/src/components/Breadcrumb.vmz +86 -72
  12. package/src/components/BulkActions.vmz +56 -51
  13. package/src/components/Button.vmz +237 -211
  14. package/src/components/Callout.vmz +178 -77
  15. package/src/components/Card.vmz +141 -120
  16. package/src/components/Checkbox.vmz +131 -55
  17. package/src/components/CodeBlock.vmz +77 -30
  18. package/src/components/Collapse.vmz +64 -11
  19. package/src/components/ConsoleShell.vmz +405 -251
  20. package/src/components/Content.vmz +15 -1
  21. package/src/components/DataTable.vmz +294 -194
  22. package/src/components/DatePicker.vmz +766 -674
  23. package/src/components/Descriptions.vmz +90 -0
  24. package/src/components/Dialog.vmz +137 -38
  25. package/src/components/Divider.vmz +8 -1
  26. package/src/components/Drawer.vmz +518 -427
  27. package/src/components/Dropdown.vmz +195 -51
  28. package/src/components/Empty.vmz +96 -54
  29. package/src/components/Field.vmz +170 -115
  30. package/src/components/FilterBar.vmz +34 -4
  31. package/src/components/Flex.vmz +3 -1
  32. package/src/components/Footer.vmz +6 -3
  33. package/src/components/Form.vmz +41 -0
  34. package/src/components/FormItem.vmz +78 -79
  35. package/src/components/Grid.vmz +6 -3
  36. package/src/components/Header.vmz +193 -6
  37. package/src/components/Layout.vmz +3 -1
  38. package/src/components/Link.vmz +25 -10
  39. package/src/components/List.vmz +124 -102
  40. package/src/components/Menu.vmz +416 -243
  41. package/src/components/Message.vmz +167 -0
  42. package/src/components/Notification.vmz +132 -37
  43. package/src/components/Pagination.vmz +237 -69
  44. package/src/components/Popconfirm.vmz +287 -0
  45. package/src/components/Popover.vmz +341 -223
  46. package/src/components/Progress.vmz +16 -5
  47. package/src/components/Prose.vmz +180 -81
  48. package/src/components/QueryForm.vmz +31 -9
  49. package/src/components/RadioGroup.vmz +204 -124
  50. package/src/components/Result.vmz +60 -27
  51. package/src/components/Segmented.vmz +86 -51
  52. package/src/components/Select.vmz +620 -533
  53. package/src/components/Sider.vmz +120 -7
  54. package/src/components/Skeleton.vmz +9 -7
  55. package/src/components/Space.vmz +9 -3
  56. package/src/components/Spinner.vmz +5 -4
  57. package/src/components/Steps.vmz +118 -103
  58. package/src/components/Switch.vmz +131 -98
  59. package/src/components/Table.vmz +270 -165
  60. package/src/components/Tabs.vmz +125 -110
  61. package/src/components/Tag.vmz +60 -43
  62. package/src/components/TextArea.vmz +125 -118
  63. package/src/components/Timeline.vmz +111 -76
  64. package/src/components/Toc.vmz +90 -74
  65. package/src/components/Tooltip.vmz +107 -58
  66. package/src/components/Tree.vmz +214 -191
  67. package/src/components/Typography.vmz +23 -8
  68. package/src/components/Upload.vmz +1394 -1289
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <dl data-vmz-ui="descriptions" :data-columns="normalizeColumns()" :data-bordered="bordered ? 'true' : 'false'" class="vmz-ui-descriptions">
3
+ <div v-for="item in items" :key="item.term" class="vmz-ui-descriptions__item">
4
+ <dt class="vmz-ui-descriptions__term">
5
+ {{ item.term }}
6
+ </dt>
7
+ <dd :data-vmz-fixture="item.fixture || null" class="vmz-ui-descriptions__detail">
8
+ {{ item.detail }}
9
+ </dd>
10
+ </div>
11
+ <slot />
12
+ </dl>
13
+ </template>
14
+ <style>
15
+ .vmz-ui-descriptions {
16
+ display: grid;
17
+ grid-template-columns: repeat(2, minmax(0, 1fr));
18
+ gap: 0.85rem 1.25rem;
19
+ margin: 0;
20
+ color: var(--vmz-text-ink);
21
+ }
22
+
23
+ .vmz-ui-descriptions[data-columns="1"] {
24
+ grid-template-columns: minmax(0, 1fr);
25
+ }
26
+
27
+ .vmz-ui-descriptions[data-columns="3"] {
28
+ grid-template-columns: repeat(3, minmax(0, 1fr));
29
+ }
30
+
31
+ .vmz-ui-descriptions__item {
32
+ display: grid;
33
+ gap: 0.2rem;
34
+ min-width: 0;
35
+ }
36
+
37
+ .vmz-ui-descriptions__term {
38
+ margin: 0;
39
+ color: var(--vmz-text-steel);
40
+ font-size: 0.8125rem;
41
+ line-height: 1.25rem;
42
+ }
43
+
44
+ .vmz-ui-descriptions__detail {
45
+ margin: 0;
46
+ color: var(--vmz-text-ink);
47
+ font-size: 0.875rem;
48
+ line-height: 1.375rem;
49
+ overflow-wrap: anywhere;
50
+ }
51
+
52
+ .vmz-ui-descriptions[data-bordered="true"] {
53
+ gap: 0;
54
+ border: 1px solid var(--vmz-line-default);
55
+ border-radius: var(--vmz-radius-md);
56
+ overflow: hidden;
57
+ }
58
+
59
+ .vmz-ui-descriptions[data-bordered="true"] .vmz-ui-descriptions__item {
60
+ padding: 0.65rem 0.85rem;
61
+ border-bottom: 1px solid var(--vmz-line-subtle);
62
+ }
63
+
64
+ .vmz-ui-descriptions[data-bordered="true"] .vmz-ui-descriptions__item:last-child {
65
+ border-bottom: 0;
66
+ }
67
+
68
+ @media (max-width: 40rem) {
69
+ .vmz-ui-descriptions,
70
+ .vmz-ui-descriptions[data-columns="3"] {
71
+ grid-template-columns: minmax(0, 1fr);
72
+ }
73
+ }
74
+ </style>
75
+ <script client>
76
+ /**
77
+ * VMZ UI — Descriptions.
78
+ * Read-only key/value detail block (drawer and record detail). Parent owns `items`.
79
+ * No data fetching, no column inference, no editing.
80
+ */
81
+ export default class Descriptions {
82
+ public items: { term: string; detail: string; fixture?: string }[] = [];
83
+ public columns: string = "2";
84
+ public bordered: boolean = false;
85
+ normalizeColumns() {
86
+ const n = Number(this.columns);
87
+ return n === 1 || n === 2 || n === 3 ? String(n) : "2";
88
+ }
89
+ }
90
+ </script>
@@ -1,18 +1,26 @@
1
1
  <template>
2
2
  <div data-vmz-ui="dialog" :data-vmz-overlay-open="open" class="vmz-ui-dialog-root">
3
- <div v-if="open" data-vmz-overlay="dialog" data-vmz-overlay-owner="dialog" :data-vmz-overlay-stack="stackLevel" class="vmz-ui-dialog">
4
- <button type="button" data-vmz-overlay-layer="backdrop" aria-label="Dismiss dialog" @click="dismiss" class="vmz-ui-dialog__backdrop" />
5
- <div role="dialog" aria-modal="true" :aria-labelledby="titleId" tabindex="-1" data-vmz-overlay-layer="panel" data-vmz-focus="enter" data-vmz-motion="overlay-enter" data-vmz-motion-token="motion.overlay" :onKeyDown="onPanelKeyDown" class="vmz-ui-dialog__panel">
6
- <h2 :id="titleId" class="vmz-ui-dialog__title">
7
- {{ title }}
8
- </h2>
3
+ <div v-if="open" data-vmz-overlay="dialog" data-vmz-overlay-owner="dialog" :data-vmz-overlay-stack="stackLevel" :data-size="size" :data-action-size="actionSize" :data-tone="danger ? 'danger' : 'default'" class="vmz-ui-dialog">
4
+ <button type="button" data-vmz-overlay-layer="backdrop" :aria-label="dismissLabel || closeLabel || label || title" @click="dismiss" class="vmz-ui-dialog__backdrop" />
5
+ <div role="dialog" aria-modal="true" :aria-labelledby="title ? titleId : null" tabindex="-1" data-vmz-overlay-layer="panel" data-vmz-focus="enter" data-vmz-motion="overlay-enter" data-vmz-motion-token="motion.overlay" :onKeyDown="onPanelKeyDown" class="vmz-ui-dialog__panel">
6
+ <header class="vmz-ui-dialog__header">
7
+ <div class="vmz-ui-dialog__heading">
8
+ <h2 v-if="title" :id="titleId" class="vmz-ui-dialog__title">
9
+ {{ title }}
10
+ </h2>
11
+ <p v-if="description" class="vmz-ui-dialog__description">
12
+ {{ description }}
13
+ </p>
14
+ </div>
15
+ <button type="button" data-vmz-focus="close" :aria-label="closeLabel || label || title" @click="dismiss" class="vmz-ui-dialog__close">
16
+ <Icon name="action.close" size="md" decorative />
17
+ </button>
18
+ </header>
9
19
  <div class="vmz-ui-dialog__body">
10
20
  <slot />
11
21
  </div>
12
22
  <div class="vmz-ui-dialog__actions">
13
- <button type="button" data-vmz-focus="close" @click="dismiss" class="vmz-ui-dialog__close">
14
- Close
15
- </button>
23
+ <slot name="actions" />
16
24
  </div>
17
25
  </div>
18
26
  </div>
@@ -29,6 +37,8 @@
29
37
  z-index: 40;
30
38
  display: grid;
31
39
  place-items: center;
40
+ box-sizing: border-box;
41
+ padding: 24px;
32
42
  }
33
43
 
34
44
  .vmz-ui-dialog[data-vmz-overlay-stack="1"] {
@@ -50,7 +60,7 @@
50
60
  padding: 0;
51
61
  margin: 0;
52
62
  cursor: pointer;
53
- background: rgba(0, 0, 0, 0.45);
63
+ background: color-mix(in srgb, var(--vmz-surface-ink) 45%, transparent);
54
64
  animation: vmz-ui-overlay-fade-in var(--vmz-motion-overlay-duration)
55
65
  var(--vmz-motion-overlay-easing);
56
66
  }
@@ -58,11 +68,14 @@
58
68
  .vmz-ui-dialog__panel {
59
69
  position: relative;
60
70
  z-index: 1;
61
- width: min(32rem, calc(100vw - 2rem));
62
- padding: 1.25rem 1.5rem 1.25rem;
63
- border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
64
- border-radius: var(--vmz-radius-lg, 8px);
65
- background: var(--vmz-surface-paper, #fff);
71
+ display: flex;
72
+ flex-direction: column;
73
+ box-sizing: border-box;
74
+ width: min(520px, 100%);
75
+ max-height: calc(100vh - 48px);
76
+ border: 1px solid var(--vmz-line-subtle);
77
+ border-radius: var(--vmz-radius-lg);
78
+ background: var(--vmz-surface-paper);
66
79
  color: var(--vmz-text-ink);
67
80
  box-shadow: var(--vmz-shadow-popup);
68
81
  outline: none;
@@ -70,6 +83,14 @@
70
83
  var(--vmz-motion-overlay-easing);
71
84
  }
72
85
 
86
+ .vmz-ui-dialog[data-size="sm"] .vmz-ui-dialog__panel {
87
+ width: min(400px, 100%);
88
+ }
89
+
90
+ .vmz-ui-dialog[data-size="lg"] .vmz-ui-dialog__panel {
91
+ width: min(720px, 100%);
92
+ }
93
+
73
94
  .vmz-ui-dialog[data-vmz-motion-adopt="true"] .vmz-ui-dialog__backdrop,
74
95
  .vmz-ui-dialog[data-vmz-motion-adopt="true"] .vmz-ui-dialog__panel {
75
96
  animation: none;
@@ -86,47 +107,109 @@
86
107
  }
87
108
 
88
109
  .vmz-ui-dialog__panel:focus-visible {
89
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
110
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring), var(--vmz-shadow-popup);
111
+ }
112
+
113
+ .vmz-ui-dialog__header {
114
+ display: flex;
115
+ align-items: flex-start;
116
+ gap: 16px;
117
+ padding: 20px 24px 16px;
118
+ }
119
+
120
+ .vmz-ui-dialog__heading {
121
+ flex: 1 1 auto;
122
+ min-width: 0;
90
123
  }
91
124
 
92
125
  .vmz-ui-dialog__title {
93
- margin: 0 0 0.75rem;
94
- font-size: 1rem;
126
+ margin: 0;
127
+ font-size: 18px;
95
128
  font-weight: 600;
96
- line-height: 1.4;
129
+ line-height: 24px;
97
130
  color: var(--vmz-text-ink);
98
131
  }
99
132
 
100
- .vmz-ui-dialog__body {
101
- margin-bottom: 1rem;
102
- color: var(--vmz-text-ink);
133
+ .vmz-ui-dialog[data-tone="danger"] .vmz-ui-dialog__title {
134
+ color: var(--vmz-status-danger-foreground);
135
+ }
136
+
137
+ .vmz-ui-dialog__description {
138
+ margin: 6px 0 0;
139
+ font-size: 14px;
140
+ line-height: 22px;
141
+ color: var(--vmz-text-tertiary);
103
142
  }
104
143
 
105
144
  .vmz-ui-dialog__close {
106
- font: inherit;
107
- font-size: 0.875rem;
108
- font-weight: 500;
109
- min-height: var(--vmz-control-height, 2rem);
110
- padding: 0.25rem 0.9375rem;
111
- border: 1px solid var(--vmz-line-default);
112
- border-radius: var(--vmz-radius-md, 6px);
145
+ flex: 0 0 auto;
146
+ display: inline-flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ width: 32px;
150
+ height: 32px;
151
+ margin: -4px -8px 0 0;
152
+ padding: 0;
153
+ border: 0;
154
+ border-radius: var(--vmz-radius-md);
155
+ background: transparent;
156
+ color: var(--vmz-text-steel);
113
157
  cursor: pointer;
114
- background: var(--vmz-surface-paper);
115
- color: var(--vmz-text-ink);
158
+ outline: none;
116
159
  transition:
117
- color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
118
- border-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
160
+ color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
161
+ background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
119
162
  }
120
163
 
121
164
  .vmz-ui-dialog__close:hover {
122
- color: var(--vmz-action-primary-hover);
123
- border-color: var(--vmz-action-primary-hover);
165
+ background: var(--vmz-surface-mist);
166
+ color: var(--vmz-text-ink);
124
167
  }
125
168
 
126
169
  .vmz-ui-dialog__close:focus-visible {
127
170
  box-shadow: 0 0 0 3px var(--vmz-focus-ring);
128
171
  }
129
172
 
173
+ .vmz-ui-dialog__body {
174
+ flex: 1 1 auto;
175
+ min-height: 0;
176
+ padding: 0 24px 20px;
177
+ overflow: auto;
178
+ font-size: 14px;
179
+ line-height: 22px;
180
+ color: var(--vmz-text-ink);
181
+ }
182
+
183
+ .vmz-ui-dialog__body :where(a) {
184
+ color: var(--vmz-action-primary-background);
185
+ text-underline-offset: 2px;
186
+ }
187
+
188
+ .vmz-ui-dialog__body :where(a):hover {
189
+ color: var(--vmz-action-primary-hover);
190
+ }
191
+
192
+ .vmz-ui-dialog__actions {
193
+ display: flex;
194
+ flex-wrap: wrap;
195
+ align-items: center;
196
+ justify-content: flex-end;
197
+ gap: 8px;
198
+ padding: 0 24px 20px;
199
+ }
200
+
201
+ .vmz-ui-dialog__actions:empty {
202
+ display: none;
203
+ }
204
+
205
+ .vmz-ui-dialog__actions :where(button, a) {
206
+ min-height: var(--vmz-control-height, 32px);
207
+ }
208
+
209
+ .vmz-ui-dialog[data-action-size="lg"] .vmz-ui-dialog__actions :where(button, a) {
210
+ min-height: 40px;
211
+ }
212
+
130
213
  @keyframes vmz-ui-overlay-fade-in {
131
214
  from {
132
215
  opacity: 0;
@@ -139,7 +222,7 @@
139
222
  @keyframes vmz-ui-overlay-panel-in {
140
223
  from {
141
224
  opacity: 0;
142
- transform: translateY(0.35rem);
225
+ transform: translateY(8px) scale(0.98);
143
226
  }
144
227
  to {
145
228
  opacity: 1;
@@ -163,16 +246,18 @@
163
246
  }
164
247
  to {
165
248
  opacity: 0;
166
- transform: translateY(0.35rem);
249
+ transform: translateY(8px) scale(0.98);
167
250
  }
168
251
  }
169
252
 
170
253
  @media (prefers-reduced-motion: reduce) {
171
254
  .vmz-ui-dialog__backdrop,
172
255
  .vmz-ui-dialog__panel,
256
+ .vmz-ui-dialog__close,
173
257
  .vmz-ui-dialog[data-vmz-motion-phase="exit"] .vmz-ui-dialog__backdrop,
174
258
  .vmz-ui-dialog[data-vmz-motion-phase="exit"] .vmz-ui-dialog__panel {
175
259
  animation: none;
260
+ transition: none;
176
261
  }
177
262
  }
178
263
  </style>
@@ -181,10 +266,24 @@
181
266
  * VMZ UI — Dialog (UI1).
182
267
  * Live `open` + overlay ownership + focus + Escape/outside dismiss + stackLevel.
183
268
  * SSR/resume adopt skips enter replay; dismiss plays overlay-exit then calls onClose.
269
+ *
270
+ * Appearance props: `size` (sm 400 / md 520 / lg 720), `danger` tone,
271
+ * `description`, `actionSize` (md 32 / lg 40 action buttons).
272
+ * Visible copy is author-supplied; `closeLabel` / `dismissLabel` only name the
273
+ * icon button and backdrop for assistive tech.
184
274
  */
185
275
  export default class Dialog {
186
276
  public open: boolean = false;
187
- public title: string = "Dialog";
277
+ public title: string = "";
278
+ public label: string = "";
279
+ public description: string = "";
280
+ /** sm | md | lg */
281
+ public size: string = "md";
282
+ /** md | lg */
283
+ public actionSize: string = "md";
284
+ public danger: boolean = false;
285
+ public closeLabel: string = "";
286
+ public dismissLabel: string = "";
188
287
  public titleId: string = "vmz-dialog-title";
189
288
  public stackLevel: string = "0";
190
289
  public onClose: (() => void) | null = null;
@@ -9,11 +9,13 @@
9
9
  .vmz-ui-divider {
10
10
  display: flex;
11
11
  align-items: center;
12
- gap: 0.75rem;
12
+ gap: var(--vmz-space-3);
13
13
  width: 100%;
14
14
  color: var(--vmz-text-steel);
15
15
  font-size: 0.875rem;
16
+ line-height: 1.5715;
16
17
  }
18
+
17
19
  .vmz-ui-divider:before,
18
20
  .vmz-ui-divider:after {
19
21
  content: "";
@@ -21,18 +23,23 @@
21
23
  flex: 1;
22
24
  background: var(--vmz-line-default);
23
25
  }
26
+
24
27
  .vmz-ui-divider:not(:has(span)):before {
25
28
  flex: 1;
26
29
  }
30
+
27
31
  .vmz-ui-divider:not(:has(span)):after {
28
32
  display: none;
29
33
  }
34
+
30
35
  .vmz-ui-divider[data-direction="vertical"] {
31
36
  display: inline-block;
32
37
  width: 1px;
33
38
  height: 1em;
39
+ margin: 0 var(--vmz-space-2);
34
40
  background: var(--vmz-line-default);
35
41
  }
42
+
36
43
  .vmz-ui-divider[data-direction="vertical"]:before,
37
44
  .vmz-ui-divider[data-direction="vertical"]:after {
38
45
  display: none;