@profpowell/vb-design-system 0.1.0 → 0.2.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.
Files changed (31) hide show
  1. package/README.md +5 -3
  2. package/dist/vb-design-system.css +5 -5
  3. package/dist/vb-design-system.js +37 -35
  4. package/dist/vb-design-system.min.css +1 -1
  5. package/dist/vb-design-system.min.js +28 -28
  6. package/package.json +6 -6
  7. package/src/lib/vb-element.js +15 -1
  8. package/src/web-components/breakpoint-specimen/styles.css +2 -2
  9. package/src/web-components/font-pairer/logic.js +16 -16
  10. package/src/web-components/gradient-builder/logic.js +1 -1
  11. package/src/web-components/motion-specimen/logic.js +1 -1
  12. package/src/web-components/palette-generator/_palette-utils.js +1 -1
  13. package/src/web-components/palette-generator/logic.js +1 -1
  14. package/src/web-components/palette-generator/styles.css +1 -1
  15. package/src/web-components/semantic-palette/_color-math.js +1 -1
  16. package/src/web-components/semantic-palette/logic.js +13 -9
  17. package/src/web-components/spacing-specimen/styles.css +1 -1
  18. package/src/web-components/theme-catalog/logic.js +3 -3
  19. package/src/web-components/theme-import/catalog/atlassian.tokens.json +2 -2
  20. package/src/web-components/theme-import/catalog/bootstrap.tokens.json +2 -2
  21. package/src/web-components/theme-import/catalog/carbon.tokens.json +2 -2
  22. package/src/web-components/theme-import/catalog/catppuccin-mocha.tokens.json +2 -2
  23. package/src/web-components/theme-import/catalog/govuk.tokens.json +2 -2
  24. package/src/web-components/theme-import/catalog/manifest.json +1 -1
  25. package/src/web-components/theme-import/catalog/material.tokens.json +2 -2
  26. package/src/web-components/theme-import/catalog/salesforce.tokens.json +2 -2
  27. package/src/web-components/theme-import/catalog/tailwind.tokens.json +2 -2
  28. package/src/web-components/type-specimen/logic.js +4 -4
  29. package/src/web-components/type-specimen/static.html +3 -3
  30. package/src/web-components/type-specimen/styles.css +1 -1
  31. /package/src/{web-components/color-picker/_color-utils.js → lib/color-utils.js} +0 -0
