diff design_system/test/storybook_test.js @ 256:30c2196d03d4

[site] Integrate Zenbu themes and components Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 16:49:01 -0700
parents 2b6e732087ff
children
line wrap: on
line diff
--- a/design_system/test/storybook_test.js	Tue Aug 04 15:12:18 2026 -0700
+++ b/design_system/test/storybook_test.js	Tue Aug 04 16:49:01 2026 -0700
@@ -138,6 +138,7 @@
     }
     for (const asset of [
       '/styles/tokens.css',
+      '/styles/themes.css',
       '/styles/components.css',
       '/styles/shadcn.css',
       '/components/index.js',
@@ -480,6 +481,52 @@
         { length: 10 },
         (_, index) => value(`data-${index + 1}`),
       );
+      const themes = ['paper', 'ink', 'playful'].map(theme => {
+        root.dataset.zenTheme = theme;
+        const channels = value => value.match(/\d+(?:\.\d+)?/g)
+          .slice(0, 3)
+          .map(Number);
+        const luminance = value => {
+          const converted = channels(value).map(channel => {
+            const normalized = channel / 255;
+            return normalized <= 0.04045
+              ? normalized / 12.92
+              : ((normalized + 0.055) / 1.055) ** 2.4;
+          });
+          return converted[0] * 0.2126 +
+            converted[1] * 0.7152 +
+            converted[2] * 0.0722;
+        };
+        const contrasts = [
+          'info',
+          'success',
+          'warning',
+          'danger',
+        ].map(tone => {
+          const probe = document.createElement('span');
+          probe.style.background = `var(--zen-color-${tone})`;
+          probe.style.color = `var(--zen-color-on-${tone})`;
+          document.body.append(probe);
+          const probeStyle = getComputedStyle(probe);
+          const foreground = luminance(probeStyle.color);
+          const background = luminance(probeStyle.backgroundColor);
+          const contrast = (Math.max(foreground, background) + 0.05) /
+            (Math.min(foreground, background) + 0.05);
+          probe.remove();
+          return contrast;
+        });
+        return {
+          canvas: value('canvas'),
+          contrast: Math.min(...contrasts),
+          font: getComputedStyle(root)
+            .getPropertyValue('--zen-font-sans')
+            .trim(),
+          name: theme,
+          radius: getComputedStyle(root)
+            .getPropertyValue('--zen-radius-lg')
+            .trim(),
+        };
+      });
       delete root.dataset.zenTheme;
       return {
         darkData,
@@ -488,6 +535,7 @@
         lightMuted,
         materials,
         rampsComplete,
+        themes,
       };
     });
     assert.equal(colorTokenState.rampsComplete, true);
@@ -495,6 +543,18 @@
     assert.equal(new Set(colorTokenState.data).size, 10);
     assert.equal(new Set(colorTokenState.darkData).size, 10);
     assert.notDeepEqual(colorTokenState.data, colorTokenState.darkData);
+    assert.equal(
+      new Set(colorTokenState.themes.map(theme => theme.canvas)).size,
+      3,
+    );
+    assert.notEqual(
+      colorTokenState.themes.find(theme => theme.name === 'paper').radius,
+      colorTokenState.themes.find(theme => theme.name === 'playful').radius,
+    );
+    assert.ok(
+      colorTokenState.themes.every(theme => theme.contrast >= 4.5),
+      JSON.stringify(colorTokenState.themes),
+    );
     assert.notEqual(
       colorTokenState.lightMuted,
       colorTokenState.darkMuted,