@vmz/ui 0.3.7 → 0.3.9

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 +2 -0
  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 +49 -16
  6. package/src/components/Alert.vmz +125 -28
  7. package/src/components/AppShell.vmz +121 -56
  8. package/src/components/Autocomplete.vmz +136 -29
  9. package/src/components/Avatar.vmz +20 -12
  10. package/src/components/Badge.vmz +18 -26
  11. package/src/components/Breadcrumb.vmz +28 -14
  12. package/src/components/BulkActions.vmz +13 -8
  13. package/src/components/Button.vmz +68 -44
  14. package/src/components/Callout.vmz +128 -27
  15. package/src/components/Card.vmz +67 -46
  16. package/src/components/Checkbox.vmz +81 -5
  17. package/src/components/CodeBlock.vmz +59 -27
  18. package/src/components/Collapse.vmz +64 -11
  19. package/src/components/ConsoleShell.vmz +249 -69
  20. package/src/components/Content.vmz +15 -1
  21. package/src/components/DataTable.vmz +123 -23
  22. package/src/components/DatePicker.vmz +171 -79
  23. package/src/components/Descriptions.vmz +90 -0
  24. package/src/components/Dialog.vmz +133 -50
  25. package/src/components/Divider.vmz +8 -1
  26. package/src/components/Drawer.vmz +131 -40
  27. package/src/components/Dropdown.vmz +147 -49
  28. package/src/components/Empty.vmz +56 -14
  29. package/src/components/Field.vmz +78 -23
  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 +2 -3
  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 +20 -9
  39. package/src/components/List.vmz +35 -13
  40. package/src/components/Menu.vmz +198 -25
  41. package/src/components/Message.vmz +167 -0
  42. package/src/components/Notification.vmz +132 -37
  43. package/src/components/Pagination.vmz +186 -20
  44. package/src/components/Popconfirm.vmz +287 -0
  45. package/src/components/Popover.vmz +152 -34
  46. package/src/components/Progress.vmz +16 -5
  47. package/src/components/Prose.vmz +131 -32
  48. package/src/components/QueryForm.vmz +31 -9
  49. package/src/components/RadioGroup.vmz +91 -11
  50. package/src/components/Result.vmz +60 -27
  51. package/src/components/Segmented.vmz +46 -11
  52. package/src/components/Select.vmz +174 -87
  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 +40 -25
  58. package/src/components/Switch.vmz +48 -15
  59. package/src/components/Table.vmz +130 -25
  60. package/src/components/Tabs.vmz +28 -13
  61. package/src/components/Tag.vmz +29 -12
  62. package/src/components/TextArea.vmz +32 -25
  63. package/src/components/Timeline.vmz +65 -30
  64. package/src/components/Toc.vmz +45 -29
  65. package/src/components/Tooltip.vmz +70 -21
  66. package/src/components/Tree.vmz +48 -25
  67. package/src/components/Typography.vmz +23 -8
  68. package/src/components/Upload.vmz +191 -96
@@ -1,11 +1,14 @@
1
1
  <template>
2
- <fieldset data-vmz-ui="radio-group" :data-invalid="invalidAttr" :aria-describedby="describedBy" :disabled="disabled" class="vmz-ui-radio-group">
2
+ <fieldset data-vmz-ui="radio-group" :data-invalid="invalidAttr" :data-disabled="disabled ? 'true' : 'false'" :aria-describedby="describedBy" :disabled="disabled" class="vmz-ui-radio-group">
3
3
  <legend class="vmz-ui-radio-group__legend">
4
4
  {{ label }}
5
5
  </legend>
6
6
  <div role="radiogroup" :aria-label="label" @click="onListClick" class="vmz-ui-radio-group__list">
7
7
  <label v-for="item in items" :key="item.value" :for="item.id" class="vmz-ui-radio-group__option">