@@ -63,9 +63,13 @@ class SemanticPalette extends VBElement {
63
63
  /** @type {HTMLElement|null} */ #probe = null;
64
64
 
65
65
  setup() {
66
- this.#probe = document.createElement('span');
67
- this.#probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none';
68
- this.append(this.#probe);
66
+ // Reconnect guard: setup() re-runs after a disconnect/reconnect (the base
67
+ // class clears data-upgraded); the probe moved back with the host, so reuse it.
68
+ if (this.#probe?.parentNode !== this) {
69
+ this.#probe = document.createElement('span');
70
+ this.#probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none';
71
+ this.append(this.#probe);
72
+ }
69
73
 
70
74
  this.#source = this.querySelector('color-palette, palette-generator');
71
75
  this.#resolveRoles();
@@ -193,7 +197,7 @@ class SemanticPalette extends VBElement {
193
197
  return `<article class="sp-card" data-role="${role}" aria-label="${roleLabel} role preview" style="${cardStyle}">
194
198
  <header style="display:flex;align-items:center;justify-content:space-between;gap:var(--size-s,0.75rem)">
195
199
  <div>
196
- <code style="font-family:${MONO};font-size:var(--font-size-sm,0.875rem);font-weight:600">${role}</code>
200
+ <code style="font-family:${MONO};font-size:var(--font-size-s,0.875rem);font-weight:600">${role}</code>
197
201
  <span style="display:block;font-size:var(--font-size-xs,0.75rem);color:${MUTED}">${roleLabel}</span>
198
202
  </div>
199
203
  <div style="display:flex;align-items:center;gap:0.5rem">
@@ -213,11 +217,11 @@ class SemanticPalette extends VBElement {
213
217
 
214
218
  return [
215
219
  this.#sample({
216
- render: `<button type="button" tabindex="-1" style="all:unset;display:inline-block;padding:0.375rem 0.875rem;border-radius:${RADIUS_S};background:${hex};color:${textOnRole};font-family:inherit;font-size:var(--font-size-sm,0.875rem);font-weight:600;cursor:default">Button</button>`,
220
+ render: `<button type="button" tabindex="-1" style="all:unset;display:inline-block;padding:0.375rem 0.875rem;border-radius:${RADIUS_S};background:${hex};color:${textOnRole};font-family:inherit;font-size:var(--font-size-s,0.875rem);font-weight:600;cursor:default">Button</button>`,
217
221
  fg: textOnRole, bg: hex, caption: 'On role',
218
222
  }),
219
223
  this.#sample({
220
- render: `<span style="color:${hex};background:${surface};padding:0.25rem 0.5rem;border-radius:${RADIUS_S};font-size:var(--font-size-sm,0.875rem);font-weight:500;text-decoration:underline">Linked text</span>`,
224
+ render: `<span style="color:${hex};background:${surface};padding:0.25rem 0.5rem;border-radius:${RADIUS_S};font-size:var(--font-size-s,0.875rem);font-weight:500;text-decoration:underline">Linked text</span>`,
221
225
  fg: hex, bg: surface || '#ffffff', caption: 'On surface',
222
226
  }),
223
227
  this.#sample({
@@ -235,7 +239,7 @@ class SemanticPalette extends VBElement {
235
239
 
236
240
  return [
237
241
  this.#sample({
238
- render: `<div style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-radius:${RADIUS_S};background:${subtleBg};color:${statusText};border:1px solid ${hex};font-size:var(--font-size-sm,0.875rem);max-inline-size:100%">
242
+ render: `<div style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-radius:${RADIUS_S};background:${subtleBg};color:${statusText};border:1px solid ${hex};font-size:var(--font-size-s,0.875rem);max-inline-size:100%">
239
243
  <span style="display:inline-block;inline-size:0.5rem;block-size:0.5rem;border-radius:50%;background:${hex};flex-shrink:0"></span>
240
244
  <span><strong>${ROLE_LABELS[role] || role}</strong> — message text</span>
241
245
  </div>`,
@@ -246,7 +250,7 @@ class SemanticPalette extends VBElement {
246
250
  fg: onRole, bg: hex, caption: 'Badge',
247
251
  }),
248
252
  this.#sample({
249
- render: `<span style="color:${hex};background:${surface};padding:0.25rem 0.5rem;border-radius:${RADIUS_S};font-size:var(--font-size-sm,0.875rem);font-weight:600">Inline status</span>`,
253
+ render: `<span style="color:${hex};background:${surface};padding:0.25rem 0.5rem;border-radius:${RADIUS_S};font-size:var(--font-size-s,0.875rem);font-weight:600">Inline status</span>`,
250
254
  fg: hex, bg: surface || '#ffffff', caption: 'On surface',
251
255
  }),
252
256
  ].join('');
@@ -270,7 +274,7 @@ class SemanticPalette extends VBElement {
270
274
 
271
275
  #renderExport() {
272
276
  const toolbar = `display:flex;gap:var(--size-2xs,0.375rem);padding-block-start:var(--size-xs,0.5rem);border-block-start:1px solid ${BORDER}`;
273
- const btn = `padding:0.375rem 0.875rem;border:1px solid ${BORDER};border-radius:${RADIUS_S};background:${SURFACE};color:${TEXT};cursor:pointer;font:inherit;font-size:var(--font-size-sm,0.875rem)`;
277
+ const btn = `padding:0.375rem 0.875rem;border:1px solid ${BORDER};border-radius:${RADIUS_S};background:${SURFACE};color:${TEXT};cursor:pointer;font:inherit;font-size:var(--font-size-s,0.875rem)`;
274
278
  return `<div class="sp-export" role="toolbar" aria-label="Export semantic palette" style="${toolbar}">
275
279
  <button type="button" class="sp-copy-css" style="${btn}">Copy Theme CSS</button>
276
280
  <button type="button" class="sp-copy-json" style="${btn}">Copy JSON</button>
@@ -34,7 +34,7 @@ spacing-specimen .scale-step {
34
34
 
35
35
  spacing-specimen .scale-name {
36
36
  font-family: var(--font-mono, monospace);
37
- font-size: var(--font-size-sm, 0.875rem);
37
+ font-size: var(--font-size-s, 0.875rem);
38
38
  color: var(--color-text-muted, #666);
39
39
  text-align: end;
40
40
  }
@@ -74,13 +74,13 @@ class ThemeCatalog extends VBElement {
74
74
  const card = `border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem);min-block-size:0`;
75
75
  const grid = `display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--size-s,0.75rem)`;
76
76
  const muted = `font-size:var(--font-size-xs,0.75rem);color:var(--color-text-muted,#666)`;
77
- const title = `margin:0;font-size:var(--font-size-md,1rem);font-weight:600;color:var(--color-text,#222)`;
77
+ const title = `margin:0;font-size:var(--font-size-m,1rem);font-weight:600;color:var(--color-text,#222)`;
78
78
  const btn = `align-self:flex-start;padding:0.375rem 0.75rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-primary,#0066cc);color:var(--color-text-on-primary,#fff);cursor:pointer;font:inherit;font-size:var(--font-size-xs,0.75rem)`;
79
79
  const tag = `display:inline-block;padding:0.125rem 0.375rem;border-radius:0.25rem;background:var(--color-surface-raised,#f3f3f3);${muted};margin-inline-end:0.25rem`;
80
80
 
81
81
  this.innerHTML = `
82
82
  <div class="tc-head" style="display:flex;align-items:baseline;gap:var(--size-s,0.75rem);margin-block-end:var(--size-s,0.75rem);flex-wrap:wrap">
83
- <strong style="font-size:var(--font-size-sm,0.875rem)">Start from a known system</strong>
83
+ <strong style="font-size:var(--font-size-s,0.875rem)">Start from a known system</strong>
84
84
  <span class="tc-target" style="${muted}"></span>
85
85
  </div>
86
86
  <div class="tc-grid" style="${grid}" role="list"></div>
@@ -129,7 +129,7 @@ class ThemeCatalog extends VBElement {
129
129
  const grid = this.querySelector('.tc-grid');
130
130
  if (!grid || !this.#entries) return;
131
131
  const card = `border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem)`;
132
- const title = `margin:0;font-size:var(--font-size-md,1rem);font-weight:600;color:var(--color-text,#222)`;
132
+ const title = `margin:0;font-size:var(--font-size-m,1rem);font-weight:600;color:var(--color-text,#222)`;
133
133
  const btn = `align-self:flex-start;margin-block-start:auto;padding:0.375rem 0.75rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-primary,#0066cc);color:var(--color-text-on-primary,#fff);cursor:pointer;font:inherit;font-size:var(--font-size-xs,0.75rem)`;
134
134
  const muted = `font-size:var(--font-size-xs,0.75rem);color:var(--color-text-muted,#666)`;
135
135
  const tag = `display:inline-block;padding:0.125rem 0.375rem;border-radius:0.25rem;background:var(--color-surface-raised,#f3f3f3);${muted};margin-inline-end:0.25rem`;
@@ -231,7 +231,7 @@
231
231
  }
