@velora-cms/design-tokens 0.9.1 → 0.10.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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The complete tokens.css text: :root variables, one [data-theme] block
3
+ * per built-in theme that has overrides (the exact mechanism a
4
+ * third-party theme plugin uses at runtime), and the language-conditional
5
+ * sans-stack swap for Arabic. Pure — generate.ts writes it to disk.
6
+ */
7
+ export declare function buildTokensCss(): string;
8
+ export declare function countVariables(): number;
@@ -0,0 +1,48 @@
1
+ import { tokens, ARABIC_SANS_FONT_FAMILY } from './tokens.js';
2
+ import { themes } from './themes/index.js';
3
+ import { flatten, themeOverridesToCss } from './theme-css.js';
4
+ /**
5
+ * The typography group flattens without its section prefix so variables
6
+ * read --font-size-base, not --typography-font-size-base. Everything
7
+ * else keeps its section name (--color-primary-500, --spacing-4, ...).
8
+ */
9
+ function rootVariables() {
10
+ const { typography, ...rest } = tokens;
11
+ const variables = {};
12
+ flatten({ ...rest, ...typography }, [], variables);
13
+ return variables;
14
+ }
15
+ /**
16
+ * The complete tokens.css text: :root variables, one [data-theme] block
17
+ * per built-in theme that has overrides (the exact mechanism a
18
+ * third-party theme plugin uses at runtime), and the language-conditional
19
+ * sans-stack swap for Arabic. Pure — generate.ts writes it to disk.
20
+ */
21
+ export function buildTokensCss() {
22
+ const variables = rootVariables();
23
+ const rootBlock = [
24
+ ':root {',
25
+ ...Object.entries(variables).map(([name, value]) => ` ${name}: ${value};`),
26
+ '}',
27
+ ].join('\n');
28
+ // Light has no overrides (it IS the :root default) so it emits no block —
29
+ // a property of Light's token set, not a special case in this loop.
30
+ const themeBlocks = themes
31
+ .map((theme) => themeOverridesToCss(theme.id, theme.contributions.themeTokens))
32
+ .filter(Boolean);
33
+ const arabicBlock = [
34
+ '/* Arabic locales lead with Plex Sans Arabic — same token, language-conditional value. */',
35
+ '[lang="ar"], [lang^="ar-"] {',
36
+ ` --font-family-sans: ${ARABIC_SANS_FONT_FAMILY};`,
37
+ '}',
38
+ ].join('\n');
39
+ return ([
40
+ '/* Generated by @velora-cms/design-tokens — do not edit by hand. */',
41
+ rootBlock,
42
+ ...themeBlocks,
43
+ arabicBlock,
44
+ ].join('\n\n') + '\n');
45
+ }
46
+ export function countVariables() {
47
+ return Object.keys(rootVariables()).length;
48
+ }
package/dist/generate.js CHANGED
@@ -1,34 +1,15 @@
1
1
  /**
2
2
  * Build-time generator: emits tokens.css (CSS custom properties on
3
- * :root) and tokens.json (for theme plugin authors) next to the
4
- * compiled output. Run via `node dist/generate.js` after tsc.
3
+ * :root + theme blocks) and tokens.json (for theme plugin authors) next
4
+ * to the compiled output. Run via `node dist/generate.js` after tsc.
5
+ * The CSS text itself comes from build-css.ts so it can be unit-tested.
5
6
  */
6
7
  import { writeFile } from 'node:fs/promises';
7
8
  import { dirname, join } from 'node:path';
8
9
  import { fileURLToPath } from 'node:url';
10
+ import { buildTokensCss, countVariables } from './build-css.js';
9
11
  import { tokens } from './tokens.js';
10
- import { themes } from './themes/index.js';
11
- import { flatten, themeOverridesToCss } from './theme-css.js';
12
- // The typography group flattens without its section prefix so variables
13
- // read --font-size-base, not --typography-font-size-base. Everything
14
- // else keeps its section name (--color-primary-500, --spacing-4, ...).
15
- const { typography, ...rest } = tokens;
16
- const cssTree = { ...rest, ...typography };
17
- const variables = {};
18
- flatten(cssTree, [], variables);
19
- // Each theme with overrides gets its own [data-theme="id"] block —
20
- // the same mechanism a third-party theme plugin will use. Light has
21
- // no overrides (it IS the :root default) so it emits no block; that's
22
- // a property of Light's token set, not a special case in this loop.
23
- const themeBlocks = themes
24
- .map((theme) => themeOverridesToCss(theme.id, theme.contributions.themeTokens))
25
- .filter(Boolean);
26
- const css = [
27
- '/* Generated by @velora-cms/design-tokens — do not edit by hand. */',
28
- [':root {', ...Object.entries(variables).map(([name, value]) => ` ${name}: ${value};`), '}'].join('\n'),
29
- ...themeBlocks,
30
- ].join('\n\n') + '\n';
31
12
  const outDir = dirname(fileURLToPath(import.meta.url));
32
- await writeFile(join(outDir, 'tokens.css'), css, 'utf8');
13
+ await writeFile(join(outDir, 'tokens.css'), buildTokensCss(), 'utf8');
33
14
  await writeFile(join(outDir, 'tokens.json'), JSON.stringify(tokens, null, 2) + '\n', 'utf8');
34
- console.log(`Generated tokens.css (${Object.keys(variables).length} variables) and tokens.json`);
15
+ console.log(`Generated tokens.css (${countVariables()} variables) and tokens.json`);
@@ -9,19 +9,20 @@ export declare const tailwindTheme: {
9
9
  warning: Record<import("./types.js").ColorScaleStep, string>;
10
10
  danger: Record<import("./types.js").ColorScaleStep, string>;
11
11
  neutral: Record<import("./types.js").ColorScaleStep, string>;
12
- background: Record<"base" | "elevated" | "overlay" | "hover", string>;
13
- text: Record<"primary" | "secondary" | "disabled" | "inverse", string>;
14
- border: Record<"default" | "subtle" | "strong", string>;
12
+ background: Record<"base" | "elevated" | "subtle" | "overlay" | "hover", string>;
13
+ text: Record<"primary" | "secondary" | "tertiary" | "disabled" | "inverse", string>;
14
+ border: Record<"subtle" | "default" | "strong", string>;
15
15
  };
16
16
  fontFamily: {
17
17
  sans: string;
18
+ serif: string;
18
19
  mono: string;
19
20
  };
