@vmz/ui 0.2.3 → 0.2.4

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 (63) hide show
  1. package/package.json +1 -1
  2. package/src/components/Accordion.vmz +46 -63
  3. package/src/components/Alert.vmz +35 -38
  4. package/src/components/AppShell.vmz +92 -75
  5. package/src/components/Autocomplete.vmz +91 -119
  6. package/src/components/Avatar.vmz +37 -8
  7. package/src/components/Badge.vmz +29 -23
  8. package/src/components/Breadcrumb.vmz +36 -34
  9. package/src/components/BulkActions.vmz +22 -28
  10. package/src/components/Button.vmz +139 -121
  11. package/src/components/Callout.vmz +33 -36
  12. package/src/components/Card.vmz +68 -51
  13. package/src/components/Checkbox.vmz +28 -47
  14. package/src/components/CodeBlock.vmz +31 -25
  15. package/src/components/Collapse.vmz +34 -16
  16. package/src/components/ConsoleShell.vmz +107 -110
  17. package/src/components/Content.vmz +8 -4
  18. package/src/components/DataTable.vmz +124 -150
  19. package/src/components/DatePicker.vmz +526 -521
  20. package/src/components/Dialog.vmz +408 -327
  21. package/src/components/Divider.vmz +38 -11
  22. package/src/components/Drawer.vmz +325 -318
  23. package/src/components/Dropdown.vmz +53 -19
  24. package/src/components/Empty.vmz +23 -21
  25. package/src/components/Field.vmz +77 -83
  26. package/src/components/FilterBar.vmz +8 -10
  27. package/src/components/Flex.vmz +21 -6
  28. package/src/components/Footer.vmz +9 -4
  29. package/src/components/Form.vmz +35 -46
  30. package/src/components/FormItem.vmz +44 -43
  31. package/src/components/Grid.vmz +22 -6
  32. package/src/components/Header.vmz +11 -4
  33. package/src/components/Icon.vmz +43 -44
  34. package/src/components/Layout.vmz +9 -4
  35. package/src/components/Link.vmz +17 -25
  36. package/src/components/List.vmz +62 -75
  37. package/src/components/Menu.vmz +182 -197
  38. package/src/components/Notification.vmz +35 -38
  39. package/src/components/Pagination.vmz +37 -47
  40. package/src/components/Popover.vmz +157 -171
  41. package/src/components/Progress.vmz +36 -10
  42. package/src/components/Prose.vmz +29 -31
  43. package/src/components/QueryForm.vmz +14 -22
  44. package/src/components/RadioGroup.vmz +70 -84
  45. package/src/components/Result.vmz +36 -38
  46. package/src/components/Segmented.vmz +43 -22
  47. package/src/components/Select.vmz +404 -411
  48. package/src/components/Sider.vmz +21 -4
  49. package/src/components/Skeleton.vmz +34 -42
  50. package/src/components/Space.vmz +24 -9
  51. package/src/components/Spinner.vmz +17 -23
  52. package/src/components/Steps.vmz +48 -51
  53. package/src/components/Switch.vmz +50 -60
  54. package/src/components/Table.vmz +81 -84
  55. package/src/components/Tabs.vmz +66 -88
  56. package/src/components/Tag.vmz +36 -11
  57. package/src/components/TextArea.vmz +73 -77
  58. package/src/components/Timeline.vmz +36 -32
  59. package/src/components/Toc.vmz +31 -37
  60. package/src/components/Tooltip.vmz +25 -35
  61. package/src/components/Tree.vmz +127 -144
  62. package/src/components/Typography.vmz +33 -7
  63. package/src/components/Upload.vmz +1135 -1057
@@ -1,174 +1,192 @@
1
1
  <template>