232
232
  },
233
233
  "size": {
234
- "md": {
234
+ "m": {
235
235
  "$type": "dimension",
236
236
  "$value": {
237
237
  "value": 0.875,
@@ -300,4 +300,4 @@
300
300
  }
301
301
  }
302
302
  }
303
- }
303
+ }
@@ -231,7 +231,7 @@
231
231
  }
232
232
  },
233
233
  "size": {
234
- "md": {
234
+ "m": {
235
235
  "$type": "dimension",
236
236
  "$value": {
237
237
  "value": 1,
@@ -301,4 +301,4 @@
301
301
  }
302
302
  }
303
303
  }
304
- }
304
+ }
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "size": {
232
- "md": {
232
+ "m": {
233
233
  "$type": "dimension",
234
234
  "$value": {
235
235
  "value": 0.875,
@@ -298,4 +298,4 @@
298
298
  }
299
299
  }
300
300
  }
301
- }
301
+ }
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "size": {
232
- "md": {
232
+ "m": {
233
233
  "$type": "dimension",
234
234
  "$value": {
235
235
  "value": 1,
@@ -298,4 +298,4 @@
298
298
  }
299
299
  }
300
300
  }
301
- }
301
+ }
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "size": {
232
- "md": {
232
+ "m": {
233
233
  "$type": "dimension",
234
234
  "$value": {
235
235
  "value": 1.1875,
@@ -298,4 +298,4 @@
298
298
  }
299
299
  }
300
300
  }
301
- }
301
+ }
@@ -129,4 +129,4 @@
129
129
  "syncedAt": "2026-05-15"
130
130
  }
131
131
  ]
132
- }
132
+ }
@@ -217,7 +217,7 @@
217
217
  }
218
218
  },
