@vanduo-oss/framework 1.6.0 → 1.7.0

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.
@@ -197,9 +197,11 @@ textarea.textarea-lg {
197
197
  border-radius: var(--vd-input-border-radius-lg);
198
198
  }
199
199
 
200
- /* Input States - Error */
200
+ /* Input States - Error (`.vd-input-danger` is the canonical alias, added 1.7.0) */
201
201
  .vd-input-error,
202
202
  input.vd-input-error,
203
+ .vd-input-danger,
204
+ input.vd-input-danger,
203
205
  .vd-input.is-error,
204
206
  input.is-error {
205
207
  border-color: var(--vd-color-error);
@@ -212,6 +214,8 @@ input.vd-input-invalid {
212
214
 
213
215
  .vd-input-error:focus,
214
216
  input.vd-input-error:focus,
217
+ .vd-input-danger:focus,
218
+ input.vd-input-danger:focus,
215
219
  .vd-input.is-error:focus,
216
220
  input.is-error:focus {
217
221
  border-color: var(--vd-color-error);
@@ -283,6 +287,7 @@ textarea.is-success:focus {
283
287
 
284
288
  /* Labels */
285
289
  .label,
290
+ .vd-form-label,
286
291
  label {
287
292
  display: inline-block;
288
293
  margin-bottom: 0.5rem;
@@ -298,6 +303,12 @@ label.required::after {
298
303
  color: var(--vd-color-error);
299
304
  }
300
305
 
306
+ /* Icon inside a radio/check label (added 1.7.0; used by @vanduo-oss/vue) */
307
+ .vd-form-radio-icon {
308
+ margin-right: 0.375rem;
309
+ vertical-align: -0.125em;
310
+ }
311
+
301
312
  .label-sm,
302
313
  label.label-sm {
303
314
  font-size: var(--vd-font-size-xs);
@@ -300,3 +300,72 @@
300
300
  overflow: hidden;
301
301
  padding-right: 0;
302
302
  }
303
+
304
+ /* ==========================================================================
305
+ @vanduo-oss/vue panel-based modal markup (additive; added in 1.6.1)
306
+ VdModal renders `.vd-modal.vd-modal-open > .vd-modal-backdrop +
307
+ .vd-modal-panel.vd-modal-panel-{sm|md|lg}` with header/body/footer directly
308
+ inside the panel (no .vd-modal-dialog / .vd-modal-content split, and the
309
+ backdrop carries no .is-visible state). These aliases style that DOM without
310
+ touching the legacy .is-open / .vd-modal-dialog / .vd-modal-content rules.
311
+ ========================================================================== */
312
+
313
+ /* Container open state (mirror of .vd-modal.is-open) */
314
+ .vd-modal.vd-modal-open {
315
+ display: flex;
316
+ align-items: center;
317
+ justify-content: center;
318
+ opacity: 1;
319
+ }
320
+
321
+ /* Backdrop becomes visible when the container is open (mirror of .is-visible) */
322
+ .vd-modal-open .vd-modal-backdrop {
323
+ opacity: 1;
324
+ pointer-events: auto;
325
+ }
326
+
327
+ /* Panel merges .vd-modal-dialog (sizing/positioning) + .vd-modal-content (box) */
328
+ .vd-modal-panel {
329
+ position: relative;
330
+ display: flex;
331
+ flex-direction: column;
332
+ width: min(calc(100% - 3.5rem), var(--vd-modal-dialog-max-width));
333
+ max-width: var(--vd-modal-dialog-max-width);
334
+ margin: 1.75rem auto;
335
+ pointer-events: auto;
336
+ background-color: var(--vd-modal-bg);
337
+ background-clip: padding-box;
338
+ border: 1px solid var(--vd-modal-border-color);
339
+ border-radius: var(--vd-btn-border-radius-lg);
340
+ box-shadow: var(--vd-shadow-2xl);
341
+ outline: 0;
342
+ transform: scale(0.95);
343
+ transition: var(--vd-modal-dialog-transition);
344
+ z-index: 1060;
345
+ }
346
+
347
+ .vd-modal.vd-modal-open .vd-modal-panel {
348
+ transform: scale(1);
349
+ }
350
+
351
+ /* Panel sizes (md = default width) */
352
+ .vd-modal-panel-sm { --vd-modal-dialog-max-width: var(--vd-modal-width-sm); }
353
+ .vd-modal-panel-md { --vd-modal-dialog-max-width: var(--vd-modal-width); }
354
+ .vd-modal-panel-lg { --vd-modal-dialog-max-width: var(--vd-modal-width-lg); }
355
+
356
+ /* Glass variant parity with .vd-modal-glass .vd-modal-content */
357
+ .vd-modal-glass .vd-modal-panel {
358
+ background: var(--vd-glass-bg-light);
359
+ border-color: var(--vd-glass-border-light);
360
+ box-shadow: var(--vd-glass-shadow);
361
+ backdrop-filter: blur(var(--vd-glass-blur)) saturate(var(--vd-glass-saturate));
362
+ -webkit-backdrop-filter: blur(var(--vd-glass-blur)) saturate(var(--vd-glass-saturate));
363
+ }
364
+
365
+ @media (max-width: 575.98px) {
366
+ .vd-modal-panel {
367
+ margin: 0.5rem;
368
+ width: calc(100% - 1rem);
369
+ max-width: calc(100% - 1rem);
370
+ }
371
+ }
@@ -54,3 +54,34 @@
54
54
  }
55
55
  }
56
56
 
57
+ /* ==========================================================================
58
+ @vanduo-oss/vue VdPreloader nested spinner (additive; added in 1.6.1)
59
+ VdPreloader nests `.vd-preloader > .vd-preloader-spinner`; when the inner
60
+ element is present the spinner visual moves to it (legacy bare .vd-preloader
61
+ keeps spinning on its own). Size/color vars set on .vd-preloader inherit down.
62
+ ========================================================================== */
63
+ .vd-preloader:has(.vd-preloader-spinner) {
64
+ width: auto;
65
+ height: auto;
66
+ border: none;
67
+ border-radius: 0;
68
+ animation: none;
69
+ display: inline-flex;
70
+ }
71
+
72
+ .vd-preloader-spinner {
73
+ display: inline-block;
74
+ width: var(--vd-spinner-size, 2rem);
75
+ height: var(--vd-spinner-size, 2rem);
76
+ border: var(--vd-spinner-border-width, 3px) solid var(--vd-border-color, #e9ecef);
77
+ border-top-color: var(--vd-spinner-color, var(--vd-color-primary));
78
+ border-radius: 50%;
79
+ animation: spinner-rotate var(--vd-spinner-speed, 0.65s) linear infinite;
80
+ }
81
+
82
+ @media (prefers-reduced-motion: reduce) {
83
+ .vd-preloader-spinner {
84
+ animation-duration: 1.5s;
85
+ }
86
+ }
87
+
@@ -105,3 +105,49 @@
105
105
  --vd-progress-bg: var(--vd-bg-tertiary, #2d3748);
106
106
  }
107
107
  }
108
+
109
+ /* ==========================================================================
110
+ @vanduo-oss/vue VdProgress markup (additive; added in 1.6.1)
111
+ VdProgress renders `.vd-progress > .vd-progress-track > .vd-progress-fill`
112
+ plus an optional `.vd-progress-label`, and uses `.is-indeterminate` (vs the
113
+ legacy `.vd-progress-bar` / `.vd-progress-indeterminate`). Scoped with :has()
114
+ so the legacy single-bar progress is untouched.
115
+ ========================================================================== */
116
+ .vd-progress:has(.vd-progress-track) {
117
+ display: block;
118
+ height: auto;
119
+ overflow: visible;
120
+ background-color: transparent;
121
+ }
122
+
123
+ .vd-progress-track {
124
+ display: flex;
125
+ height: var(--vd-progress-height);
126
+ overflow: hidden;
127
+ background-color: var(--vd-progress-bg);
128
+ border-radius: var(--vd-progress-border-radius);
129
+ }
130
+
131
+ .vd-progress-fill {
132
+ display: block;
133
+ height: 100%;
134
+ background-color: var(--vd-progress-bar-bg);
135
+ border-radius: var(--vd-progress-border-radius);
136
+ transition: width 0.4s ease;
137
+ }
138
+
139
+ .vd-progress.is-indeterminate .vd-progress-fill {
140
+ width: 30%;
141
+ animation: progress-indeterminate 1.5s ease-in-out infinite;
142
+ }
143
+
144
+ .vd-progress-label {
145
+ display: block;
146
+ margin-top: 0.375rem;
147
+ }
148
+
149
+ @media (prefers-reduced-motion: reduce) {
150
+ .vd-progress.is-indeterminate .vd-progress-fill {
151
+ animation: none;
152
+ }
153
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Vanduo Framework - Separator / Divider
3
+ * Added in 1.7.0 to back @vanduo-oss/vue's VdSeparator.
4
+ */
5
+
6
+ :root {
7
+ --vd-separator-color: var(--vd-border-color);
8
+ --vd-separator-spacing: 1.3125rem; /* 21px - fib */
9
+ }
10
+
11
+ .vd-separator {
12
+ width: 100%;
13
+ height: 0;
14
+ margin: var(--vd-separator-spacing) 0;
15
+ border: none;
16
+ border-top: 1px solid var(--vd-separator-color);
17
+ }
18
+
19
+ .vd-separator-vertical {
20
+ width: 0;
21
+ height: auto;
22
+ min-height: 1em;
23
+ margin: 0 var(--vd-separator-spacing);
24
+ border-top: none;
25
+ border-left: 1px solid var(--vd-separator-color);
26
+ align-self: stretch;
27
+ }
28
+
29
+ /* Labeled separator: a horizontal rule with centered text. */
30
+ .vd-separator-labeled {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 0.75rem;
34
+ width: 100%;
35
+ margin: var(--vd-separator-spacing) 0;
36
+ border: none;
37
+ color: var(--vd-text-muted);
38
+ font-size: var(--vd-font-size-sm);
39
+ }
40
+
41
+ .vd-separator-labeled::before,
42
+ .vd-separator-labeled::after {
43
+ content: '';
44
+ flex: 1 1 auto;
45
+ border-top: 1px solid var(--vd-separator-color);
46
+ }
47
+
48
+ .vd-separator-label {
49
+ flex-shrink: 0;
50
+ }
@@ -240,3 +240,45 @@
240
240
  animation: none;
241
241
  }
242
242
  }
243
+
244
+ /* ==========================================================================
245
+ @vanduo-oss/vue VdSkeleton additions (additive; added in 1.6.1)
246
+ VdSkeleton renders multi-line (`.vd-skeleton-lines`) and card shapes
247
+ (`.vd-skeleton-card.vd-skeleton-card-{size} > .vd-skeleton-card-header +
248
+ .vd-skeleton-card-body`), plus a `.vd-skeleton-text-short` last line.
249
+ ========================================================================== */
250
+ .vd-skeleton-lines {
251
+ display: flex;
252
+ flex-direction: column;
253
+ gap: 0.5rem;
254
+ }
255
+
256
+ .vd-skeleton-lines .vd-skeleton-text {
257
+ margin-bottom: 0;
258
+ }
259
+
260
+ .vd-skeleton-text-short {
261
+ width: 60%;
262
+ }
263
+
264
+ .vd-skeleton-card-header {
265
+ height: 8rem;
266
+ width: 100%;
267
+ margin-bottom: 0.8125rem;
268
+ }
269
+
270
+ .vd-skeleton-card-body {
271
+ display: flex;
272
+ flex-direction: column;
273
+ gap: 0.5rem;
274
+ }
275
+
276
+ .vd-skeleton-card-body .vd-skeleton-text {
277
+ margin-bottom: 0;
278
+ }
279
+
280
+ /* Card size variants scale the header placeholder height */
281
+ .vd-skeleton-card-sm .vd-skeleton-card-header { height: 5rem; }
282
+ .vd-skeleton-card-md .vd-skeleton-card-header { height: 8rem; }
283
+ .vd-skeleton-card-lg .vd-skeleton-card-header { height: 12rem; }
284
+ .vd-skeleton-card-xl .vd-skeleton-card-header { height: 16rem; }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Vanduo Framework - Slider (range input)
3
+ * Added in 1.7.0 to back @vanduo-oss/vue's VdSlider.
4
+ */
5
+
6
+ :root {
7
+ --vd-slider-track-height: 0.375rem; /* 6px */
8
+ --vd-slider-track-bg: var(--vd-bg-tertiary, #e9ecef);
9
+ --vd-slider-thumb-size: 1.125rem; /* 18px */
10
+ --vd-slider-thumb-bg: var(--vd-color-primary);
11
+ }
12
+
13
+ .vd-slider-field {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: 0.375rem;
17
+ width: 100%;
18
+ }
19
+
20
+ .vd-slider-row {
21
+ display: flex;
22
+ align-items: center;
23
+ gap: 0.75rem;
24
+ }
25
+
26
+ .vd-slider-value {
27
+ flex-shrink: 0;
28
+ min-width: 3ch;
29
+ text-align: right;
30
+ font-size: var(--vd-font-size-sm);
31
+ font-variant-numeric: tabular-nums;
32
+ color: var(--vd-text-secondary);
33
+ }
34
+
35
+ .vd-slider {
36
+ -webkit-appearance: none;
37
+ appearance: none;
38
+ width: 100%;
39
+ height: var(--vd-slider-track-height);
40
+ border-radius: calc(var(--vd-slider-track-height) / 2);
41
+ background-color: var(--vd-slider-track-bg);
42
+ cursor: pointer;
43
+ outline-offset: 4px;
44
+ }
45
+
46
+ .vd-slider:disabled {
47
+ opacity: 0.6;
48
+ cursor: not-allowed;
49
+ }
50
+
51
+ .vd-slider:focus-visible {
52
+ outline: 2px solid var(--vd-color-primary);
53
+ }
54
+
55
+ /* WebKit / Blink thumb */
56
+ .vd-slider::-webkit-slider-thumb {
57
+ -webkit-appearance: none;
58
+ appearance: none;
59
+ width: var(--vd-slider-thumb-size);
60
+ height: var(--vd-slider-thumb-size);
61
+ border: 2px solid var(--vd-color-white);
62
+ border-radius: 50%;
63
+ background-color: var(--vd-slider-thumb-bg);
64
+ box-shadow: var(--vd-shadow-sm);
65
+ transition: transform 0.1s ease;
66
+ }
67
+
68
+ .vd-slider::-webkit-slider-thumb:active {
69
+ transform: scale(1.15);
70
+ }
71
+
72
+ /* Firefox thumb + track */
73
+ .vd-slider::-moz-range-thumb {
74
+ width: var(--vd-slider-thumb-size);
75
+ height: var(--vd-slider-thumb-size);
76
+ border: 2px solid var(--vd-color-white);
77
+ border-radius: 50%;
78
+ background-color: var(--vd-slider-thumb-bg);
79
+ box-shadow: var(--vd-shadow-sm);
80
+ }
81
+
82
+ .vd-slider::-moz-range-track {
83
+ height: var(--vd-slider-track-height);
84
+ border-radius: calc(var(--vd-slider-track-height) / 2);
85
+ background-color: var(--vd-slider-track-bg);
86
+ }
87
+
88
+ @media (prefers-reduced-motion: reduce) {
89
+ .vd-slider::-webkit-slider-thumb {
90
+ transition: none;
91
+ }
92
+ }
@@ -327,3 +327,49 @@
327
327
  transition: none;
328
328
  }
329
329
  }
330
+
331
+ /* ==========================================================================
332
+ @vanduo-oss/vue VdTabs markup (additive; added in 1.6.1)
333
+ VdTabs renders `.vd-tabs > .vd-tab-list > button.vd-tab.is-active` and a
334
+ `.vd-tab-panels` wrapper (vs the legacy .vd-tab-link / .vd-tab-content).
335
+ ========================================================================== */
336
+ .vd-tab {
337
+ display: inline-flex;
338
+ align-items: center;
339
+ gap: 0.5rem;
340
+ padding: var(--vd-tab-padding-y) var(--vd-tab-padding-x);
341
+ font-size: var(--vd-font-size-base);
342
+ font-weight: var(--vd-font-weight-medium);
343
+ color: var(--vd-tab-text);
344
+ background: transparent;
345
+ border: none;
346
+ border-bottom: var(--vd-tab-border-width) solid transparent;
347
+ cursor: pointer;
348
+ transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
349
+ white-space: nowrap;
350
+ }
351
+
352
+ .vd-tab:hover {
353
+ color: var(--vd-tab-text-hover);
354
+ background-color: var(--vd-tab-bg-hover);
355
+ }
356
+
357
+ .vd-tab:focus-visible {
358
+ outline: 2px solid var(--vd-color-primary);
359
+ outline-offset: -2px;
360
+ }
361
+
362
+ .vd-tab.is-active {
363
+ color: var(--vd-tab-text-active);
364
+ border-bottom-color: var(--vd-tab-border-active);
365
+ }
366
+
367
+ .vd-tab-panels {
368
+ padding-top: 1rem;
369
+ }
370
+
371
+ @media (prefers-reduced-motion: reduce) {
372
+ .vd-tab {
373
+ transition: none;
374
+ }
375
+ }
@@ -2203,3 +2203,20 @@
2203
2203
  --vd-radius-fib-13: 1.625rem; /* 26px */
2204
2204
  --vd-radius-fib-21: 2.625rem; /* 42px */
2205
2205
  }
