@profpowell/vb-design-system 0.1.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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/dist/vb-design-system.css +993 -0
  4. package/dist/vb-design-system.js +4482 -0
  5. package/dist/vb-design-system.min.css +1 -0
  6. package/dist/vb-design-system.min.js +513 -0
  7. package/package.json +78 -0
  8. package/src/index.css +21 -0
  9. package/src/index.js +24 -0
  10. package/src/lib/bundle-registry.js +156 -0
  11. package/src/lib/vb-element.js +96 -0
  12. package/src/patterns/do-dont.css +86 -0
  13. package/src/patterns/token-table.css +67 -0
  14. package/src/utils/copy-init.js +287 -0
  15. package/src/web-components/accessibility-specimen/api.json +51 -0
  16. package/src/web-components/accessibility-specimen/logic.js +232 -0
  17. package/src/web-components/accessibility-specimen/static.html +41 -0
  18. package/src/web-components/accessibility-specimen/styles.css +156 -0
  19. package/src/web-components/brand-specimen/api.json +37 -0
  20. package/src/web-components/brand-specimen/logic.js +61 -0
  21. package/src/web-components/brand-specimen/static.html +77 -0
  22. package/src/web-components/brand-specimen/styles.css +10 -0
  23. package/src/web-components/breakpoint-specimen/api.json +44 -0
  24. package/src/web-components/breakpoint-specimen/logic.js +186 -0
  25. package/src/web-components/breakpoint-specimen/static.html +38 -0
  26. package/src/web-components/breakpoint-specimen/styles.css +180 -0
  27. package/src/web-components/color-palette/api.json +73 -0
  28. package/src/web-components/color-palette/logic.js +280 -0
  29. package/src/web-components/color-palette/static.html +54 -0
  30. package/src/web-components/color-palette/styles.css +113 -0
  31. package/src/web-components/color-picker/_color-utils.js +210 -0
  32. package/src/web-components/component-sampler/api.json +15 -0
  33. package/src/web-components/component-sampler/logic.js +120 -0
  34. package/src/web-components/component-sampler/static.html +47 -0
  35. package/src/web-components/component-sampler/styles.css +9 -0
  36. package/src/web-components/font-pairer/_font-data.js +95 -0
  37. package/src/web-components/font-pairer/api.json +56 -0
  38. package/src/web-components/font-pairer/logic.js +401 -0
  39. package/src/web-components/font-pairer/static.html +9 -0
  40. package/src/web-components/font-pairer/styles.css +10 -0
  41. package/src/web-components/gradient-builder/_gradient-utils.js +54 -0
  42. package/src/web-components/gradient-builder/api.json +63 -0
  43. package/src/web-components/gradient-builder/logic.js +261 -0
  44. package/src/web-components/gradient-builder/static.html +9 -0
  45. package/src/web-components/gradient-builder/styles.css +10 -0
  46. package/src/web-components/icon-set/api.json +39 -0
  47. package/src/web-components/icon-set/logic.js +133 -0
  48. package/src/web-components/icon-set/static.html +36 -0
  49. package/src/web-components/icon-set/styles.css +82 -0
  50. package/src/web-components/icon-specimen/api.json +46 -0
  51. package/src/web-components/icon-specimen/logic.js +67 -0
  52. package/src/web-components/icon-specimen/static.html +39 -0
  53. package/src/web-components/icon-specimen/styles.css +38 -0
  54. package/src/web-components/layout-specimen/api.json +12 -0
  55. package/src/web-components/layout-specimen/logic.js +219 -0
  56. package/src/web-components/layout-specimen/static.html +22 -0
  57. package/src/web-components/layout-specimen/styles.css +95 -0
  58. package/src/web-components/motion-specimen/api.json +54 -0
  59. package/src/web-components/motion-specimen/logic.js +146 -0
  60. package/src/web-components/motion-specimen/static.html +13 -0
  61. package/src/web-components/motion-specimen/styles.css +29 -0
  62. package/src/web-components/palette-generator/_palette-utils.js +133 -0
  63. package/src/web-components/palette-generator/api.json +79 -0
  64. package/src/web-components/palette-generator/logic.js +288 -0
  65. package/src/web-components/palette-generator/static.html +47 -0
  66. package/src/web-components/palette-generator/styles.css +36 -0
  67. package/src/web-components/semantic-palette/_color-math.js +149 -0
  68. package/src/web-components/semantic-palette/api.json +41 -0
  69. package/src/web-components/semantic-palette/logic.js +400 -0
  70. package/src/web-components/semantic-palette/static.html +42 -0
  71. package/src/web-components/semantic-palette/styles.css +20 -0
  72. package/src/web-components/spacing-specimen/api.json +63 -0
  73. package/src/web-components/spacing-specimen/logic.js +132 -0
  74. package/src/web-components/spacing-specimen/static.html +71 -0
  75. package/src/web-components/spacing-specimen/styles.css +58 -0
  76. package/src/web-components/theme-catalog/api.json +14 -0
  77. package/src/web-components/theme-catalog/logic.js +228 -0
  78. package/src/web-components/theme-catalog/static.html +15 -0
  79. package/src/web-components/theme-export/api.json +18 -0
  80. package/src/web-components/theme-export/dtcg-serialize.js +417 -0
  81. package/src/web-components/theme-export/logic.js +201 -0
  82. package/src/web-components/theme-export/static.html +12 -0
  83. package/src/web-components/theme-export/theme-css-parse.js +93 -0
  84. package/src/web-components/theme-import/api.json +14 -0
  85. package/src/web-components/theme-import/catalog/atlassian.tokens.json +303 -0
  86. package/src/web-components/theme-import/catalog/bootstrap.tokens.json +304 -0
  87. package/src/web-components/theme-import/catalog/carbon.tokens.json +301 -0
  88. package/src/web-components/theme-import/catalog/catppuccin-mocha.tokens.json +301 -0
  89. package/src/web-components/theme-import/catalog/govuk.tokens.json +301 -0
  90. package/src/web-components/theme-import/catalog/manifest.json +132 -0
  91. package/src/web-components/theme-import/catalog/material.tokens.json +289 -0
  92. package/src/web-components/theme-import/catalog/salesforce.tokens.json +301 -0
  93. package/src/web-components/theme-import/catalog/tailwind.tokens.json +302 -0
  94. package/src/web-components/theme-import/dtcg-deserialize.js +322 -0
  95. package/src/web-components/theme-import/logic.js +263 -0
  96. package/src/web-components/theme-import/static.html +15 -0
  97. package/src/web-components/token-specimen/api.json +24 -0
  98. package/src/web-components/token-specimen/logic.js +256 -0
  99. package/src/web-components/token-specimen/static.html +47 -0
  100. package/src/web-components/token-specimen/styles.css +10 -0
  101. package/src/web-components/type-specimen/api.json +91 -0
  102. package/src/web-components/type-specimen/logic.js +156 -0
  103. package/src/web-components/type-specimen/static.html +84 -0
  104. package/src/web-components/type-specimen/styles.css +131 -0
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@profpowell/vb-design-system",
3
+ "version": "0.1.0",
4
+ "description": "Design-system documentation components for Vanilla Breeze: color, type, spacing, token and motion specimens, palette generator, semantic palette, component sampler, theme export, accessibility specimen, breakpoint specimen, layout specimen, font pairer, and gradient builder.",
5
+ "license": "MIT",
6
+ "author": "Patrick Powell",
7
+ "type": "module",
8
+ "homepage": "https://github.com/ProfPowell/vb-design-system#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ProfPowell/vb-design-system.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/ProfPowell/vb-design-system/issues"
15
+ },
16
+ "keywords": [
17
+ "vanilla-breeze",
18
+ "web-components",
19
+ "design-system",
20
+ "design-tokens",
21
+ "specimen",
22
+ "theme"
23
+ ],
24
+ "files": [
25
+ "src",
26
+ "dist"
27
+ ],
28
+ "main": "./dist/vb-design-system.js",
29
+ "module": "./src/index.js",
30
+ "style": "./dist/vb-design-system.css",
31
+ "exports": {
32
+ ".": {
33
+ "import": "./src/index.js",
34
+ "default": "./dist/vb-design-system.js"
35
+ },
36
+ "./css": "./src/index.css",
37
+ "./dist/css": "./dist/vb-design-system.css",
38
+ "./color-palette": "./src/web-components/color-palette/logic.js",
39
+ "./palette-generator": "./src/web-components/palette-generator/logic.js",
40
+ "./type-specimen": "./src/web-components/type-specimen/logic.js",
41
+ "./spacing-specimen": "./src/web-components/spacing-specimen/logic.js",
42
+ "./token-specimen": "./src/web-components/token-specimen/logic.js",
43
+ "./component-sampler": "./src/web-components/component-sampler/logic.js",
44
+ "./semantic-palette": "./src/web-components/semantic-palette/logic.js",
45
+ "./motion-specimen": "./src/web-components/motion-specimen/logic.js",
46
+ "./theme-export": "./src/web-components/theme-export/logic.js",
47
+ "./accessibility-specimen": "./src/web-components/accessibility-specimen/logic.js",
48
+ "./breakpoint-specimen": "./src/web-components/breakpoint-specimen/logic.js",
49
+ "./layout-specimen": "./src/web-components/layout-specimen/logic.js",
50
+ "./font-pairer": "./src/web-components/font-pairer/logic.js",
51
+ "./gradient-builder": "./src/web-components/gradient-builder/logic.js",
52
+ "./theme-import": "./src/web-components/theme-import/logic.js",
53
+ "./theme-catalog": "./src/web-components/theme-catalog/logic.js",
54
+ "./brand-specimen": "./src/web-components/brand-specimen/logic.js",
55
+ "./icon-set": "./src/web-components/icon-set/logic.js",
56
+ "./icon-specimen": "./src/web-components/icon-specimen/logic.js",
57
+ "./package.json": "./package.json"
58
+ },
59
+ "scripts": {
60
+ "build": "npm run build:js && npm run build:css",
61
+ "build:js": "esbuild src/index.js --bundle --format=esm --outfile=dist/vb-design-system.js && esbuild src/index.js --bundle --format=esm --minify --outfile=dist/vb-design-system.min.js",
62
+ "build:css": "esbuild src/index.css --bundle --outfile=dist/vb-design-system.css && esbuild src/index.css --bundle --minify --outfile=dist/vb-design-system.min.css",
63
+ "prepublishOnly": "npm run build",
64
+ "test:components": "playwright test"
65
+ },
66
+ "peerDependencies": {
67
+ "vanilla-breeze": ">=0.1.0"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "vanilla-breeze": {
71
+ "optional": true
72
+ }
73
+ },
74
+ "devDependencies": {
75
+ "@playwright/test": "^1.61.1",
76
+ "esbuild": "^0.27.0"
77
+ }
78
+ }
package/src/index.css ADDED
@@ -0,0 +1,21 @@
1
+ /* @profpowell/vb-design-system — component styles (light DOM). */
2
+ @import "./web-components/color-palette/styles.css";
3
+ @import "./web-components/palette-generator/styles.css";
4
+ @import "./web-components/type-specimen/styles.css";
5
+ @import "./web-components/spacing-specimen/styles.css";
6
+ @import "./web-components/token-specimen/styles.css";
7
+ @import "./web-components/component-sampler/styles.css";
8
+ @import "./web-components/semantic-palette/styles.css";
9
+ @import "./web-components/motion-specimen/styles.css";
10
+ @import "./web-components/accessibility-specimen/styles.css";
11
+ @import "./web-components/breakpoint-specimen/styles.css";
12
+ @import "./web-components/layout-specimen/styles.css";
13
+ @import "./web-components/font-pairer/styles.css";
14
+ @import "./web-components/gradient-builder/styles.css";
15
+ @import "./web-components/brand-specimen/styles.css";
16
+ @import "./web-components/icon-set/styles.css";
17
+ @import "./web-components/icon-specimen/styles.css";
18
+
19
+ /* design-system authoring patterns */
20
+ @import "./patterns/do-dont.css";
21
+ @import "./patterns/token-table.css";
package/src/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @profpowell/vb-design-system — barrel.
3
+ * Side-effect imports register every design-system component.
4
+ * Consumes Vanilla Breeze design tokens/themes via CSS custom properties.
5
+ */
6
+ import './web-components/color-palette/logic.js';
7
+ import './web-components/palette-generator/logic.js';
8
+ import './web-components/type-specimen/logic.js';
9
+ import './web-components/spacing-specimen/logic.js';
10
+ import './web-components/token-specimen/logic.js';
11
+ import './web-components/component-sampler/logic.js';
12
+ import './web-components/semantic-palette/logic.js';
13
+ import './web-components/motion-specimen/logic.js';
14
+ import './web-components/theme-export/logic.js';
15
+ import './web-components/accessibility-specimen/logic.js';
16
+ import './web-components/breakpoint-specimen/logic.js';
17
+ import './web-components/layout-specimen/logic.js';
18
+ import './web-components/font-pairer/logic.js';
19
+ import './web-components/gradient-builder/logic.js';
20
+ import './web-components/theme-import/logic.js';
21
+ import './web-components/theme-catalog/logic.js';
22
+ import './web-components/brand-specimen/logic.js';
23
+ import './web-components/icon-set/logic.js';
24
+ import './web-components/icon-specimen/logic.js';
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Bundle Registry — Vanilla Breeze
3
+ *
4
+ * Provides infrastructure for modular bundles to register effects,
5
+ * components, and activate full bundles at runtime.
6
+ */
7
+
8
+ // ─── Effect registry ─────────────────────────────────────────────────────────
9
+
10
+ const effects = new Map()
11
+ let observer = null
12
+ const reducedMotionMq = window.matchMedia('(prefers-reduced-motion: reduce)')
13
+
14
+ function startObserver() {
15
+ if (observer) return
16
+ observer = new MutationObserver(mutations => {
17
+ for (const mutation of mutations) {
18
+ for (const node of mutation.addedNodes) {
19
+ if (node.nodeType !== Node.ELEMENT_NODE) continue
20
+ const el = /** @type {Element} */ (node)
21
+ matchEffects(el)
22
+ el.querySelectorAll('*').forEach(matchEffects)
23
+ }
24
+ for (const node of mutation.removedNodes) {
25
+ if (node.nodeType !== Node.ELEMENT_NODE) continue
26
+ const el = /** @type {Element} */ (node)
27
+ unmatchEffects(el)
28
+ el.querySelectorAll('*').forEach(unmatchEffects)
29
+ }
30
+ }
31
+ })
32
+ observer.observe(document.body, { childList: true, subtree: true })
33
+ }
34
+
35
+ function matchEffects(el) {
36
+ for (const [, def] of effects) {
37
+ if (el.matches?.(def.selector)) {
38
+ if (reducedMotionMq.matches && def.reducedMotionFallback) {
39
+ def.reducedMotionFallback(el)
40
+ } else {
41
+ def.init(el)
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ function unmatchEffects(el) {
48
+ for (const [, def] of effects) {
49
+ if (el.matches?.(def.selector) && def.destroy) {
50
+ def.destroy(el)
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Register a DOM effect that auto-initializes on matching elements.
57
+ *
58
+ * @param {string} name - Unique effect name
59
+ * @param {{ selector: string, init: (el: Element) => void, destroy?: (el: Element) => void, reducedMotionFallback?: (el: Element) => void }} def
60
+ */
61
+ export function registerEffect(name, def) {
62
+ effects.set(name, def)
63
+
64
+ // Initialize on existing matching elements
65
+ document.querySelectorAll(def.selector).forEach(el => {
66
+ if (reducedMotionMq.matches && def.reducedMotionFallback) {
67
+ def.reducedMotionFallback(el)
68
+ } else {
69
+ def.init(el)
70
+ }
71
+ })
72
+
73
+ // Start shared observer lazily
74
+ if (document.body) {
75
+ startObserver()
76
+ } else {
77
+ document.addEventListener('DOMContentLoaded', startObserver, { once: true })
78
+ }
79
+ }
80
+
81
+ // ─── Component registry ──────────────────────────────────────────────────────
82
+
83
+ const components = new Map()
84
+
85
+ /**
86
+ * Register a custom element with priority-based conflict resolution.
87
+ * First-wins at equal priority. Higher priority wins over lower.
88
+ *
89
+ * @param {string} tag - Custom element tag name
90
+ * @param {typeof HTMLElement} impl - The element class
91
+ * @param {{ bundle?: string, contract?: string, priority?: number }} [opts]
92
+ */
93
+ export function registerComponent(tag, impl, opts = {}) {
94
+ const priority = opts.priority ?? 10
95
+ const meta = { impl, bundle: opts.bundle, contract: opts.contract, priority }
96
+
97
+ const existing = components.get(tag)
98
+
99
+ if (customElements.get(tag)) {
100
+ // Already defined in the browser — cannot redefine
101
+ if (!existing || existing.priority >= priority) {
102
+ if (existing && existing.priority === priority && existing.impl !== impl) {
103
+ console.warn(
104
+ `[VB Bundle] Tag <${tag}> already registered by "${existing.bundle}" (priority ${existing.priority}). Skipping "${opts.bundle}".`
105
+ )
106
+ }
107
+ return
108
+ }
109
+ // Higher priority but can't redefine — warn
110
+ console.warn(
111
+ `[VB Bundle] Tag <${tag}> defined by "${existing.bundle}" cannot be replaced (customElements.define is permanent). "${opts.bundle}" has higher priority but arrived late.`
112
+ )
113
+ return
114
+ }
115
+
116
+ if (existing && existing.priority >= priority) {
117
+ if (existing.priority === priority) {
118
+ console.warn(
119
+ `[VB Bundle] Tag <${tag}> already registered by "${existing.bundle}". Skipping "${opts.bundle}" (first wins at equal priority).`
120
+ )
121
+ }
122
+ return
123
+ }
124
+
125
+ components.set(tag, meta)
126
+ customElements.define(tag, impl)
127
+ }
128
+
129
+ /**
130
+ * Activate a full pack by loading its CSS and JS from the CDN path.
131
+ * Convention: cdn/packs/{name}.full.css and cdn/packs/{name}.full.js
132
+ *
133
+ * @param {string} bundleName
134
+ * @param {{ basePath?: string }} [opts]
135
+ * @returns {Promise<void>}
136
+ */
137
+ export async function activateBundle(bundleName, opts = {}) {
138
+ const base = opts.basePath ?? '/cdn/packs'
139
+
140
+ // Load CSS
141
+ const cssHref = `${base}/${bundleName}.full.css`
142
+ if (!document.querySelector(`link[href="${cssHref}"]`)) {
143
+ const link = document.createElement('link')
144
+ link.rel = 'stylesheet'
145
+ link.href = cssHref
146
+ await new Promise((resolve, reject) => {
147
+ link.onload = resolve
148
+ link.onerror = () => reject(new Error(`Failed to load bundle CSS: ${cssHref}`))
149
+ document.head.appendChild(link)
150
+ })
151
+ }
152
+
153
+ // Load JS
154
+ const jsSrc = `${base}/${bundleName}.full.js`
155
+ await import(jsSrc)
156
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * VBElement — Minimal base class for Vanilla Breeze web components
3
+ *
4
+ * Provides:
5
+ * - data-upgraded guard (prevents double initialization on reconnect)
6
+ * - listen() method with automatic cleanup on disconnect
7
+ * - setup()/teardown() lifecycle hooks
8
+ *
9
+ * Does NOT provide: props reflection, template rendering, reactivity.
10
+ * Components that need observedAttributes/attributeChangedCallback
11
+ * declare them normally alongside setup()/teardown().
12
+ */
13
+ class VBElement extends HTMLElement {
14
+ #cleanups = [];
15
+ /** @type {ElementInternals | undefined} */
16
+ #internals;
17
+
18
+ connectedCallback() {
19
+ if (this.hasAttribute('data-upgraded')) return;
20
+ if (this.setup() === false) return;
21
+ this.setAttribute('data-upgraded', '');
22
+ // Dispatch :upgraded in a microtask so any sibling component definitions
23
+ // queued in the same synchronous script (e.g. a pack's registerComponent
24
+ // calls) complete before consumers react. Without this, listeners that
25
+ // immediately assign .items can hit a race where downstream components
26
+ // (work-item, etc.) aren't defined yet and the default renderer falls
27
+ // back to a plain element.
28
+ queueMicrotask(() => {
29
+ this.dispatchEvent(new CustomEvent(`${this.localName}:upgraded`, { bubbles: true }));
30
+ });
31
+ }
32
+
33
+ disconnectedCallback() {
34
+ for (const fn of this.#cleanups) fn();
35
+ this.#cleanups = [];
36
+ this.removeAttribute('data-upgraded');
37
+ this.teardown();
38
+ }
39
+
40
+ /**
41
+ * Track an event listener for automatic cleanup on disconnect.
42
+ * @param {EventTarget} target
43
+ * @param {string} event
44
+ * @param {EventListenerOrEventListenerObject} handler
45
+ * @param {AddEventListenerOptions} [opts]
46
+ */
47
+ listen(target, event, handler, opts) {
48
+ target.addEventListener(event, handler, opts);
49
+ this.#cleanups.push(() => target.removeEventListener(event, handler, opts));
50
+ }
51
+
52
+ /**
53
+ * Override in subclass. Return false to abort upgrade.
54
+ * @returns {boolean | void}
55
+ */
56
+ setup() {}
57
+
58
+ /** Override in subclass for cleanup beyond event listeners. */
59
+ teardown() {}
60
+
61
+ /**
62
+ * Toggle a CustomStateSet entry targetable via the `:state(name)` CSS selector.
63
+ * Use for component-private flags. For author-facing state, keep using
64
+ * data-* / aria-* attributes — see admin/specs/custom-state-set-research.md.
65
+ *
66
+ * Lazily attaches ElementInternals on first call; subclasses that already
67
+ * attached internals (form-associated components) must hand them over via
68
+ * `_adoptInternals(this.attachInternals())` in their constructor to avoid
69
+ * the double-attach throw.
70
+ *
71
+ * @param {string} name
72
+ * @param {boolean} on
73
+ */
74
+ setState(name, on) {
75
+ if (!this.#internals) this.#internals = this.attachInternals();
76
+ const states = this.#internals.states;
77
+ try {
78
+ if (on) states.add(name); else states.delete(name);
79
+ } catch {
80
+ // Legacy --name syntax for older Chromium/WebKit releases
81
+ const legacy = `--${name}`;
82
+ if (on) states.add(legacy); else states.delete(legacy);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Hand pre-attached ElementInternals to the base class. Form-associated
88
+ * subclasses call this in their constructor right after attachInternals().
89
+ * @param {ElementInternals} internals
90
+ */
91
+ _adoptInternals(internals) {
92
+ if (!this.#internals) this.#internals = internals;
93
+ }
94
+ }
95
+
96
+ export { VBElement };
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Do/Don't and Pro/Con list patterns
3
+ *
4
+ * Usage:
5
+ * <ul data-list="do-dont">
6
+ * <li data-do>Use the full logo on light backgrounds.</li>
7
+ * <li data-dont>Don't stretch or rotate the logo.</li>
8
+ * </ul>
9
+ *
10
+ * <ul data-list="pro-con">
11
+ * <li data-pro>Fast initial load time.</li>
12
+ * <li data-con>Requires JavaScript for interactivity.</li>
13
+ * </ul>
14
+ */
15
+
16
+ [data-list="do-dont"],
17
+ [data-list="pro-con"] {
18
+ list-style: none;
19
+ padding-inline-start: 0;
20
+ display: grid;
21
+ grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
22
+ gap: var(--size-s, 0.5rem);
23
+ }
24
+
25
+ /* Do / Pro items */
26
+ [data-list] > [data-do],
27
+ [data-list] > [data-pro] {
28
+ padding: var(--size-s, 0.5rem) var(--size-m, 1rem);
29
+ border-inline-start: 4px solid var(--color-success, oklch(55% 0.2 145));
30
+ background: var(--color-success-subtle, oklch(95% 0.03 145));
31
+ border-radius: var(--radius-s, 0.25rem);
32
+ }
33
+
34
+ /* Don't / Con items */
35
+ [data-list] > [data-dont],
36
+ [data-list] > [data-con] {
37
+ padding: var(--size-s, 0.5rem) var(--size-m, 1rem);
38
+ border-inline-start: 4px solid var(--color-error, oklch(55% 0.22 25));
39
+ background: var(--color-error-subtle, oklch(95% 0.03 25));
40
+ border-radius: var(--radius-s, 0.25rem);
41
+ }
42
+
43
+ /* Labels via ::before */
44
+ [data-list="do-dont"] > [data-do]::before {
45
+ content: "Do";
46
+ display: block;
47
+ font-weight: 700;
48
+ font-size: var(--font-size-xs, 0.75rem);
49
+ color: var(--color-success, oklch(45% 0.2 145));
50
+ margin-block-end: var(--size-2xs, 0.25rem);
51
+ text-transform: uppercase;
52
+ letter-spacing: 0.05em;
53
+ }
54
+
55
+ [data-list="do-dont"] > [data-dont]::before {
56
+ content: "Don\2019t";
57
+ display: block;
58
+ font-weight: 700;
59
+ font-size: var(--font-size-xs, 0.75rem);
60
+ color: var(--color-error, oklch(45% 0.22 25));
61
+ margin-block-end: var(--size-2xs, 0.25rem);
62
+ text-transform: uppercase;
63
+ letter-spacing: 0.05em;
64
+ }
65
+
66
+ [data-list="pro-con"] > [data-pro]::before {
67
+ content: "Pro";
68
+ display: block;
69
+ font-weight: 700;
70
+ font-size: var(--font-size-xs, 0.75rem);
71
+ color: var(--color-success, oklch(45% 0.2 145));
72
+ margin-block-end: var(--size-2xs, 0.25rem);
73
+ text-transform: uppercase;
74
+ letter-spacing: 0.05em;
75
+ }
76
+
77
+ [data-list="pro-con"] > [data-con]::before {
78
+ content: "Con";
79
+ display: block;
80
+ font-weight: 700;
81
+ font-size: var(--font-size-xs, 0.75rem);
82
+ color: var(--color-error, oklch(45% 0.22 25));
83
+ margin-block-end: var(--size-2xs, 0.25rem);
84
+ text-transform: uppercase;
85
+ letter-spacing: 0.05em;
86
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Design System Token Table
3
+ *
4
+ * Usage:
5
+ * <table class="ds-token-table">
6
+ * <thead><tr><th>Token</th><th>Preview</th><th>Value</th></tr></thead>
7
+ * <tbody>
8
+ * <tr>
9
+ * <td><code>--color-primary</code></td>
10
+ * <td><token-swatch data-preview="var(--color-primary)"></token-swatch></td>
11
+ * <td>oklch(50% 0.2 260)</td>
12
+ * </tr>
13
+ * </tbody>
14
+ * </table>
15
+ */
16
+
17
+ .ds-token-table {
18
+ width: 100%;
19
+ border-collapse: collapse;
20
+ font-size: var(--font-size-s, 0.875rem);
21
+ }
22
+
23
+ .ds-token-table thead {
24
+ border-block-end: 2px solid var(--color-border, #ddd);
25
+ }
26
+
27
+ .ds-token-table th {
28
+ text-align: start;
29
+ padding: var(--size-xs, 0.25rem) var(--size-s, 0.5rem);
30
+ font-size: var(--font-size-xs, 0.75rem);
31
+ font-weight: 700;
32
+ text-transform: uppercase;
33
+ letter-spacing: 0.05em;
34
+ color: var(--color-text-muted, #666);
35
+ }
36
+
37
+ .ds-token-table td {
38
+ padding: var(--size-xs, 0.25rem) var(--size-s, 0.5rem);
39
+ border-block-end: 1px solid var(--color-border, #eee);
40
+ vertical-align: middle;
41
+ }
42
+
43
+ .ds-token-table code {
44
+ font-family: var(--font-mono, monospace);
45
+ font-size: var(--font-size-xs, 0.75rem);
46
+ }
47
+
48
+ /* Inline swatch preview in table cells */
49
+ .ds-token-table .ds-swatch {
50
+ display: inline-block;
51
+ width: 2.5rem;
52
+ height: 1.5rem;
53
+ border-radius: var(--radius-s, 0.25rem);
54
+ border: 1px solid var(--color-border, #ddd);
55
+ vertical-align: middle;
56
+ }
57
+
58
+ /* Also support token-swatch with proper child markup */
59
+ .ds-token-table token-swatch {
60
+ display: inline-flex;
61
+ }
62
+ .ds-token-table token-swatch > [data-preview] {
63
+ width: 2.5rem;
64
+ height: 1.5rem;
65
+ border-radius: var(--radius-s, 0.25rem);
66
+ border: 1px solid var(--color-border, #ddd);
67
+ }