219
219
  "size": {
220
- "md": {
220
+ "m": {
221
221
  "$type": "dimension",
222
222
  "$value": {
223
223
  "value": 1,
@@ -286,4 +286,4 @@
286
286
  }
287
287
  }
288
288
  }
289
- }
289
+ }
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "size": {
232
- "md": {
232
+ "m": {
233
233
  "$type": "dimension",
234
234
  "$value": {
235
235
  "value": 0.8125,
@@ -298,4 +298,4 @@
298
298
  }
299
299
  }
300
300
  }
301
- }
301
+ }
@@ -229,7 +229,7 @@
229
229
  }
230
230
  },
231
231
  "size": {
232
- "md": {
232
+ "m": {
233
233
  "$type": "dimension",
234
234
  "$value": {
235
235
  "value": 1,
@@ -299,4 +299,4 @@
299
299
  }
300
300
  }
301
301
  }
302
- }
302
+ }
@@ -57,7 +57,7 @@ class TypeSpecimen extends VBElement {
57
57
 
58
58
  // Header with font name and large sample
59
59
  const labelHTML = editable
60
- ? `<input type="text" class="specimen-font-input" value="${fontFamily.replace(/"/g, '&quot;')}" aria-label="Font family" style="font:inherit;padding:0.25rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);min-inline-size:18rem;max-inline-size:100%;font-family:${fontFamily};font-size:var(--font-size-sm,0.875rem)">
60
+ ? `<input type="text" class="specimen-font-input" value="${fontFamily.replace(/"/g, '&quot;')}" aria-label="Font family" style="font:inherit;padding:0.25rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);min-inline-size:18rem;max-inline-size:100%;font-family:${fontFamily};font-size:var(--font-size-s,0.875rem)">
61
61
  <span class="specimen-quick" style="display:inline-flex;flex-wrap:wrap;gap:0.25rem;margin-inline-start:0.5rem">
62
62
  ${QUICK_FONTS.map((f) => `<button type="button" class="specimen-quick-btn" data-font="${f.replace(/"/g, '&quot;')}" style="font:inherit;font-size:var(--font-size-xs,0.75rem);padding:0.125rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:999px;background:var(--color-surface,#fff);color:var(--color-text,#222);cursor:pointer">${f.split(',')[0].replace(/["']/g, '')}</button>`).join('')}
63
63
  </span>`
@@ -94,9 +94,9 @@ class TypeSpecimen extends VBElement {
94
94
  if (showScale) {
95
95
  const scale = [
96
96
  { name: 'xs', rem: 0.75 },
97
- { name: 'sm', rem: 0.875 },
98
- { name: 'md', rem: 1 },
99
- { name: 'lg', rem: 1.125 },
97
+ { name: 's', rem: 0.875 },
98
+ { name: 'm', rem: 1 },
99
+ { name: 'l', rem: 1.125 },
100
100
  { name: 'xl', rem: 1.25 },
101
101
  { name: '2xl', rem: 1.5 },
102
102
  { name: '3xl', rem: 1.875 },
@@ -55,13 +55,13 @@
55
55
  <small>xs (0.75rem)</small> — The quick brown fox jumps over
56
56
  </p>
57
57
  <p style="font-family: Georgia, serif; font-size: 0.875rem">
58
- <small>sm (0.875rem)</small> — The quick brown fox jumps over
58
+ <small>s (0.875rem)</small> — The quick brown fox jumps over
59
59
  </p>
60
60
  <p style="font-family: Georgia, serif; font-size: 1rem">
61
- <small>md (1rem)</small> — The quick brown fox jumps over
61
+ <small>m (1rem)</small> — The quick brown fox jumps over
62
62
  </p>
63
63
  <p style="font-family: Georgia, serif; font-size: 1.125rem">
64
- <small>lg (1.125rem)</small> — The quick brown fox jumps over
64
+ <small>l (1.125rem)</small> — The quick brown fox jumps over
65
65
  </p>
66
66
  <p style="font-family: Georgia, serif; font-size: 1.25rem">
67
67
  <small>xl (1.25rem)</small> — The quick brown fox jumps over
@@ -59,7 +59,7 @@ type-specimen .char-row {
59
59
  flex-wrap: wrap;
60
60
  gap: 2px;
61
61
  align-items: center;
62
- font-size: var(--font-size-sm, 0.875rem);
62
+ font-size: var(--font-size-s, 0.875rem);
63
63
  }
64
64
 
65
65
  type-specimen .char-label {