2206
+
2207
+ /* Muted text + visually-hidden utilities (added in 1.6.1; used by @vanduo-oss/vue) */
2208
+ .vd-muted {
2209
+ color: var(--vd-text-muted);
2210
+ }
2211
+
2212
+ .vd-visually-hidden {
2213
+ position: absolute !important;
2214
+ width: 1px;
2215
+ height: 1px;
2216
+ padding: 0;
2217
+ margin: -1px;
2218
+ overflow: hidden;
2219
+ clip: rect(0, 0, 0, 0);
2220
+ white-space: nowrap;
2221
+ border: 0;
2222
+ }
@@ -32,6 +32,15 @@
32
32
  border-collapse: collapse;
33
33
  }
34
34
 
35
+ /* @vanduo-oss/vue VdTable <caption> (additive; added in 1.6.1) */
36
+ .vd-table-caption {
37
+ padding: var(--vd-table-padding-y) var(--vd-table-padding-x);
38
+ color: var(--vd-text-muted);
39
+ font-size: var(--vd-font-size-sm);
40
+ text-align: left;
41
+ caption-side: top;
42
+ }
43
+
35
44
  .vd-table th,
36
45
  .vd-table td,
37
46
  .table th,
package/css/vanduo.css CHANGED
@@ -42,6 +42,9 @@
42
42
  @import url('components/buttons.css');
43
43
  @import url('components/forms.css');
44
44
  @import url('components/cards.css');
45
+ @import url('components/accordion.css');
46
+ @import url('components/separator.css');
47
+ @import url('components/slider.css');
45
48
  @import url('components/expanding-cards.css');
46
49
  @import url('components/navbar.css');
47
50
  @import url('components/footer.css');
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.6.0",
3
- "builtAt": "2026-06-27T15:48:08.659Z",
4
- "commit": "9384f14",
2
+ "version": "1.7.0",
3
+ "builtAt": "2026-06-29T06:28:14.462Z",
4
+ "commit": "c12c685",
5
5
  "mode": "development+production"
6
6
  }