diff --git a/demo/src/main.ts b/demo/src/main.ts
index 5f2fdb0..3ece1bf 100644
--- a/demo/src/main.ts
+++ b/demo/src/main.ts
@@ -3,6 +3,7 @@ import '@ivy-interactive/ivy-design-system/css/ivy-framework-light'
import '@ivy-interactive/ivy-design-system/css/ivy-framework-dark'
import '@ivy-interactive/ivy-design-system/css/ivy-framework-chromatic'
import '@ivy-interactive/ivy-design-system/css/ivy-framework-neutral'
+import '@ivy-interactive/ivy-design-system/css/ivy-framework-shadow'
import tokens from '@ivy-interactive/ivy-design-system/tokens'
import './style.css'
@@ -290,6 +291,41 @@ function createExamples(): HTMLElement {
return section
}
+function createShadowExamples(): HTMLElement {
+ const section = document.createElement('section')
+ section.className = 'color-section shadow-section'
+ section.innerHTML = `
+
Box Shadow Tokens
+
+
+ sm
+ var(--shadow-sm)
+
+
+ md
+ var(--shadow-md)
+
+
+ lg
+ var(--shadow-lg)
+
+
+ xl
+ var(--shadow-xl)
+
+
+ 2xl
+ var(--shadow-2xl)
+
+
+ inner
+ var(--shadow-inner)
+
+
+ `
+ return section
+}
+
function init(): void {
const app = document.getElementById('app')
if (!app) return
@@ -341,6 +377,7 @@ function init(): void {
}
app.appendChild(createExamples())
+ app.appendChild(createShadowExamples())
if (ivyFramework.chromatic?.color) {
app.appendChild(createSection('Chromatic Colors', ivyFramework.chromatic.color))
diff --git a/demo/src/style.css b/demo/src/style.css
index 3971941..c0a3229 100644
--- a/demo/src/style.css
+++ b/demo/src/style.css
@@ -515,3 +515,34 @@ header code {
background-color: var(--color-primary);
}
+/* Shadow tokens */
+.shadow-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 2rem;
+ margin-top: 1rem;
+}
+
+.shadow-card {
+ background: var(--color-background);
+ border-radius: 8px;
+ padding: 2rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.5rem;
+ min-height: 120px;
+ justify-content: center;
+}
+
+.shadow-label {
+ font-weight: 600;
+ font-size: 1.125rem;
+ color: var(--color-foreground);
+}
+
+.shadow-card code {
+ font-size: 0.875rem;
+ color: var(--color-muted-foreground);
+}
+
diff --git a/figma-tokens/$tokens.json b/figma-tokens/$tokens.json
index 5696196..5825dec 100644
--- a/figma-tokens/$tokens.json
+++ b/figma-tokens/$tokens.json
@@ -728,6 +728,38 @@
"type": "spacing"
}
}
+ },
+ "shadow": {
+ "shadow": {
+ "none": {
+ "value": "none",
+ "type": "boxShadow"
+ },
+ "sm": {
+ "value": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
+ "type": "boxShadow"
+ },
+ "md": {
+ "value": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
+ "type": "boxShadow"
+ },
+ "lg": {
+ "value": "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
+ "type": "boxShadow"
+ },
+ "xl": {
+ "value": "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
+ "type": "boxShadow"
+ },
+ "2xl": {
+ "value": "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
+ "type": "boxShadow"
+ },
+ "inner": {
+ "value": "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)",
+ "type": "boxShadow"
+ }
+ }
}
},
"ivy-web": {
diff --git a/package.json b/package.json
index fb6e510..186eeec 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,8 @@
"./css/ivy-framework-chromatic.css": "./dist/css/ivy-framework-chromatic.css",
"./css/ivy-framework-neutral": "./dist/css/ivy-framework-neutral.css",
"./css/ivy-framework-neutral.css": "./dist/css/ivy-framework-neutral.css",
+ "./css/ivy-framework-shadow": "./dist/css/ivy-framework-shadow.css",
+ "./css/ivy-framework-shadow.css": "./dist/css/ivy-framework-shadow.css",
"./css/ivy-web": "./dist/css/ivy-web-light.css",
"./css/ivy-web-light": "./dist/css/ivy-web-light.css",
"./css/ivy-web-dark": "./dist/css/ivy-web-dark.css",
diff --git a/scripts/build.ts b/scripts/build.ts
index 3f08f57..0e3a81e 100644
--- a/scripts/build.ts
+++ b/scripts/build.ts
@@ -41,6 +41,9 @@ interface PackageTokens {
padding?: {
padding?: ColorTokens;
};
+ shadow?: {
+ shadow?: ColorTokens;
+ };
}
interface NormalizedTokens {
@@ -124,6 +127,7 @@ async function build() {
const ivyFrameworkChromatic = ivyFramework.chromatic || {};
const ivyFrameworkBorderRadius = ivyFramework["border-radius"] || {};
const ivyFrameworkPadding = ivyFramework.padding || {};
+ const ivyFrameworkShadow = ivyFramework.shadow || {};
const ivyFrameworkLightTheme = {
theme: { light: ivyFramework.theme?.light || {} },
};
@@ -184,6 +188,12 @@ async function build() {
false,
ivyFrameworkSource
);
+ await generateCSS(
+ ivyFrameworkShadow,
+ "dist/css/ivy-framework-shadow.css",
+ false,
+ ivyFrameworkSource
+ );
await generateCSS(
ivyFrameworkLightTheme,
"dist/css/ivy-framework-light.css",
@@ -222,6 +232,12 @@ async function build() {
true,
ivyFrameworkSource
);
+ await generateFlatCSS(
+ ivyFrameworkShadow,
+ "dist/css/ivy-framework-shadow-flat.css",
+ false,
+ ivyFrameworkSource
+ );
// Generate CSS for ivy-web
console.log("📝 Generating CSS for ivy-web...");
@@ -309,6 +325,13 @@ async function build() {
"Ivy.Themes",
ivyFrameworkSource
);
+ await generateCSharp(
+ ivyFrameworkShadow,
+ "dist/csharp/IvyFrameworkShadowTokens.cs",
+ "IvyFrameworkShadowTokens",
+ "Ivy.Themes",
+ ivyFrameworkSource
+ );
await generateCSharp(
ivyFrameworkLightTheme,
"dist/csharp/IvyFrameworkLightThemeTokens.cs",
diff --git a/scripts/generate-csharp.ts b/scripts/generate-csharp.ts
index 622092d..38d6188 100644
--- a/scripts/generate-csharp.ts
+++ b/scripts/generate-csharp.ts
@@ -42,7 +42,7 @@ export function extractTokens(
return tokens;
}
- const categories = ["color", "sizing", "border-radius", "padding"];
+ const categories = ["color", "sizing", "border-radius", "padding", "shadow"];
for (const cat of categories) {
if (obj[cat]) {
tokens.push(...extractTokens(obj[cat], "", cat));
@@ -80,7 +80,7 @@ function resolveTokenReference(
value: string,
sourceTokens: Record
): string {
- const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing)\.([\w.-]+)\}$/);
+ const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing|shadow)\.([\w.-]+)\}$/);
if (referenceMatch) {
const category = referenceMatch[2];
const tokenName = referenceMatch[3];
diff --git a/scripts/generate-css.ts b/scripts/generate-css.ts
index 3bcb309..c9a6003 100644
--- a/scripts/generate-css.ts
+++ b/scripts/generate-css.ts
@@ -9,7 +9,7 @@ function resolveTokenReference(
): string {
if (!sourceTokens) return value;
- const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing)\.([\w.-]+)\}$/);
+ const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing|shadow)\.([\w.-]+)\}$/);
if (referenceMatch) {
const category = referenceMatch[2];
const tokenName = referenceMatch[3];
@@ -46,7 +46,7 @@ function tokenToCSS(obj: any, prefix = "", sourceTokens?: Record):
return css;
}
- const categories = ["color", "sizing", "border-radius", "padding"];
+ const categories = ["color", "sizing", "border-radius", "padding", "shadow"];
for (const category of categories) {
if (obj[category]) {
css += tokenToCSS(obj[category], category, sourceTokens);
diff --git a/scripts/generate-flat-css.ts b/scripts/generate-flat-css.ts
index d909e7e..5137e3c 100644
--- a/scripts/generate-flat-css.ts
+++ b/scripts/generate-flat-css.ts
@@ -83,7 +83,7 @@ function resolveTokenReference(
): string {
if (!sourceTokens) return value;
- const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing)\.([\w.-]+)\}$/);
+ const referenceMatch = value.match(/^\{(ivy-framework|ivy-web)\.source\.(color|sizing|shadow)\.([\w.-]+)\}$/);
if (referenceMatch) {
const category = referenceMatch[2];
const tokenName = referenceMatch[3];
@@ -125,7 +125,7 @@ function tokenToFlatCSS(
return css;
}
- const categories = ["color", "sizing", "border-radius", "padding"];
+ const categories = ["color", "sizing", "border-radius", "padding", "shadow"];
for (const category of categories) {
if (obj[category]) {
css += tokenToFlatCSS(obj[category], category, mapping, sourceTokens);