20
- fontSize: Record<"xs" | "sm" | "base" | "lg" | "xl", string>;
21
+ fontSize: Record<"xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl", string>;
21
22
  fontWeight: Record<"normal" | "medium" | "semibold" | "bold", string>;
22
23
  lineHeight: Record<"normal" | "tight" | "relaxed", string>;
23
24
  spacing: Record<import("./types.js").SpacingStep, string>;
24
- borderRadius: Record<"sm" | "lg" | "none" | "md" | "full", string>;
25
+ borderRadius: Record<"sm" | "lg" | "xl" | "none" | "md" | "full", string>;
25
26
  boxShadow: Record<"sm" | "lg" | "xl" | "md", string>;
26
27
  transitionDuration: Record<string, string>;
27
28
  transitionTimingFunction: Record<string, string>;
@@ -36,6 +36,7 @@ export const tailwindTheme = {
36
36
  },
37
37
  fontFamily: {
38
38
  sans: 'var(--font-family-sans)',
39
+ serif: 'var(--font-family-serif)',
39
40
  mono: 'var(--font-family-mono)',
40
41
  },
41
42
  fontSize: scaleRefs(tokens.typography.fontSize, 'font-size'),
@@ -1,12 +1,13 @@
1
1
  import type { BuiltInTheme } from '../theme-types.js';
2
2
  /**
3
- * Dark theme overrides. Every value here is drawn from tokens the base
4
- * set already declares — no new colors invented outside the
5
- * VeloraDesignTokens shape. The background/text/border remaps make
6
- * #0F1117 (the brand dark bg reserved for this theme since Session 25)
7
- * and #F3F4F6 text actually apply; primary/secondary swap in the
8
- * lighter tint their own scale already defines (400/500) so accents
9
- * stay legible against the dark background, with the hover shade
10
- * shifting to what was the light theme's base shade.
3
+ * Dark theme overrides (S177/S178): warm charcoal, not GitHub-black. The
4
+ * light blue (#7CC0E8) becomes the ACTION colour itself — primary-600 is
5
+ * remapped to it, and text.inverse flips to near-black so `bg-primary-600
6
+ * text-text-inverse` (every primary button) stays legible without any
7
+ * component knowing which theme is active. Status scales remap the steps
8
+ * components use accordingly (100 fill, 600, and the AA text step — 700
9
+ * for success/danger, 800 for warning). Colour only — the
10
+ * Theme System contract keeps typography/spacing/shadow/motion in the
11
+ * base set.
11
12
  */
12
13
  export declare const darkTheme: BuiltInTheme;
@@ -1,12 +1,13 @@
1
1
  /**
2
- * Dark theme overrides. Every value here is drawn from tokens the base
3
- * set already declares — no new colors invented outside the
4
- * VeloraDesignTokens shape. The background/text/border remaps make
5
- * #0F1117 (the brand dark bg reserved for this theme since Session 25)
6
- * and #F3F4F6 text actually apply; primary/secondary swap in the
7
- * lighter tint their own scale already defines (400/500) so accents
8
- * stay legible against the dark background, with the hover shade
9
- * shifting to what was the light theme's base shade.
2
+ * Dark theme overrides (S177/S178): warm charcoal, not GitHub-black. The
3
+ * light blue (#7CC0E8) becomes the ACTION colour itself — primary-600 is
4
+ * remapped to it, and text.inverse flips to near-black so `bg-primary-600
5
+ * text-text-inverse` (every primary button) stays legible without any
6
+ * component knowing which theme is active. Status scales remap the steps
7
+ * components use accordingly (100 fill, 600, and the AA text step — 700
8
+ * for success/danger, 800 for warning). Colour only — the
9
+ * Theme System contract keeps typography/spacing/shadow/motion in the
10
+ * base set.
10
11
  */