8
- <input :id="item.id" type="radio" :name="name" :value="item.value" :checked="value === item.value" :disabled="disabled" :data-vmz-radio="item.value" class="vmz-ui-radio-group__input" />
8
+ <span class="vmz-ui-radio-group__box">
9
+ <input :id="item.id" type="radio" :name="name" :value="item.value" :checked="value === item.value" :disabled="disabled" :data-vmz-radio="item.value" class="vmz-ui-radio-group__input" />
10
+ <span aria-hidden="true" class="vmz-ui-radio-group__dot" />
11
+ </span>
9
12
  <span class="vmz-ui-radio-group__text">
10
13
  {{ item.label }}
11
14
  </span>
@@ -23,7 +26,8 @@
23
26
  .vmz-ui-radio-group {
24
27
  display: flex;
25
28
  flex-direction: column;
26
- gap: 0.5rem;
29
+ gap: var(--vmz-space-2);
30
+ width: 100%;
27
31
  max-width: 28rem;
28
32
  margin: 0;
29
33
  padding: 0;
@@ -34,28 +38,69 @@
34
38
  .vmz-ui-radio-group__legend {
35
39
  padding: 0;
36
40
  font: inherit;
37
- font-weight: 600;
41
+ font-weight: 500;
42
+ font-size: 0.875rem;
43
+ line-height: 1.5715;
44
+ color: var(--vmz-text-ink);
38
45
  }
39
46
 
40
47
  .vmz-ui-radio-group__list {
41
48
  display: flex;
42
49
  flex-direction: column;
43
- gap: 0.375rem;
50
+ gap: var(--vmz-space-2);
44
51
  }
45
52
 
46
53
  .vmz-ui-radio-group__option {
47
54
  display: inline-flex;
48
55
  align-items: center;
49
- gap: 0.5rem;
56
+ gap: var(--vmz-space-2);
50
57
  font: inherit;
58
+ font-size: 0.875rem;
59
+ line-height: 1.5715;
60
+ color: var(--vmz-text-ink);
51
61
  cursor: pointer;
52
62
  }
53
63
 
64
+ .vmz-ui-radio-group__box {
65
+ position: relative;
66
+ display: inline-flex;
67
+ flex: 0 0 auto;
68
+ width: 1rem;
69
+ height: 1rem;
70
+ }
71
+
54
72
  .vmz-ui-radio-group__input {
73
+ position: absolute;
74
+ inset: 0;
75
+ z-index: 1;
76
+ box-sizing: border-box;
55
77
  width: 1rem;
56
78
  height: 1rem;
57
- accent-color: var(--vmz-action-primary-background);
79
+ margin: 0;
80
+ appearance: none;
81
+ border: 1px solid var(--vmz-line-default);
82
+ border-radius: var(--vmz-radius-pill);
83
+ background: var(--vmz-surface-paper);
58
84
  outline: none;
85
+ cursor: pointer;
86
+ transition:
87
+ background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
88
+ border-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
89
+ box-shadow var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
90
+ }
91
+
92
+ .vmz-ui-radio-group__input:hover:not(:disabled):not(:checked) {
93
+ border-color: var(--vmz-action-primary-hover);
94
+ }
95
+
96
+ .vmz-ui-radio-group__input:checked {
97
+ border-color: var(--vmz-action-primary-background);
98
+ background: var(--vmz-action-primary-background);
99
+ }
100
+
101
+ .vmz-ui-radio-group__input:checked:hover:not(:disabled) {
102
+ border-color: var(--vmz-action-primary-hover);
103
+ background: var(--vmz-action-primary-hover);
59
104
  }
60
105
 
61
106
  .vmz-ui-radio-group__input:focus-visible {
@@ -63,29 +108,64 @@
63
108
  }
64
109
 
65
110
  .vmz-ui-radio-group__input:disabled {
111
+ cursor: not-allowed;
112
+ }
113
+
114
+ .vmz-ui-radio-group__dot {
115
+ position: absolute;
116
+ inset: 0;
117
+ z-index: 2;
118
+ width: 0.375rem;
119
+ height: 0.375rem;
120
+ margin: auto;
121
+ border-radius: var(--vmz-radius-pill);
122
+ background: var(--vmz-action-primary-foreground);
123
+ opacity: 0;
124
+ pointer-events: none;
125
+ transition: opacity var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
126
+ }
127
+
128
+ .vmz-ui-radio-group__input:checked + .vmz-ui-radio-group__dot {
129
+ opacity: 1;
130
+ }
131
+
132
+ .vmz-ui-radio-group[data-disabled="true"] {
66
133
  opacity: 0.55;
134
+ }
135
+
136
+ .vmz-ui-radio-group[data-disabled="true"] .vmz-ui-radio-group__option,
137
+ .vmz-ui-radio-group[data-disabled="true"] .vmz-ui-radio-group__input {
67
138
  cursor: not-allowed;
68
139
  }
69
140
 
70
141
  .vmz-ui-radio-group__text {
71
- font-weight: 600;
142
+ font-weight: 400;
72
143
  }
73
144
 
74
145
  .vmz-ui-radio-group__description {
75
146
  margin: 0;
76
- opacity: 0.75;
77
- font-size: 0.9em;
147
+ color: var(--vmz-text-steel);
148
+ font-size: 0.875rem;
149
+ line-height: 1.5715;
78
150
  }
79
151
 
80
152
  .vmz-ui-radio-group__error {
81
153
  margin: 0;
82
154
  color: var(--vmz-status-danger-foreground);
83
- font-size: 0.9em;
155
+ font-size: 0.875rem;
156
+ line-height: 1.5715;
84
157
  }
85
158
 
86
159
  .vmz-ui-radio-group[data-invalid="true"] .vmz-ui-radio-group__legend {
87
160
  color: var(--vmz-status-danger-foreground);
88
161
  }
162
+
163
+ @media (prefers-reduced-motion: reduce) {
164
+ .vmz-ui-radio-group__input,
165
+ .vmz-ui-radio-group__dot {
166
+ transition: none;
167
+ }
168
+ }
89
169
  </style>
90
170
  <script client>
91
171
  /**
@@ -1,6 +1,9 @@
1
1
  <template>
2
2
  <section data-vmz-ui="result" :data-status="status" class="vmz-ui-result">
3
- <p class="vmz-ui-result__title">
3
+ <span aria-hidden="true" class="vmz-ui-result__icon">
4
+ <Icon :name="statusIcon()" size="lg" decorative />
5
+ </span>
6
+ <p v-if="title" class="vmz-ui-result__title">
4
7
  {{ title }}
5
8
  </p>
6
9
  <p v-if="description" class="vmz-ui-result__description">
@@ -15,68 +18,98 @@
15
18
  .vmz-ui-result {
16
19
  display: flex;
17
20
  flex-direction: column;
18
- align-items: flex-start;
19
- gap: var(--vmz-density-control-gap);
20
- padding: calc(var(--vmz-density-control-padding-y) * 1.5) var(--vmz-density-control-padding-x);
21
- border: 1px solid var(--vmz-status-info-accent);
22
- border-radius: var(--vmz-radius-md, 6px);
23
- color: var(--vmz-status-info-foreground);
21
+ align-items: center;
22
+ gap: var(--vmz-space-2, 0.5rem);
23
+ padding: var(--vmz-space-6, 2rem) var(--vmz-space-5, 1.5rem);
24
+ border: 1px solid var(--vmz-line-default, var(--vmz-line-strong));
25
+ border-radius: var(--vmz-radius-lg, 8px);
26
+ background: var(--vmz-surface-paper);
27
+ color: var(--vmz-text-ink);
28
+ text-align: center;
24
29
  }
25
30
 
26
- .vmz-ui-result[data-status="info"] {
27
- border-color: var(--vmz-status-info-accent);
28
- color: var(--vmz-status-info-foreground);
31
+ .vmz-ui-result__icon {
32
+ display: inline-flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ margin-bottom: var(--vmz-space-1, 0.25rem);
29
36
  }
30
37
 
31
- .vmz-ui-result[data-status="success"] {
32
- border-color: var(--vmz-status-success-accent);
33
- color: var(--vmz-status-success-foreground);
38
+ .vmz-ui-result__icon .vmz-ui-icon[data-size] {
39
+ font-size: 2.5rem;
34
40
  }
35
41
 
36
- .vmz-ui-result[data-status="warning"] {
37
- border-color: var(--vmz-status-warning-accent);
38
- color: var(--vmz-status-warning-foreground);
42
+ .vmz-ui-result[data-status="info"] .vmz-ui-result__icon {
43
+ color: var(--vmz-status-info-accent);
39
44
  }
40
45
 
41
- .vmz-ui-result[data-status="danger"] {
42
- border-color: var(--vmz-status-danger-accent);
43
- color: var(--vmz-status-danger-foreground);
46
+ .vmz-ui-result[data-status="success"] .vmz-ui-result__icon {
47
+ color: var(--vmz-status-success-accent);
44
48
  }
45
49
 
46
- :where([data-density="compact"]) .vmz-ui-result {
47
- gap: var(--vmz-density-compact-gap);
48
- padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
50
+ .vmz-ui-result[data-status="warning"] .vmz-ui-result__icon {
51
+ color: var(--vmz-status-warning-accent);
52
+ }
53
+
54
+ .vmz-ui-result[data-status="danger"] .vmz-ui-result__icon,
55
+ .vmz-ui-result[data-status="error"] .vmz-ui-result__icon {
56
+ color: var(--vmz-status-danger-accent);
49
57
  }
50
58
 
51
59
  .vmz-ui-result__title {
52
60
  margin: 0;
53
- font-size: 1.15rem;
54
- font-weight: 700;
61
+ font-family: var(--vmz-font-sans, inherit);
62
+ font-size: 1.5rem;
63
+ font-weight: 600;
64
+ line-height: 1.32;
65
+ color: var(--vmz-text-ink);
55
66
  }
56
67
 
57
68
  .vmz-ui-result__description {
58
69
  margin: 0;
59
- opacity: 0.9;
70
+ max-width: 40rem;
71
+ font-size: 0.9375rem;
72
+ line-height: 1.55;
73
+ color: var(--vmz-text-tertiary);
60
74
  }
61
75
 
62
76
  .vmz-ui-result__actions {
63
77
  display: flex;
64
78
  flex-wrap: wrap;
65
- gap: 0.5rem;
79
+ justify-content: center;
80
+ gap: var(--vmz-space-3, 0.75rem);
81
+ margin-top: var(--vmz-space-2, 0.5rem);
66
82
  }
67
83
 
68
84
  .vmz-ui-result__actions:empty {
69
85
  display: none;
70
86
  }
87
+
88
+ :where([data-density="compact"]) .vmz-ui-result {
89
+ gap: var(--vmz-space-1, 0.25rem);
90
+ padding: var(--vmz-space-5, 1.5rem) var(--vmz-space-4, 1rem);
91
+ }
92
+
93
+ :where([data-density="dense"]) .vmz-ui-result {
94
+ gap: var(--vmz-space-1, 0.25rem);
95
+ padding: var(--vmz-space-4, 1rem);
96
+ }
71
97
  </style>
72
98
  <script client>
73
99
  /**
74
100
  * VMZ UI — Result (UI4 Commercial Surface).
75
- * Outcome block for success/error flows; status → status.* tokens.
101
+ * Outcome block for success/error flows; status → status.* accent tokens.
76
102
  */
77
103
  export default class Result {
78
104
  public title: string = "";
79
105
  public description: string = "";
80
106
  public status: string = "info";
107
+
108
+ statusIcon() {
109
+ const status = String(this.status || "").toLowerCase();
110
+ if (status === "success" || status === "warning") return `status.${status}`;
111
+ if (status === "danger" || status === "error") return "status.danger";
112
+ return "status.info";
113
+ }
81
114
  }
82
115
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div data-vmz-ui="segmented" role="group" :aria-label="label" class="vmz-ui-segmented">
2
+ <div data-vmz-ui="segmented" role="group" :aria-label="label" :data-size="size" class="vmz-ui-segmented">
3
3
  <button v-for="opt in options" :key="opt.value" type="button" :data-vmz-segment="opt.value" :aria-pressed="opt.value === value ? 'true' : 'false'" @click="(() => onPick(opt.value))">
4
4
  {{ opt.label }}
5
5
  </button>
@@ -9,38 +9,73 @@
9
9
  .vmz-ui-segmented {
10
10
  display: inline-flex;
11
11
  max-width: 100%;
12
- padding: 0.2rem;
13
- border-radius: var(--vmz-radius-md, 6px);
12
+ padding: var(--vmz-space-1);
13
+ border-radius: var(--vmz-radius-lg);
14
14
  background: var(--vmz-surface-mist);
15
15
  overflow-x: auto;
16
16
  }
17
+
17
18
  .vmz-ui-segmented button {
18
- min-height: 2rem;
19
- padding: 0.25rem 0.75rem;
19
+ box-sizing: border-box;
20
+ min-height: var(--vmz-control-height);
21
+ padding: 0 var(--vmz-space-3);
20
22
  border: 0;
21
- border-radius: calc(var(--vmz-radius-md, 6px) - 2px);
23
+ border-radius: var(--vmz-radius-md);
22
24
  background: transparent;
23
25
  color: var(--vmz-text-steel);
24
26
  font: inherit;
25
27
  font-size: 0.875rem;
26
- font-weight: 550;
28
+ font-weight: 500;
29
+ line-height: 1.5715;
27
30
  white-space: nowrap;
28
31
  cursor: pointer;
32
+ outline: none;
33
+ transition:
34
+ background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
35
+ color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
36
+ box-shadow var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
29
37
  }
38
+
39
+ .vmz-ui-segmented[data-size="small"] button {
40
+ min-height: var(--vmz-control-height-sm);
41
+ padding: 0 var(--vmz-space-2);
42
+ }
43
+
44
+ .vmz-ui-segmented[data-size="large"] button {
45
+ min-height: var(--vmz-control-height-lg);
46
+ padding: 0 var(--vmz-space-4);
47
+ }
48
+
49
+ .vmz-ui-segmented button:hover:not([aria-pressed="true"]) {
50
+ color: var(--vmz-text-ink);
51
+ background: var(--vmz-surface-fill);
52
+ }
53
+
30
54
  .vmz-ui-segmented button[aria-pressed="true"] {
31
55
  background: var(--vmz-surface-paper);
32
56
  color: var(--vmz-text-ink);
33
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
57
+ box-shadow: 0 0 0 1px var(--vmz-line-default);
34
58
  }
59
+
60
+ .vmz-ui-segmented button[aria-pressed="true"]:hover {
61
+ color: var(--vmz-text-ink);
62
+ }
63
+
35
64
  .vmz-ui-segmented button:focus-visible {
36
- outline: 2px solid var(--vmz-focus-ring);
37
- outline-offset: -2px;
65
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
66
+ }
67
+
68
+ @media (prefers-reduced-motion: reduce) {
69
+ .vmz-ui-segmented button {
70
+ transition: none;
71
+ }
38
72
  }
39
73
  </style>
40
74
  <script client>
41
75
  export default class Segmented {
42
- public label: string = "Segments";
76
+ public label: string = "";
43
77
  public value: string = "";
78
+ public size: string = "middle";
44
79
  public options: Array<{ value: string; label: string }> = [];
45
80
  public onChange: ((value: string) => void) | null = null;
46
81
  onPick(next: string) {