2
- <a
3
- v-if="href"
4
- class="vmz-ui-btn"
5
- data-vmz-ui="button"
6
- data-vmz-motion="control"
7
- data-vmz-motion-token="motion.control"
8
- :data-variant="variant"
9
- :data-size="size"
10
- :data-block="block ? 'true' : 'false'"
11
- :href="href"
12
- :target="target"
13
- :rel="rel"
14
- @click="onDomClick"
15
- >
16
- <span v-if="loading" class="vmz-ui-btn__spinner" aria-hidden="true"></span>
17
- <slot />
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 />
18
5
  </a>
19
- <button
20
- v-else
21
- :type="type"
22
- class="vmz-ui-btn"
23
- data-vmz-ui="button"
24
- data-vmz-motion="control"
25
- data-vmz-motion-token="motion.control"
26
- :data-variant="variant"
27
- :data-size="size"
28
- :data-block="block ? 'true' : 'false'"
29
- :data-loading="loading ? 'true' : 'false'"
30
- :disabled="disabled"
31
- :aria-busy="loading ? 'true' : 'false'"
32
- @click="onDomClick"
33
- >
34
- <span v-if="loading" class="vmz-ui-btn__spinner" aria-hidden="true"></span>
35
- <slot />
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 />
36
9
  </button>
37
10
  </template>
38
-
39
11
  <style>
40
12
  .vmz-ui-btn {
41
- display: inline-flex;
42
- align-items: center;
43
- justify-content: center;
44
- gap: 0.35rem;
45
- min-height: var(--vmz-control-height, 2rem);
46
- padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
47
- border: 1px solid transparent;
48
- border-radius: var(--vmz-radius-md, 6px);
49
- font: inherit;
50
- font-size: 0.875rem;
51
- font-weight: 400;
52
- line-height: 1.5715;
53
- cursor: pointer;
54
- background: var(--vmz-action-primary-background);
55
- color: var(--vmz-action-primary-foreground);
56
- outline: none;
57
- box-shadow: none;
58
- transition:
59
- background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
60
- border-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
61
- color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
62
- }
63
-
64
- .vmz-ui-btn[data-size='small'] { min-height: var(--vmz-control-height-sm, 1.5rem); padding: 0 0.5rem; font-size: 0.875rem; }
65
- .vmz-ui-btn[data-size='large'] { min-height: var(--vmz-control-height-lg, 2.5rem); padding: 0.4rem 1rem; font-size: 1rem; }
66
- .vmz-ui-btn[data-block='true'] { width: 100%; }
67
- .vmz-ui-btn[data-loading='true'] { cursor: wait; }
68
- .vmz-ui-btn__spinner { width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: vmz-btn-spin .7s linear infinite; }
69
- @keyframes vmz-btn-spin { to { transform: rotate(360deg); } }
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ gap: 0.35rem;
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: 400;
24
+ line-height: 1.5715;
25
+ cursor: pointer;
26
+ background: var(--vmz-action-primary-background);
27
+ color: var(--vmz-action-primary-foreground);
28
+ outline: none;
29
+ box-shadow: none;
30
+ transition:
31
+ background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
32
+ border-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
33
+ color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
34
+ }
35
+
36
+ .vmz-ui-btn[data-size="small"] {
37
+ min-height: var(--vmz-control-height-sm, 1.5rem);
38
+ padding: 0 0.5rem;
39
+ font-size: 0.875rem;
40
+ }
41
+ .vmz-ui-btn[data-size="large"] {
42
+ min-height: var(--vmz-control-height-lg, 2.5rem);
43
+ padding: 0.4rem 1rem;
44
+ font-size: 1rem;
45
+ }
46
+ .vmz-ui-btn[data-block="true"] {
47
+ width: 100%;
48
+ }
49
+ .vmz-ui-btn[data-loading="true"] {
50
+ cursor: wait;
51
+ }
52
+ .vmz-ui-btn__spinner {
53
+ width: 1em;
54
+ height: 1em;
55
+ border: 2px solid currentColor;
56
+ border-right-color: transparent;
57
+ border-radius: 50%;
58
+ animation: vmz-btn-spin 0.7s linear infinite;
59
+ }
60
+ @keyframes vmz-btn-spin {
61
+ to {
62
+ transform: rotate(360deg);
63
+ }
64
+ }
70
65
 