11
12
  export const darkTheme = {
12
13
  id: 'dark',
@@ -16,25 +17,50 @@ export const darkTheme = {
16
17
  themeTokens: {
17
18
  color: {
18
19
  background: {
19
- base: '#0F1117',
20
- elevated: '#171923',
20
+ base: '#1A1C1B',
21
+ elevated: '#232625',
22
+ subtle: '#1F2221',
21
23
  overlay: 'rgba(0, 0, 0, 0.6)',
22
- // one step lighter than elevated (neutral.800) — the missing dark
23
- // remap behind the Session 41 outline-hover bug
24
- hover: '#1F2937',
24
+ hover: '#2C302E',
25
25
  },
26
26
  text: {
27
- primary: '#F3F4F6',
28
- secondary: '#9CA3AF',
29
- disabled: '#4B5563',
27
+ primary: '#ECEAE3',
28
+ secondary: '#A3A8A6',
29
+ tertiary: '#969C99',
30
+ disabled: '#6F7573',
31
+ inverse: '#14181B',
30
32
  },
31
33
  border: {
32
- default: '#1F2937',
33
- subtle: '#171923',
34
- strong: '#374151',
34
+ default: '#33373A',
35
+ subtle: '#2C302E',
36
+ strong: '#444A4D',
37
+ },
38
+ primary: {
39
+ '50': '#1D2A34',
40
+ '100': '#22364A',
41
+ '200': '#2A4A66',
42
+ '300': '#7CC0E8',
43
+ '600': '#7CC0E8',
44
+ '700': '#9AD0EE',
45
+ '800': '#BFE1F5',
46
+ },
47
+ secondary: { '100': '#2A2C46', '500': '#9A9DE3', '600': '#9A9DE3' },
48
+ success: { '100': '#223A1E', '600': '#7FC46E', '700': '#8FD07F' },
49
+ warning: { '100': '#3D3016', '600': '#E0AA4B', '800': '#EABB6A' },
50
+ danger: { '100': '#45201D', '600': '#E8776E', '700': '#F0918A' },
51
+ neutral: {
52
+ '50': '#1F2221',
53
+ '100': '#232625',
54
+ '200': '#2C302E',
55
+ '300': '#33373A',
56
+ '400': '#444A4D',
57
+ '500': '#6F7573',
58
+ '600': '#A3A8A6',
59
+ '700': '#C5C9C6',
60
+ '800': '#DAD9D3',
61
+ '900': '#ECEAE3',
62
+ '950': '#F5F4F0',
35
63
  },
36
- primary: { '500': '#818CF8', '600': '#6366F1' },
37
- secondary: { '500': '#A78BFA', '600': '#8B5CF6' },
38
64
  },
39
65
  },
40
66
  },
package/dist/tokens.css CHANGED
@@ -1,83 +1,85 @@
1
1
  /* Generated by @velora-cms/design-tokens — do not edit by hand. */
2
2
 
3
3
  :root {
4
- --color-primary-50: #EEF2FF;
5
- --color-primary-100: #E0E7FF;
6
- --color-primary-200: #C7D2FE;
7
- --color-primary-300: #A5B4FC;
8
- --color-primary-400: #818CF8;
9
- --color-primary-500: #6366F1;
10
- --color-primary-600: #4F46E5;
11
- --color-primary-700: #4338CA;
12
- --color-primary-800: #3730A3;
13
- --color-primary-900: #312E81;
14
- --color-primary-950: #1E1B4B;
15
- --color-secondary-50: #F5F3FF;
16
- --color-secondary-100: #EDE9FE;
17
- --color-secondary-200: #DDD6FE;
18
- --color-secondary-300: #C4B5FD;
19
- --color-secondary-400: #A78BFA;
20
- --color-secondary-500: #8B5CF6;
21
- --color-secondary-600: #7C3AED;
22
- --color-secondary-700: #6D28D9;
23
- --color-secondary-800: #5B21B6;
24
- --color-secondary-900: #4C1D95;
25
- --color-secondary-950: #2E1065;
26
- --color-success-50: #ECFDF5;
27
- --color-success-100: #D1FAE5;
28
- --color-success-200: #A7F3D0;
29
- --color-success-300: #6EE7B7;
30
- --color-success-400: #34D399;
31
- --color-success-500: #10B981;
32
- --color-success-600: #059669;
33
- --color-success-700: #047857;
34
- --color-success-800: #065F46;
35
- --color-success-900: #064E3B;
36
- --color-success-950: #022C22;
37
- --color-warning-50: #FFFBEB;
38
- --color-warning-100: #FEF3C7;
39
- --color-warning-200: #FDE68A;
40
- --color-warning-300: #FCD34D;
41
- --color-warning-400: #FBBF24;
42
- --color-warning-500: #F59E0B;
43
- --color-warning-600: #D97706;
44
- --color-warning-700: #B45309;
45
- --color-warning-800: #92400E;
46
- --color-warning-900: #78350F;
47
- --color-warning-950: #451A03;
48
- --color-danger-50: #FEF2F2;
49
- --color-danger-100: #FEE2E2;
50
- --color-danger-200: #FECACA;
51
- --color-danger-300: #FCA5A5;
52
- --color-danger-400: #F87171;
53
- --color-danger-500: #EF4444;
54
- --color-danger-600: #DC2626;
55
- --color-danger-700: #B91C1C;
56
- --color-danger-800: #991B1B;
57
- --color-danger-900: #7F1D1D;
58
- --color-danger-950: #450A0A;
59
- --color-neutral-50: #F9FAFB;
60
- --color-neutral-100: #F3F4F6;
61
- --color-neutral-200: #E5E7EB;
62
- --color-neutral-300: #D1D5DB;
63
- --color-neutral-400: #9CA3AF;
64
- --color-neutral-500: #6B7280;
65
- --color-neutral-600: #4B5563;
66
- --color-neutral-700: #374151;
67
- --color-neutral-800: #1F2937;
68
- --color-neutral-900: #111827;
69
- --color-neutral-950: #030712;
70
- --color-background-base: #F9FAFB;
4
+ --color-primary-50: #EAF4FB;
5
+ --color-primary-100: #CFE6F6;
6
+ --color-primary-200: #A9D5F0;
7
+ --color-primary-300: #7CC0E8;
8
+ --color-primary-400: #4E9CCB;
9
+ --color-primary-500: #2A82BC;
10
+ --color-primary-600: #1F6FA8;
11
+ --color-primary-700: #1A5E8F;
12
+ --color-primary-800: #154D75;
13
+ --color-primary-900: #113D5C;
14
+ --color-primary-950: #0B2A40;
15
+ --color-secondary-50: #F0F0FA;
16
+ --color-secondary-100: #E9E9F8;
17
+ --color-secondary-200: #D3D4F1;
18
+ --color-secondary-300: #B4B6E6;
19
+ --color-secondary-400: #8F92D8;
20
+ --color-secondary-500: #5B5FC7;
21
+ --color-secondary-600: #4B4FB0;
22
+ --color-secondary-700: #3E4194;
23
+ --color-secondary-800: #333676;
24
+ --color-secondary-900: #282A5C;
25
+ --color-secondary-950: #181A3A;
26
+ --color-success-50: #EEF5EB;
27
+ --color-success-100: #E4F0DF;
28
+ --color-success-200: #C6E0BD;
29
+ --color-success-300: #9CC78E;
30
+ --color-success-400: #6CA85C;
31
+ --color-success-500: #4E9340;
32
+ --color-success-600: #3B7D2E;
33
+ --color-success-700: #306626;
34
+ --color-success-800: #27521F;
35
+ --color-success-900: #1F4119;
36
+ --color-success-950: #122A0E;
37
+ --color-warning-50: #FBF5E8;
38
+ --color-warning-100: #F7EBD2;
39
+ --color-warning-200: #EFD8A6;
40
+ --color-warning-300: #E4BF72;
41
+ --color-warning-400: #D6A245;
42
+ --color-warning-500: #C98E2D;
43
+ --color-warning-600: #B7791F;
44
+ --color-warning-700: #96631A;
45
+ --color-warning-800: #764E15;
46
+ --color-warning-900: #5B3C11;
47
+ --color-warning-950: #3B260A;
48
+ --color-danger-50: #FBEFEE;
49
+ --color-danger-100: #F6E0DE;
50
+ --color-danger-200: #EEC3BF;
51
+ --color-danger-300: #E39B95;
52
+ --color-danger-400: #D66E66;
53
+ --color-danger-500: #C94F46;
54
+ --color-danger-600: #B93A32;
55
+ --color-danger-700: #9A2F29;
56
+ --color-danger-800: #7B2621;
57
+ --color-danger-900: #611E1A;
58
+ --color-danger-950: #3F120F;
59
+ --color-neutral-50: #FAF9F5;
60
+ --color-neutral-100: #F3F1EB;
61
+ --color-neutral-200: #ECEAE3;
62
+ --color-neutral-300: #E1DED5;
63
+ --color-neutral-400: #CFCBC0;
64
+ --color-neutral-500: #8C9490;
65
+ --color-neutral-600: #5C6663;
66
+ --color-neutral-700: #3E4644;
67
+ --color-neutral-800: #2A3230;
68
+ --color-neutral-900: #1B2321;
69
+ --color-neutral-950: #111614;
70
+ --color-background-base: #F3F1EB;
71
71
  --color-background-elevated: #FFFFFF;
72
- --color-background-overlay: rgba(17, 24, 39, 0.5);
73
- --color-background-hover: #F3F4F6;
74
- --color-text-primary: #111827;
75
- --color-text-secondary: #6B7280;
76
- --color-text-disabled: #9CA3AF;
72
+ --color-background-subtle: #FAF9F5;
73
+ --color-background-overlay: rgba(27, 35, 33, 0.5);
74
+ --color-background-hover: #F0EEE7;
75
+ --color-text-primary: #1B2321;
76
+ --color-text-secondary: #5C6663;
77
+ --color-text-tertiary: #616966;
78
+ --color-text-disabled: #8C9490;
77
79
  --color-text-inverse: #FFFFFF;
78
- --color-border-default: #E5E7EB;
79
- --color-border-subtle: #F3F4F6;
80
- --color-border-strong: #D1D5DB;
80
+ --color-border-default: #E1DED5;
81
+ --color-border-subtle: #ECEAE3;
82
+ --color-border-strong: #CFCBC0;
81
83
  --spacing-0: 0;
82
84
  --spacing-1: 0.25rem;
83
85
  --spacing-2: 0.5rem;
@@ -95,16 +97,18 @@
95
97
  --spacing-16: 4rem;
96
98
  --spacing-20: 5rem;
97
99
  --spacing-24: 6rem;
100
+ --spacing-72: 18rem;
98
101
  --spacing-px: 1px;
99
102
  --radius-none: 0;
100
- --radius-sm: 0.25rem;
101
- --radius-md: 0.375rem;
102
- --radius-lg: 0.5rem;
103
+ --radius-sm: 0.375rem;
104
+ --radius-md: 0.5rem;
105
+ --radius-lg: 0.75rem;
106
+ --radius-xl: 1rem;
103
107
  --radius-full: 9999px;
104
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
105
- --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
106
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
107
- --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
108
+ --shadow-sm: 0 1px 2px 0 rgba(43, 38, 24, 0.06);
109
+ --shadow-md: 0 1px 2px 0 rgba(43, 38, 24, 0.05), 0 6px 18px 0 rgba(43, 38, 24, 0.07);
110
+ --shadow-lg: 0 2px 4px 0 rgba(43, 38, 24, 0.06), 0 16px 40px 0 rgba(43, 38, 24, 0.12);
111
+ --shadow-xl: 0 4px 8px 0 rgba(43, 38, 24, 0.08), 0 24px 56px 0 rgba(43, 38, 24, 0.16);
108
112
  --motion-duration-fast: 150ms;
109
113
  --motion-duration-normal: 250ms;
110
114
  --motion-duration-slow: 400ms;
@@ -112,13 +116,16 @@
112
116
  --motion-easing-enter: cubic-bezier(0, 0, 0.2, 1);
113
117
  --motion-easing-exit: cubic-bezier(0.4, 0, 1, 1);
114
118
  --direction: ltr;
115
- --font-family-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
116
- --font-family-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;
119
+ --font-family-sans: 'IBM Plex Sans', 'IBM Plex Sans Arabic', ui-sans-serif, system-ui, sans-serif;
120
+ --font-family-serif: 'Literata', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;
121
+ --font-family-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;
117
122
  --font-size-xs: 0.75rem;
118
- --font-size-sm: 0.875rem;
119
- --font-size-base: 1rem;
120
- --font-size-lg: 1.125rem;
123
+ --font-size-sm: 0.8125rem;
124
+ --font-size-base: 0.875rem;
125
+ --font-size-lg: 1rem;
121
126
  --font-size-xl: 1.25rem;
127
+ --font-size-2xl: 1.5rem;
128
+ --font-size-3xl: 1.875rem;
122
129
  --font-weight-normal: 400;
123
130
  --font-weight-medium: 500;
124
131
  --font-weight-semibold: 600;
@@ -129,18 +136,52 @@
129
136
  }
130
137
 
131
138
  [data-theme="dark"] {
132
- --color-background-base: #0F1117;
133
- --color-background-elevated: #171923;
139
+ --color-background-base: #1A1C1B;
140
+ --color-background-elevated: #232625;
141
+ --color-background-subtle: #1F2221;
134
142
  --color-background-overlay: rgba(0, 0, 0, 0.6);
135
- --color-background-hover: #1F2937;
136
- --color-text-primary: #F3F4F6;
137
- --color-text-secondary: #9CA3AF;
138
- --color-text-disabled: #4B5563;
139
- --color-border-default: #1F2937;
140
- --color-border-subtle: #171923;
141
- --color-border-strong: #374151;
142
- --color-primary-500: #818CF8;
143
- --color-primary-600: #6366F1;
144
- --color-secondary-500: #A78BFA;
145
- --color-secondary-600: #8B5CF6;
143
+ --color-background-hover: #2C302E;
144
+ --color-text-primary: #ECEAE3;
145
+ --color-text-secondary: #A3A8A6;
146
+ --color-text-tertiary: #969C99;
147
+ --color-text-disabled: #6F7573;
148
+ --color-text-inverse: #14181B;
149
+ --color-border-default: #33373A;
150
+ --color-border-subtle: #2C302E;
151
+ --color-border-strong: #444A4D;
152
+ --color-primary-50: #1D2A34;
153
+ --color-primary-100: #22364A;
154
+ --color-primary-200: #2A4A66;
155
+ --color-primary-300: #7CC0E8;
156
+ --color-primary-600: #7CC0E8;
157
+ --color-primary-700: #9AD0EE;
158
+ --color-primary-800: #BFE1F5;
159
+ --color-secondary-100: #2A2C46;
160
+ --color-secondary-500: #9A9DE3;
161
+ --color-secondary-600: #9A9DE3;
162
+ --color-success-100: #223A1E;
163
+ --color-success-600: #7FC46E;
164
+ --color-success-700: #8FD07F;
165
+ --color-warning-100: #3D3016;
166
+ --color-warning-600: #E0AA4B;
167
+ --color-warning-800: #EABB6A;
168
+ --color-danger-100: #45201D;
169
+ --color-danger-600: #E8776E;
170
+ --color-danger-700: #F0918A;
171
+ --color-neutral-50: #1F2221;
172
+ --color-neutral-100: #232625;
173
+ --color-neutral-200: #2C302E;
174
+ --color-neutral-300: #33373A;
175
+ --color-neutral-400: #444A4D;
176
+ --color-neutral-500: #6F7573;
177
+ --color-neutral-600: #A3A8A6;
178
+ --color-neutral-700: #C5C9C6;
179
+ --color-neutral-800: #DAD9D3;
180
+ --color-neutral-900: #ECEAE3;
181
+ --color-neutral-950: #F5F4F0;
182
+ }
183
+
184
+ /* Arabic locales lead with Plex Sans Arabic — same token, language-conditional value. */
185
+ [lang="ar"], [lang^="ar-"] {
186
+ --font-family-sans: 'IBM Plex Sans Arabic', 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
146
187
  }
package/dist/tokens.d.ts CHANGED
@@ -1,12 +1,25 @@
1
1
  import type { VeloraDesignTokens } from './types.js';
2
2
  /**
3
- * Velora brand tokens — the default (light) token set.
3
+ * Velora brand tokens — the default (light) token set, per the S177
4
+ * design (the Session-177 design decisions,
5
+ * user-approved 2026-08-30).
4
6
  *
5
- * Brand anchors, per the UI & Design System plan:
6
- * every brand color is the 500 step of its scale (indigo #6366F1,
7
- * violet #8B5CF6, emerald #10B981, amber #F59E0B, red #EF4444), and
8
- * the light background #F9FAFB is neutral.50. The dark background
9
- * #0F1117 belongs to the Dark theme's overrides (Session 27), not to
10
- * this base set — themes override tokens, never components.
7
+ * Colour roles: the primary scale runs sky (50–300, atmosphere:
8
+ * selection, focus, the version rail) into cerulean (600–800, action:
9
+ * buttons, links). THE ACTION COLOUR IS primary-600 — this supersedes the
10
+ * Session-27 "brand = 500 step" convention for primary; 500 is a
11
+ * mid-step used for nothing in particular. Status scales pair a 100-step
12
+ * soft fill with the lightest text step that clears 4.5:1 on that fill
13
+ * (success/danger 700, warning 800). Neutrals are warm stone, not grey. The
14
+ * dark set (themes/dark.ts) overrides colour only — themes never touch
15
+ * typography/spacing/shadow/motion.
11
16
  */
12
17
  export declare const tokens: VeloraDesignTokens;
18
+ /**
19
+ * Under an Arabic document language the SAME sans token leads with Plex
20
+ * Sans Arabic (its Latin glyphs are Plex-compatible), so RTL locales get a
21
+ * native UI face without any component knowing. Emitted by build-css.ts
22
+ * as a `[lang="ar"]` block — a language-conditional value of an existing
23
+ * token, not a new one.
24
+ */
25
+ export declare const ARABIC_SANS_FONT_FAMILY = "'IBM Plex Sans Arabic', 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif";
package/dist/tokens.js CHANGED
@@ -1,124 +1,140 @@
1
1
  /**
2
- * Velora brand tokens — the default (light) token set.
2
+ * Velora brand tokens — the default (light) token set, per the S177
3
+ * design (the Session-177 design decisions,
4
+ * user-approved 2026-08-30).
3
5
  *
4
- * Brand anchors, per the UI & Design System plan:
5
- * every brand color is the 500 step of its scale (indigo #6366F1,
6
- * violet #8B5CF6, emerald #10B981, amber #F59E0B, red #EF4444), and
7
- * the light background #F9FAFB is neutral.50. The dark background
8
- * #0F1117 belongs to the Dark theme's overrides (Session 27), not to
9
- * this base set — themes override tokens, never components.
6
+ * Colour roles: the primary scale runs sky (50–300, atmosphere:
7
+ * selection, focus, the version rail) into cerulean (600–800, action:
8
+ * buttons, links). THE ACTION COLOUR IS primary-600 — this supersedes the
9
+ * Session-27 "brand = 500 step" convention for primary; 500 is a
10
+ * mid-step used for nothing in particular. Status scales pair a 100-step
11
+ * soft fill with the lightest text step that clears 4.5:1 on that fill
12
+ * (success/danger 700, warning 800). Neutrals are warm stone, not grey. The
13
+ * dark set (themes/dark.ts) overrides colour only — themes never touch
14
+ * typography/spacing/shadow/motion.
10
15
  */
11
16
  export const tokens = {
12
17
  color: {
13
18
  primary: {
14
- '50': '#EEF2FF',
15
- '100': '#E0E7FF',
16
- '200': '#C7D2FE',
17
- '300': '#A5B4FC',
18
- '400': '#818CF8',
19
- '500': '#6366F1',
20
- '600': '#4F46E5',
21
- '700': '#4338CA',
22
- '800': '#3730A3',
23
- '900': '#312E81',
24
- '950': '#1E1B4B',
19
+ '50': '#EAF4FB',
20
+ '100': '#CFE6F6',
21
+ '200': '#A9D5F0',
22
+ '300': '#7CC0E8',
23
+ '400': '#4E9CCB',
24
+ '500': '#2A82BC',
25
+ '600': '#1F6FA8',
26
+ '700': '#1A5E8F',
27
+ '800': '#154D75',
28
+ '900': '#113D5C',
29
+ '950': '#0B2A40',
25
30
  },
31
+ // The former brand indigo, demoted to the info/secondary role.
26
32
  secondary: {
27
- '50': '#F5F3FF',
28
- '100': '#EDE9FE',
29
- '200': '#DDD6FE',
30
- '300': '#C4B5FD',
31
- '400': '#A78BFA',
32
- '500': '#8B5CF6',
33
- '600': '#7C3AED',
34
- '700': '#6D28D9',
35
- '800': '#5B21B6',
36
- '900': '#4C1D95',
37
- '950': '#2E1065',
33
+ '50': '#F0F0FA',
34
+ '100': '#E9E9F8',
35
+ '200': '#D3D4F1',
36
+ '300': '#B4B6E6',
37
+ '400': '#8F92D8',
38
+ '500': '#5B5FC7',
39
+ '600': '#4B4FB0',
40
+ '700': '#3E4194',
41
+ '800': '#333676',
42
+ '900': '#282A5C',
43
+ '950': '#181A3A',
38
44
  },
39
45
  success: {
40
- '50': '#ECFDF5',
41
- '100': '#D1FAE5',
42
- '200': '#A7F3D0',
43
- '300': '#6EE7B7',
44
- '400': '#34D399',
45
- '500': '#10B981',
46
- '600': '#059669',
47
- '700': '#047857',
48
- '800': '#065F46',
49
- '900': '#064E3B',
50
- '950': '#022C22',
46
+ '50': '#EEF5EB',
47
+ '100': '#E4F0DF',
48
+ '200': '#C6E0BD',
49
+ '300': '#9CC78E',
50
+ '400': '#6CA85C',
51
+ '500': '#4E9340',
52
+ '600': '#3B7D2E',
53
+ '700': '#306626',
54
+ '800': '#27521F',
55
+ '900': '#1F4119',
56
+ '950': '#122A0E',
51
57
  },
52
58
  warning: {
53
- '50': '#FFFBEB',
54
- '100': '#FEF3C7',
55
- '200': '#FDE68A',
56
- '300': '#FCD34D',
57
- '400': '#FBBF24',
58
- '500': '#F59E0B',
59
- '600': '#D97706',
60
- '700': '#B45309',
61
- '800': '#92400E',
62
- '900': '#78350F',
63
- '950': '#451A03',
59
+ '50': '#FBF5E8',
60
+ '100': '#F7EBD2',
61
+ '200': '#EFD8A6',
62
+ '300': '#E4BF72',
63
+ '400': '#D6A245',
64
+ '500': '#C98E2D',
65
+ '600': '#B7791F',
66
+ '700': '#96631A',
67
+ '800': '#764E15',
68
+ '900': '#5B3C11',
69
+ '950': '#3B260A',
64
70
  },
65
71
  danger: {
66
- '50': '#FEF2F2',
67
- '100': '#FEE2E2',
68
- '200': '#FECACA',
69
- '300': '#FCA5A5',
70
- '400': '#F87171',
71
- '500': '#EF4444',
72
- '600': '#DC2626',
73
- '700': '#B91C1C',
74
- '800': '#991B1B',
75
- '900': '#7F1D1D',
76
- '950': '#450A0A',
72
+ '50': '#FBEFEE',
73
+ '100': '#F6E0DE',
74
+ '200': '#EEC3BF',
75
+ '300': '#E39B95',
76
+ '400': '#D66E66',
77
+ '500': '#C94F46',
78
+ '600': '#B93A32',
79
+ '700': '#9A2F29',
80
+ '800': '#7B2621',
81
+ '900': '#611E1A',
82
+ '950': '#3F120F',
77
83
  },
78
84
  neutral: {
79
- '50': '#F9FAFB',
80
- '100': '#F3F4F6',
81
- '200': '#E5E7EB',
82
- '300': '#D1D5DB',
83
- '400': '#9CA3AF',
84
- '500': '#6B7280',
85
- '600': '#4B5563',
86
- '700': '#374151',
87
- '800': '#1F2937',
88
- '900': '#111827',
89
- '950': '#030712',
85
+ '50': '#FAF9F5',
86
+ '100': '#F3F1EB',
87
+ '200': '#ECEAE3',
88
+ '300': '#E1DED5',
89
+ '400': '#CFCBC0',
90
+ '500': '#8C9490',
91
+ '600': '#5C6663',
92
+ '700': '#3E4644',
93
+ '800': '#2A3230',
94
+ '900': '#1B2321',
95
+ '950': '#111614',
90
96
  },
91
97
  background: {
92
- base: '#F9FAFB',
98
+ base: '#F3F1EB',
93
99
  elevated: '#FFFFFF',
94
- overlay: 'rgba(17, 24, 39, 0.5)',
95
- // neutral.100 — the shade outline/ghost hovers rendered before this
96
- // was a token, so light theme is visually unchanged
97
- hover: '#F3F4F6',
100
+ subtle: '#FAF9F5',
101
+ overlay: 'rgba(27, 35, 33, 0.5)',
102
+ // Nudged from #ECEAE3 (S179): the original wash put primary-600 text
103
+ // at 4.48:1 against it, just under AA — #F0EEE7 clears 4.5:1 while
104
+ // staying the darkest of the four light surfaces (the hover-wash
105
+ // hierarchy is unchanged).
106
+ hover: '#F0EEE7',
98
107
  },
99
108
  text: {
100
- primary: '#111827',
101
- secondary: '#6B7280',
102
- disabled: '#9CA3AF',
109
+ primary: '#1B2321',
110
+ secondary: '#5C6663',
111
+ tertiary: '#616966',
112
+ disabled: '#8C9490',
103
113
  inverse: '#FFFFFF',
104
114
  },
105
115
  border: {
106
- default: '#E5E7EB',
107
- subtle: '#F3F4F6',
108
- strong: '#D1D5DB',
116
+ default: '#E1DED5',
117
+ subtle: '#ECEAE3',
118
+ strong: '#CFCBC0',
109
119
  },
110
120
  },
111
121
  typography: {
112
122
  fontFamily: {
113
- sans: "'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif",
114
- mono: "'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace",
123
+ sans: "'IBM Plex Sans', 'IBM Plex Sans Arabic', ui-sans-serif, system-ui, sans-serif",
124
+ serif: "'Literata', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif",
125
+ mono: "'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace",
115
126
  },
127
+ // px targets at a 16px root: 12 · 13 · 14 · 16 · 20 · 24 · 30.
128
+ // base is 14px (the tool's body size); 2xl = tool titles, 3xl =
129
+ // content titles (serif).
116
130
  fontSize: {
117
131
  xs: '0.75rem',
118
- sm: '0.875rem',
119
- base: '1rem',
120
- lg: '1.125rem',
132
+ sm: '0.8125rem',
133
+ base: '0.875rem',
134
+ lg: '1rem',
121
135
  xl: '1.25rem',
136
+ '2xl': '1.5rem',
137
+ '3xl': '1.875rem',
122
138
  },
123
139
  fontWeight: {
124
140
  normal: 400,
@@ -151,19 +167,25 @@ export const tokens = {
151
167
  '16': '4rem',
152
168
  '20': '5rem',
153
169
  '24': '6rem',
170
+ // 72 (18rem): the persistent tree panel's width (S49 structure, S177 spec
171
+ // 284px) — Tailwind's `w-72` resolves only through this scale.
172
+ '72': '18rem',
154
173
  },
174
+ // 6 small · 8 controls · 12 cards · 16 dialogs
155
175
  radius: {
156
176
  none: '0',
157
- sm: '0.25rem',
158
- md: '0.375rem',
159
- lg: '0.5rem',
177
+ sm: '0.375rem',
178
+ md: '0.5rem',
179
+ lg: '0.75rem',
180
+ xl: '1rem',
160
181
  full: '9999px',
161
182
  },
183
+ // Warm-tinted (the shadow colour is the neutral-900 ink, not black).
162
184
  shadow: {
163
- sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
164
- md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
165
- lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
166
- xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
185
+ sm: '0 1px 2px 0 rgba(43, 38, 24, 0.06)',
186
+ md: '0 1px 2px 0 rgba(43, 38, 24, 0.05), 0 6px 18px 0 rgba(43, 38, 24, 0.07)',
187
+ lg: '0 2px 4px 0 rgba(43, 38, 24, 0.06), 0 16px 40px 0 rgba(43, 38, 24, 0.12)',
188
+ xl: '0 4px 8px 0 rgba(43, 38, 24, 0.08), 0 24px 56px 0 rgba(43, 38, 24, 0.16)',
167
189
  },
168
190
  motion: {
169
191
  duration: {
@@ -179,3 +201,11 @@ export const tokens = {
179
201
  },
180
202
  direction: 'ltr',
181
203
  };
204
+ /**
205
+ * Under an Arabic document language the SAME sans token leads with Plex
206
+ * Sans Arabic (its Latin glyphs are Plex-compatible), so RTL locales get a
207
+ * native UI face without any component knowing. Emitted by build-css.ts
208
+ * as a `[lang="ar"]` block — a language-conditional value of an existing
209
+ * token, not a new one.
210
+ */
211
+ export const ARABIC_SANS_FONT_FAMILY = "'IBM Plex Sans Arabic', 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif";
package/dist/tokens.json CHANGED
@@ -1,112 +1,117 @@
1
1
  {
2
2
  "color": {
3
3
  "primary": {
4
- "50": "#EEF2FF",
5
- "100": "#E0E7FF",
6
- "200": "#C7D2FE",
7
- "300": "#A5B4FC",
8
- "400": "#818CF8",
9
- "500": "#6366F1",
10
- "600": "#4F46E5",
11
- "700": "#4338CA",
12
- "800": "#3730A3",
13
- "900": "#312E81",
14
- "950": "#1E1B4B"
4
+ "50": "#EAF4FB",
5
+ "100": "#CFE6F6",
6
+ "200": "#A9D5F0",
7
+ "300": "#7CC0E8",
8
+ "400": "#4E9CCB",
9
+ "500": "#2A82BC",
10
+ "600": "#1F6FA8",
11
+ "700": "#1A5E8F",
12
+ "800": "#154D75",
13
+ "900": "#113D5C",
14
+ "950": "#0B2A40"
15
15
  },
16
16
  "secondary": {
17
- "50": "#F5F3FF",
18
- "100": "#EDE9FE",
19
- "200": "#DDD6FE",
20
- "300": "#C4B5FD",
21
- "400": "#A78BFA",
22
- "500": "#8B5CF6",
23
- "600": "#7C3AED",
24
- "700": "#6D28D9",
25
- "800": "#5B21B6",
26
- "900": "#4C1D95",
27
- "950": "#2E1065"
17
+ "50": "#F0F0FA",
18
+ "100": "#E9E9F8",
19
+ "200": "#D3D4F1",
20
+ "300": "#B4B6E6",
21
+ "400": "#8F92D8",
22
+ "500": "#5B5FC7",
23
+ "600": "#4B4FB0",
24
+ "700": "#3E4194",
25
+ "800": "#333676",
26
+ "900": "#282A5C",
27
+ "950": "#181A3A"
28
28
  },
29
29
  "success": {
30
- "50": "#ECFDF5",
31
- "100": "#D1FAE5",
32
- "200": "#A7F3D0",
33
- "300": "#6EE7B7",
34
- "400": "#34D399",
35
- "500": "#10B981",
36
- "600": "#059669",
37
- "700": "#047857",
38
- "800": "#065F46",
39
- "900": "#064E3B",
40
- "950": "#022C22"
30
+ "50": "#EEF5EB",
31
+ "100": "#E4F0DF",
32
+ "200": "#C6E0BD",
33
+ "300": "#9CC78E",
34
+ "400": "#6CA85C",
35
+ "500": "#4E9340",
36
+ "600": "#3B7D2E",
37
+ "700": "#306626",
38
+ "800": "#27521F",
39
+ "900": "#1F4119",
40
+ "950": "#122A0E"
41
41
  },
42
42
  "warning": {
43
- "50": "#FFFBEB",
44
- "100": "#FEF3C7",
45
- "200": "#FDE68A",
46
- "300": "#FCD34D",
47
- "400": "#FBBF24",
48
- "500": "#F59E0B",
49
- "600": "#D97706",
50
- "700": "#B45309",
51
- "800": "#92400E",
52
- "900": "#78350F",
53
- "950": "#451A03"
43
+ "50": "#FBF5E8",
44
+ "100": "#F7EBD2",
45
+ "200": "#EFD8A6",
46
+ "300": "#E4BF72",
47
+ "400": "#D6A245",
48
+ "500": "#C98E2D",
49
+ "600": "#B7791F",
50
+ "700": "#96631A",
51
+ "800": "#764E15",
52
+ "900": "#5B3C11",
53
+ "950": "#3B260A"
54
54
  },
55
55
  "danger": {
56
- "50": "#FEF2F2",
57
- "100": "#FEE2E2",
58
- "200": "#FECACA",
59
- "300": "#FCA5A5",
60
- "400": "#F87171",
61
- "500": "#EF4444",
62
- "600": "#DC2626",
63
- "700": "#B91C1C",
64
- "800": "#991B1B",
65
- "900": "#7F1D1D",
66
- "950": "#450A0A"
56
+ "50": "#FBEFEE",
57
+ "100": "#F6E0DE",
58
+ "200": "#EEC3BF",
59
+ "300": "#E39B95",
60
+ "400": "#D66E66",
61
+ "500": "#C94F46",
62
+ "600": "#B93A32",
63
+ "700": "#9A2F29",
64
+ "800": "#7B2621",
65
+ "900": "#611E1A",
66
+ "950": "#3F120F"
67
67
  },
68
68
  "neutral": {
69
- "50": "#F9FAFB",
70
- "100": "#F3F4F6",
71
- "200": "#E5E7EB",
72
- "300": "#D1D5DB",
73
- "400": "#9CA3AF",
74
- "500": "#6B7280",
75
- "600": "#4B5563",
76
- "700": "#374151",
77
- "800": "#1F2937",
78
- "900": "#111827",
79
- "950": "#030712"
69
+ "50": "#FAF9F5",
70
+ "100": "#F3F1EB",
71
+ "200": "#ECEAE3",
72
+ "300": "#E1DED5",
73
+ "400": "#CFCBC0",
74
+ "500": "#8C9490",
75
+ "600": "#5C6663",
76
+ "700": "#3E4644",
77
+ "800": "#2A3230",
78
+ "900": "#1B2321",
79
+ "950": "#111614"
80
80
  },
81
81
  "background": {
82
- "base": "#F9FAFB",
82
+ "base": "#F3F1EB",
83
83
  "elevated": "#FFFFFF",
84
- "overlay": "rgba(17, 24, 39, 0.5)",
85
- "hover": "#F3F4F6"
84
+ "subtle": "#FAF9F5",
85
+ "overlay": "rgba(27, 35, 33, 0.5)",
86
+ "hover": "#F0EEE7"
86
87
  },
87
88
  "text": {
88
- "primary": "#111827",
89
- "secondary": "#6B7280",
90
- "disabled": "#9CA3AF",
89
+ "primary": "#1B2321",
90
+ "secondary": "#5C6663",
91
+ "tertiary": "#616966",
92
+ "disabled": "#8C9490",
91
93
  "inverse": "#FFFFFF"
92
94
  },
93
95
  "border": {
94
- "default": "#E5E7EB",
95
- "subtle": "#F3F4F6",
96
- "strong": "#D1D5DB"
96
+ "default": "#E1DED5",
97
+ "subtle": "#ECEAE3",
98
+ "strong": "#CFCBC0"
97
99
  }
98
100
  },
99
101
  "typography": {
100
102
  "fontFamily": {
101
- "sans": "'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif",
102
- "mono": "'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace"
103
+ "sans": "'IBM Plex Sans', 'IBM Plex Sans Arabic', ui-sans-serif, system-ui, sans-serif",
104
+ "serif": "'Literata', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif",
105
+ "mono": "'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace"
103
106
  },
104
107
  "fontSize": {
105
108
  "xs": "0.75rem",
106
- "sm": "0.875rem",
107
- "base": "1rem",
108
- "lg": "1.125rem",
109
- "xl": "1.25rem"
109
+ "sm": "0.8125rem",
110
+ "base": "0.875rem",
111
+ "lg": "1rem",
112
+ "xl": "1.25rem",
113
+ "2xl": "1.5rem",
114
+ "3xl": "1.875rem"
110
115
  },
111
116
  "fontWeight": {
112
117
  "normal": 400,
@@ -138,20 +143,22 @@
138
143
  "16": "4rem",
139
144
  "20": "5rem",
140
145
  "24": "6rem",
146
+ "72": "18rem",
141
147
  "px": "1px"
142
148
  },
143
149
  "radius": {
144
150
  "none": "0",
145
- "sm": "0.25rem",
146
- "md": "0.375rem",
147
- "lg": "0.5rem",
151
+ "sm": "0.375rem",
152
+ "md": "0.5rem",
153
+ "lg": "0.75rem",
154
+ "xl": "1rem",
148
155
  "full": "9999px"
149
156
  },
150
157
  "shadow": {
151
- "sm": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
152
- "md": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
153
- "lg": "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
154
- "xl": "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)"
158
+ "sm": "0 1px 2px 0 rgba(43, 38, 24, 0.06)",
159
+ "md": "0 1px 2px 0 rgba(43, 38, 24, 0.05), 0 6px 18px 0 rgba(43, 38, 24, 0.07)",
160
+ "lg": "0 2px 4px 0 rgba(43, 38, 24, 0.06), 0 16px 40px 0 rgba(43, 38, 24, 0.12)",
161
+ "xl": "0 4px 8px 0 rgba(43, 38, 24, 0.08), 0 24px 56px 0 rgba(43, 38, 24, 0.16)"
155
162
  },
156
163
  "motion": {
157
164
  "duration": {
package/dist/types.d.ts CHANGED
@@ -10,7 +10,7 @@ export type ColorScale = Record<ColorScaleStep, string>;
10
10
  * Dots are avoided in keys so CSS custom property names stay valid
11
11
  * without escaping.
12
12
  */
13
- export type SpacingStep = '0' | 'px' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | '14' | '16' | '20' | '24';
13
+ export type SpacingStep = '0' | 'px' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | '14' | '16' | '20' | '24' | '72';
14
14
  export type ScaleTokens = Record<SpacingStep, string>;
15
15
  export interface VeloraDesignTokens {
16
16
  color: {
@@ -23,12 +23,14 @@ export interface VeloraDesignTokens {
23
23
  background: {
24
24
  base: string;
25
25
  elevated: string;
26
+ subtle: string;
26
27
  overlay: string;
27
28
  hover: string;
28
29
  };
29
30
  text: {
30
31
  primary: string;
31
32
  secondary: string;
33
+ tertiary: string;
32
34
  disabled: string;
33
35
  inverse: string;
34
36
  };
@@ -41,14 +43,15 @@ export interface VeloraDesignTokens {
41
43
  typography: {
42
44
  fontFamily: {
43
45
  sans: string;
46
+ serif: string;
44
47
  mono: string;
45
48
  };
46
- fontSize: Record<'xs' | 'sm' | 'base' | 'lg' | 'xl', string>;
49
+ fontSize: Record<'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl', string>;
47
50
  fontWeight: Record<'normal' | 'medium' | 'semibold' | 'bold', number>;
48
51
  lineHeight: Record<'tight' | 'normal' | 'relaxed', number>;
49
52
  };
50
53
  spacing: ScaleTokens;
51
- radius: Record<'none' | 'sm' | 'md' | 'lg' | 'full', string>;
54
+ radius: Record<'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full', string>;
52
55
  shadow: Record<'sm' | 'md' | 'lg' | 'xl', string>;
53
56
  motion: {
54
57
  duration: Record<string, string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velora-cms/design-tokens",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Velora's design token source, generating the Tailwind config and CSS variables consumed by the UI library, admin UI, and plugin UIs.",
6
6
  "engines": {