71
66
  .vmz-ui-btn:hover:not(:disabled) {
72
- background: var(--vmz-action-primary-hover);
67
+ background: var(--vmz-action-primary-hover);
73
68
  }
74
69
 
75
70
  .vmz-ui-btn:active:not(:disabled) {
76
- background: var(--vmz-action-primary-active);
71
+ background: var(--vmz-action-primary-active);
77
72
  }
78
73
 
79
- .vmz-ui-btn[data-variant='secondary'] {
80
- background: var(--vmz-action-secondary-background);
81
- color: var(--vmz-action-secondary-foreground);
82
- border-color: var(--vmz-action-secondary-border);
74
+ .vmz-ui-btn[data-variant="secondary"] {
75
+ background: var(--vmz-action-secondary-background);
76
+ color: var(--vmz-action-secondary-foreground);
77
+ border-color: var(--vmz-action-secondary-border);
78
+ }
79
+ .vmz-ui-btn[data-variant="default"] {
80
+ background: #fff;
81
+ color: var(--vmz-text-ink);
82
+ border-color: var(--vmz-line-default);
83
+ box-shadow: none;
84
+ }
85
+ .vmz-ui-btn[data-variant="default"]:hover:not(:disabled) {
86
+ color: var(--vmz-action-primary-background);
87
+ border-color: var(--vmz-action-primary-background);
88
+ background: #fff;
89
+ }
90
+ .vmz-ui-btn[data-variant="text"],
91
+ .vmz-ui-btn[data-variant="link"] {
92
+ min-height: auto;
93
+ padding: 0.25rem 0.35rem;
94
+ border-color: transparent;
95
+ background: transparent;
96
+ color: var(--vmz-action-primary-background);
97
+ box-shadow: none;
98
+ }
99
+ .vmz-ui-btn[data-variant="dashed"] {
100
+ background: #fff;
101
+ color: var(--vmz-text-ink);
102
+ border: 1px dashed var(--vmz-line-default);
103
+ box-shadow: none;
83
104
  }
84
- .vmz-ui-btn[data-variant='default'] { background:#fff; color:var(--vmz-text-ink); border-color:var(--vmz-line-default); box-shadow:none; }
85
- .vmz-ui-btn[data-variant='default']:hover:not(:disabled) { color:var(--vmz-action-primary-background); border-color:var(--vmz-action-primary-background); background:#fff; }
86
- .vmz-ui-btn[data-variant='text'], .vmz-ui-btn[data-variant='link'] { min-height:auto; padding:.25rem .35rem; border-color:transparent; background:transparent; color:var(--vmz-action-primary-background); box-shadow:none; }
87
- .vmz-ui-btn[data-variant='dashed'] { background:#fff; color:var(--vmz-text-ink); border:1px dashed var(--vmz-line-default); box-shadow:none; }
88
105
 
89
- .vmz-ui-btn[data-variant='secondary']:hover:not(:disabled) {
106
+ .vmz-ui-btn[data-variant="secondary"]:hover:not(:disabled) {
90
107
  background: var(--vmz-action-secondary-hover);
91
- }
108
+ }
92
109
 
93
- .vmz-ui-btn[data-variant='secondary']:active:not(:disabled) {
110
+ .vmz-ui-btn[data-variant="secondary"]:active:not(:disabled) {
94
111
  background: var(--vmz-action-secondary-hover);
95
112
  border-color: var(--vmz-action-primary-active);
96
- }
113
+ }
97
114
 
98
- .vmz-ui-btn[data-variant='ghost'] {
115
+ .vmz-ui-btn[data-variant="ghost"] {
99
116
  background: transparent;
100
117
  color: var(--vmz-text-ink);
101
118
  border-color: transparent;
102
- }
119
+ }
103
120
 
104
- .vmz-ui-btn[data-variant='ghost']:hover:not(:disabled) {
121
+ .vmz-ui-btn[data-variant="ghost"]:hover:not(:disabled) {
105
122
  background: color-mix(in srgb, var(--vmz-surface-mist) 85%, transparent);
106
- }
123
+ }
107
124
 
108
- .vmz-ui-btn[data-variant='ghost']:active:not(:disabled) {
125
+ .vmz-ui-btn[data-variant="ghost"]:active:not(:disabled) {
109
126
  background: var(--vmz-surface-mist);
110
- }
127
+ }
111
128
 
112
- .vmz-ui-btn[data-variant='danger'] {
129
+ .vmz-ui-btn[data-variant="danger"] {
113
130
  background: var(--vmz-status-danger-accent);
114
131
  color: var(--vmz-action-primary-foreground);
115
132
  border-color: transparent;
116
- }
133
+ }
117
134
 
118
- .vmz-ui-btn[data-variant='danger']:hover:not(:disabled) {
135
+ .vmz-ui-btn[data-variant="danger"]:hover:not(:disabled) {
119
136
  background: color-mix(in srgb, var(--vmz-status-danger-accent) 82%, var(--vmz-text-ink));
120
- }
137
+ }
121
138
 
122
- .vmz-ui-btn[data-variant='danger']:active:not(:disabled) {
139
+ .vmz-ui-btn[data-variant="danger"]:active:not(:disabled) {
123
140
  background: var(--vmz-status-danger-foreground);
124
- }
141
+ }
125
142
 
126
- .vmz-ui-btn:focus-visible {
143
+ .vmz-ui-btn:focus-visible {
127
144
  box-shadow: 0 0 0 2px var(--vmz-focus-ring);
128
- }
145
+ }
129
146
 
130
- .vmz-ui-btn:disabled {
147
+ .vmz-ui-btn:disabled {
131
148
  opacity: 0.55;
132
149
  cursor: not-allowed;
133
- }
150
+ }
134
151
 
135
- :where([data-density='compact']) .vmz-ui-btn {
152
+ :where([data-density="compact"]) .vmz-ui-btn {
136
153
  padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
137
- }
154
+ }
138
155
 
139
- :where([data-density='dense']) .vmz-ui-btn {
156
+ :where([data-density="dense"]) .vmz-ui-btn {
140
157
  padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
141
- }
158
+ }
142
159
 
143
- @media (prefers-reduced-motion: reduce) {
160
+ @media (prefers-reduced-motion: reduce) {
144
161
  .vmz-ui-btn {
145
- transition: none;
162
+ transition: none;
146
163
  }
147
- }
164
+ }
148
165
  </style>
149
-
150
166
  <script client>
151
167
  /**
152
- * VMZ UI — Button (variants + motion control feedback).
153
- * Colors / motion come only from Style Theme semantic tokens — never brand hex.
154
- * Variants: primary | secondary | ghost | danger
155
- */
168
+ * VMZ UI — Button (variants + motion control feedback).
169
+ * Colors / motion come only from Style Theme semantic tokens — never brand hex.
170
+ * Variants: primary | secondary | ghost | danger
171
+ */
156
172
  export default class Button {
157
- /** @type {'contents'} Direct host: no layout box (`ui-direct-host-box`). */
158
- static __vmzHostBox = 'contents';
159
- public type: string = "button";
160
- public variant: string = "primary";
161
- public disabled: boolean = false;
162
- public loading: boolean = false;
163
- public block: boolean = false;
164
- public size: string = "middle";
165
- public href: string = "";
166
- public target: string = "";
167
- public rel: string = "";
168
- public onClick: ((e: Event) => void) | null = null;
169
- onDomClick(e: Event) {
170
- this.emit("click", e);
171
- if (typeof this.onClick === "function") this.onClick(e);
172
- }
173
+ /** @type {'contents'} Direct host: no layout box (`ui-direct-host-box`). */
174
+ static __vmzHostBox = "contents";
175
+ public type: string = "button";
176
+ public variant: string = "primary";
177
+ public disabled: boolean = false;
178
+ public loading: boolean = false;
179
+ public block: boolean = false;
180
+ public size: string = "middle";
181
+ public href: string = "";
182
+ public target: string = "";
183
+ public rel: string = "";
184
+ public ariaHaspopup: string = "";
185
+ public ariaControls: string = "";
186
+ public onClick: ((e: Event) => void) | null = null;
187
+ onDomClick(e: Event) {
188
+ this.emit("click", e);
189
+ if (typeof this.onClick === "function") this.onClick(e);
190
+ }
173
191
  }
174
192
  </script>
@@ -1,20 +1,18 @@
1
1
  <template>
2
- <aside
3
- class="vmz-ui-callout"
4
- data-vmz-ui="callout"
5
- :data-tone="tone"
6
- :role="roleName"
7
- >
8
- <p v-if="title" class="vmz-ui-callout__title">{{ title }}</p>
9
- <p v-if="description" class="vmz-ui-callout__description">{{ description }}</p>
10
- <div class="vmz-ui-callout__body">
11
- <slot />
12
- </div>
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>
13
12
  </aside>
14
13
  </template>
15
-
16
14
  <style>
17
- .vmz-ui-callout {
15
+ .vmz-ui-callout {
18
16
  display: flex;
19
17
  flex-direction: column;
20
18
  gap: 0.45rem;
@@ -24,57 +22,56 @@
24
22
  border-radius: var(--vmz-radius-md, 6px);
25
23
  background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
26
24
  color: var(--vmz-status-info-foreground);
27
- }
25
+ }
28
26
 
29
- .vmz-ui-callout[data-tone='info'] {
27
+ .vmz-ui-callout[data-tone="info"] {
30
28
  border-color: var(--vmz-status-info-accent);
31
29
  background: color-mix(in srgb, var(--vmz-status-info-accent) 10%, var(--vmz-surface-paper));
32
30
  color: var(--vmz-status-info-foreground);
33
- }
31
+ }
34
32
 
35
- .vmz-ui-callout[data-tone='success'] {
33
+ .vmz-ui-callout[data-tone="success"] {
36
34
  border-color: var(--vmz-status-success-accent);
37
35
  background: color-mix(in srgb, var(--vmz-status-success-accent) 10%, var(--vmz-surface-paper));
38
36
  color: var(--vmz-status-success-foreground);
39
- }
37
+ }
40
38
 
41
- .vmz-ui-callout[data-tone='warning'] {
39
+ .vmz-ui-callout[data-tone="warning"] {
42
40
  border-color: var(--vmz-status-warning-accent);
43
41
  background: color-mix(in srgb, var(--vmz-status-warning-accent) 10%, var(--vmz-surface-paper));
44
42
  color: var(--vmz-status-warning-foreground);
45
- }
43
+ }
46
44
 
47
- .vmz-ui-callout[data-tone='danger'] {
45
+ .vmz-ui-callout[data-tone="danger"] {
48
46
  border-color: var(--vmz-status-danger-accent);
49
47
  background: color-mix(in srgb, var(--vmz-status-danger-accent) 10%, var(--vmz-surface-paper));
50
48
  color: var(--vmz-status-danger-foreground);
51
- }
49
+ }
52
50
 
53
- .vmz-ui-callout__title {
51
+ .vmz-ui-callout__title {
54
52
  margin: 0;
55
53
  font-family: var(--vmz-font-display);
56
54
  font-weight: 700;
57
- }
55
+ }
58
56
 
59
- .vmz-ui-callout__description {
57
+ .vmz-ui-callout__description {
60
58
  margin: 0;
61
59
  line-height: 1.5;
62
- }
60
+ }
63
61
 
64
- .vmz-ui-callout__body:empty {
62
+ .vmz-ui-callout__body:empty {
65
63
  display: none;
66
- }
64
+ }
67
65
  </style>
68
-
69
66
  <script client>
70
67
  /**
71
- * VMZ UI — Callout (Document/Product composition).
72
- * Inline guidance block for prose; shares status.* tones with Alert.
73
- */
68
+ * VMZ UI — Callout (Document/Product composition).
69
+ * Inline guidance block for prose; shares status.* tones with Alert.
70
+ */
74
71
  export default class Callout {
75
- public title: string = "";
76
- public description: string = "";
77
- public tone: string = "info";
78
- public roleName: string = "note";
72
+ public title: string = "";
73
+ public description: string = "";
74
+ public tone: string = "info";
75
+ public roleName: string = "note";
79
76
  }
80
77
  </script>
@@ -1,89 +1,106 @@
1
1
  <template>
2
- <section class="vmz-ui-card" data-vmz-ui="card" :data-size="size" :data-bordered="bordered ? 'true' : 'false'" :data-hoverable="hoverable ? 'true' : 'false'">
3
- <header v-if="title" class="vmz-ui-card__header">
4
- <h2 class="vmz-ui-card__title">{{ title }}</h2>
5
- <p v-if="description" class="vmz-ui-card__description">{{ description }}</p>
6
- </header>
7
- <div class="vmz-ui-card__body">
8
- <slot />
9
- </div>
2
+ <section data-vmz-ui="card" :data-size="size" :data-bordered='bordered ? "true" : "false"' :data-hoverable='hoverable ? "true" : "false"' class="vmz-ui-card">
3
+ <header v-if="title" class="vmz-ui-card__header">
4
+ <h2 class="vmz-ui-card__title">
5
+ {{ title }}
6
+ </h2>
7
+ <p v-if="description" class="vmz-ui-card__description">
8
+ {{ description }}
9
+ </p>
10
+ </header>
11
+ <div class="vmz-ui-card__body">
12
+ <slot />
13
+ </div>
10
14
  </section>
11
15
  </template>
12
-
13
16
  <style>
14
17
  .vmz-ui-card {
15
- display: flex;
16
- flex-direction: column;
17
- gap: 0.75rem;
18
- padding: 1rem 1.25rem;
19
- border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
20
- border-radius: var(--vmz-radius-lg, 8px);
21
- background: var(--vmz-surface-paper);
22
- color: var(--vmz-text-ink);
23
- box-shadow: var(--vmz-shadow-card, none);
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 0.75rem;
21
+ padding: 1rem 1.25rem;
22
+ border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
23
+ border-radius: var(--vmz-radius-lg, 8px);
24
+ background: var(--vmz-surface-paper);
25
+ color: var(--vmz-text-ink);
26
+ box-shadow: var(--vmz-shadow-card, none);
27
+ }
28
+ .vmz-ui-card[data-bordered="false"] {
29
+ border-color: transparent;
30
+ }
31
+ .vmz-ui-card[data-hoverable="true"] {
32
+ transition:
33
+ border-color var(--vmz-motion-control-duration, 0.16s),
34
+ box-shadow var(--vmz-motion-control-duration, 0.16s);
35
+ }
36
+ .vmz-ui-card[data-hoverable="true"]:hover {
37
+ box-shadow: var(
38
+ --vmz-shadow-card-hover,
39
+ 0 1px 2px -2px rgba(0, 0, 0, 0.08),
40
+ 0 3px 6px 0 rgba(0, 0, 0, 0.06)
41
+ );
42
+ }
43
+ .vmz-ui-card[data-size="small"] {
44
+ gap: 0.5rem;
45
+ padding: 0.75rem 1rem;
24
46
  }
25
- .vmz-ui-card[data-bordered='false'] { border-color: transparent; }
26
- .vmz-ui-card[data-hoverable='true'] { transition: border-color var(--vmz-motion-control-duration, .16s), box-shadow var(--vmz-motion-control-duration, .16s); }
27
- .vmz-ui-card[data-hoverable='true']:hover { box-shadow: var(--vmz-shadow-card-hover, 0 1px 2px -2px rgba(0,0,0,.08), 0 3px 6px 0 rgba(0,0,0,.06)); }
28
- .vmz-ui-card[data-size='small'] { gap: .5rem; padding: .75rem 1rem; }
29
47
 
30
- :where([data-density='compact']) .vmz-ui-card {
48
+ :where([data-density="compact"]) .vmz-ui-card {
31
49
  gap: var(--vmz-density-compact-gap);
32
50
  padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
33
- }
51
+ }
34
52
 
35
- :where([data-density='dense']) .vmz-ui-card {
53
+ :where([data-density="dense"]) .vmz-ui-card {
36
54
  gap: var(--vmz-density-dense-gap);
37
55
  padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
38
- }
56
+ }
39
57
 
40
- .vmz-ui-card__header {
58
+ .vmz-ui-card__header {
41
59
  display: flex;
42
60
  flex-direction: column;
43
61
  gap: 0.35rem;
44
- }
62
+ }
45
63
 
46
64
  .vmz-ui-card__title {
47
- margin: 0;
48
- font-family: var(--vmz-font-sans, inherit);
49
- font-size: 1rem;
50
- font-weight: 600;
51
- color: var(--vmz-text-ink);
65
+ margin: 0;
66
+ font-family: var(--vmz-font-sans, inherit);
67
+ font-size: 1rem;
68
+ font-weight: 600;
69
+ color: var(--vmz-text-ink);
52
70
  }
53
71
 
54
- .vmz-ui-card__description {
72
+ .vmz-ui-card__description {
55
73
  margin: 0;
56
74
  color: var(--vmz-text-steel);
57
75
  line-height: 1.45;
58
- }
76
+ }
59
77
 
60
- .vmz-ui-card__body {
78
+ .vmz-ui-card__body {
61
79
  display: flex;
62
80
  flex-direction: column;
63
81
  gap: var(--vmz-density-control-gap);
64
- }
82
+ }
65
83
 
66
- /* Direct host default is display:contents (runtime); Badge-only CSS special-case removed. */
84
+ /* Direct host default is display:contents (runtime); Badge-only CSS special-case removed. */
67
85
 
68
- :where([data-density='compact']) .vmz-ui-card__body {
86
+ :where([data-density="compact"]) .vmz-ui-card__body {
69
87
  gap: var(--vmz-density-compact-gap);
70
- }
88
+ }
71
89
 
72
- :where([data-density='dense']) .vmz-ui-card__body {
90
+ :where([data-density="dense"]) .vmz-ui-card__body {
73
91
  gap: var(--vmz-density-dense-gap);
74
- }
92
+ }
75
93
  </style>
76
-
77
94
  <script client>
78
95
  /**
79
- * VMZ UI — Card (Commercial Surface).
80
- * Surface container; spacing from density.*; chrome from surface/line/text.
81
- */
96
+ * VMZ UI — Card (Commercial Surface).
97
+ * Surface container; spacing from density.*; chrome from surface/line/text.
98
+ */
82
99
  export default class Card {
83
- public title: string = "";
84
- public description: string = "";
85
- public size: string = "middle";
86
- public bordered: boolean = true;
87
- public hoverable: boolean = false;
100
+ public title: string = "";
101
+ public description: string = "";
102
+ public size: string = "middle";
103
+ public bordered: boolean = true;
104
+ public hoverable: boolean = false;
88
105
  }
89
106
  </script>