@loworbitstudio/visor-core 0.3.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.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # @loworbitstudio/visor-core
2
+
3
+ CSS custom property design tokens for the Visor design system.
4
+
5
+ ## Installation
6
+
7
+ > **Note:** This package (`@loworbitstudio/visor-core`) is not yet published to npm. For new projects, use `npx @loworbitstudio/visor init --template nextjs` — it generates all tokens inline via the theme engine, no npm package needed. For monorepo usage, import via a relative path.
8
+
9
+ When the package is published, installation will be:
10
+
11
+ ```sh
12
+ npm install @loworbitstudio/visor-core
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Import the full token bundle in your project's entry CSS or JS:
18
+
19
+ ```css
20
+ @import "@loworbitstudio/visor-core";
21
+ ```
22
+
23
+ Or import specific layers:
24
+
25
+ ```css
26
+ @import "@loworbitstudio/visor-core/primitives"; /* Tier 1: raw values */
27
+ @import "@loworbitstudio/visor-core/semantic"; /* Tier 2: purpose-named */
28
+ @import "@loworbitstudio/visor-core/themes/light"; /* Tier 3: light theme */
29
+ @import "@loworbitstudio/visor-core/themes/dark"; /* Tier 3: dark theme */
30
+ ```
31
+
32
+ Then use tokens in your CSS:
33
+
34
+ ```css
35
+ .card {
36
+ background: var(--surface-card);
37
+ color: var(--text-primary);
38
+ border: 1px solid var(--border-default);
39
+ border-radius: var(--radius-lg);
40
+ padding: var(--spacing-4);
41
+ }
42
+ ```
43
+
44
+ ## Token Architecture
45
+
46
+ Visor tokens follow a strict 3-tier hierarchy:
47
+
48
+ ### Tier 1: Primitives
49
+
50
+ Raw values named by what they ARE. Never reference these directly in components — use semantic tokens instead.
51
+
52
+ ```css
53
+ --color-gray-900: #111827;
54
+ --spacing-4: 1rem; /* 16px */
55
+ --radius-lg: 0.5rem; /* 8px */
56
+ --font-size-base: 1rem; /* 16px */
57
+ ```
58
+
59
+ ### Tier 2: Semantic
60
+
61
+ Named by PURPOSE. Map to primitives.
62
+
63
+ ```css
64
+ --text-primary: var(--color-gray-900);
65
+ --surface-card: var(--color-white);
66
+ --border-default: var(--color-gray-200);
67
+ --component-md: var(--spacing-4);
68
+ ```
69
+
70
+ ### Tier 3: Adaptive
71
+
72
+ Theme-aware tokens that switch based on the active theme class. Light theme values are set on `:root`. Dark theme values are applied under `.theme-dark`.
73
+
74
+ ```css
75
+ :root {
76
+ --text-primary: var(--color-gray-900);
77
+ --surface-page: var(--color-white);
78
+ }
79
+
80
+ .theme-dark {
81
+ --text-primary: var(--color-gray-50);
82
+ --surface-page: var(--color-gray-950);
83
+ }
84
+ ```
85
+
86
+ To enable the dark theme, add `.theme-dark` to your root element:
87
+
88
+ ```html
89
+ <html class="theme-dark">
90
+ ```
91
+
92
+ ## Consumer Override Mechanism
93
+
94
+ Override any token by redefining the CSS custom property. No forking required.
95
+
96
+ **Override a primitive** — all semantic tokens that reference it update automatically:
97
+
98
+ ```css
99
+ :root {
100
+ /* Rebrand the accent color */
101
+ --color-blue-500: #your-brand-color;
102
+ --color-blue-600: #your-brand-color-dark;
103
+ }
104
+ ```
105
+
106
+ **Override a semantic token** — change a specific role without touching primitives:
107
+
108
+ ```css
109
+ :root {
110
+ /* Use a custom card background */
111
+ --surface-card: var(--color-gray-50);
112
+ }
113
+ ```
114
+
115
+ **Override adaptive tokens per theme:**
116
+
117
+ ```css
118
+ :root {
119
+ --text-primary: #1a1a2e; /* Custom light mode text */
120
+ }
121
+
122
+ .theme-dark {
123
+ --text-primary: #e8e8f0; /* Custom dark mode text */
124
+ }
125
+ ```
126
+
127
+ ## TypeScript Support
128
+
129
+ Import token name constants for type-safe usage:
130
+
131
+ ```ts
132
+ import {
133
+ TOKEN_TEXT_PRIMARY,
134
+ TOKEN_SURFACE_CARD,
135
+ TOKEN_BORDER_DEFAULT,
136
+ } from "@loworbitstudio/visor-core/types"
137
+
138
+ // Use in JS (e.g., for animations or dynamic styles)
139
+ element.style.setProperty(TOKEN_TEXT_PRIMARY, "#custom-value")
140
+ const value = getComputedStyle(element).getPropertyValue(TOKEN_TEXT_PRIMARY)
141
+ ```
142
+
143
+ ## Available Token Groups
144
+
145
+ | Group | Prefix | Example |
146
+ |-------|--------|---------|
147
+ | Primitive colors | `--color-*` | `--color-gray-900` |
148
+ | Spacing | `--spacing-*` | `--spacing-4` (1rem / 16px) |
149
+ | Border radius | `--radius-*` | `--radius-lg` |
150
+ | Border widths | `--border-width-*` | `--border-width-1` |
151
+ | Font families | `--font-*` | `--font-sans` |
152
+ | Font sizes | `--font-size-*` | `--font-size-base` |
153
+ | Font weights | `--font-weight-*` | `--font-weight-semibold` |
154
+ | Line heights | `--line-height-*` | `--line-height-normal` |
155
+ | Shadows | `--shadow-*` | `--shadow-md` |
156
+ | Z-index | `--z-*` | `--z-modal` |
157
+ | Semantic text | `--text-*` | `--text-primary` |
158
+ | Semantic surface | `--surface-*` | `--surface-card` |
159
+ | Semantic border | `--border-*` | `--border-default` |
160
+ | Interactive | `--interactive-*` | `--interactive-primary-bg` |
161
+ | Component spacing | `--component-*` | `--component-md` |
162
+ | Layout spacing | `--layout-*` | `--layout-lg` |
163
+ | Typography roles | `--font-body`, `--size-*`, `--weight-*` | `--size-heading-lg` |
164
+
165
+ ## Development
166
+
167
+ ```sh
168
+ # Generate dist/tokens.css from source
169
+ npm run build
170
+
171
+ # Validate all token references
172
+ npm run validate
173
+
174
+ # Run tests
175
+ npm run test
176
+
177
+ # Type check
178
+ npm run typecheck
179
+ ```
package/dist/index.css ADDED
@@ -0,0 +1,8 @@
1
+ /* ============================================
2
+ Visor Design Tokens — Index
3
+ Generated by @loworbitstudio/visor-core
4
+ DO NOT EDIT — run `npm run build` to regenerate
5
+ ============================================ */
6
+
7
+ /* Full design token bundle */
8
+ @import './tokens.css';
@@ -0,0 +1,194 @@
1
+ /* ============================================
2
+ Visor Design Tokens — Primitives
3
+ Generated by @loworbitstudio/visor-core
4
+ DO NOT EDIT — run `npm run build` to regenerate
5
+ ============================================ */
6
+
7
+ /* --- Primitive: Colors --- */
8
+ :root {
9
+ --color-neutral-50: #f9fafb;
10
+ --color-neutral-100: #f3f4f6;
11
+ --color-neutral-200: #e5e7eb;
12
+ --color-neutral-300: #d1d5db;
13
+ --color-neutral-400: #9ca3af;
14
+ --color-neutral-500: #6b7280;
15
+ --color-neutral-600: #4b5563;
16
+ --color-neutral-700: #374151;
17
+ --color-neutral-800: #1f2937;
18
+ --color-neutral-900: #111827;
19
+ --color-neutral-950: #030712;
20
+ --color-white: #ffffff;
21
+ --color-black: #000000;
22
+ --color-primary-50: #eff6ff;
23
+ --color-primary-100: #dbeafe;
24
+ --color-primary-200: #bfdbfe;
25
+ --color-primary-300: #93c5fd;
26
+ --color-primary-400: #60a5fa;
27
+ --color-primary-500: #3b82f6;
28
+ --color-primary-600: #2563eb;
29
+ --color-primary-700: #1d4ed8;
30
+ --color-primary-800: #1e40af;
31
+ --color-primary-900: #1e3a8a;
32
+ --color-success-50: #f0fdf4;
33
+ --color-success-100: #dcfce7;
34
+ --color-success-500: #22c55e;
35
+ --color-success-600: #16a34a;
36
+ --color-success-700: #15803d;
37
+ --color-success-900: #14532d;
38
+ --color-warning-50: #fffbeb;
39
+ --color-warning-100: #fef3c7;
40
+ --color-warning-500: #f59e0b;
41
+ --color-warning-600: #d97706;
42
+ --color-warning-700: #b45309;
43
+ --color-warning-900: #78350f;
44
+ --color-error-50: #fef2f2;
45
+ --color-error-100: #fee2e2;
46
+ --color-error-500: #ef4444;
47
+ --color-error-600: #dc2626;
48
+ --color-error-700: #b91c1c;
49
+ --color-error-900: #7f1d1d;
50
+ --color-info-50: #f0f9ff;
51
+ --color-info-100: #e0f2fe;
52
+ --color-info-500: #0ea5e9;
53
+ --color-info-600: #0284c7;
54
+ --color-info-700: #0369a1;
55
+ --color-info-900: #0c4a6e;
56
+ }
57
+
58
+
59
+ /* --- Primitive: Spacing --- */
60
+ :root {
61
+ --spacing-0: 0; /* 0px */
62
+ --spacing-1: 0.25rem; /* 4px */
63
+ --spacing-2: 0.5rem; /* 8px */
64
+ --spacing-3: 0.75rem; /* 12px */
65
+ --spacing-4: 1rem; /* 16px */
66
+ --spacing-5: 1.25rem; /* 20px */
67
+ --spacing-6: 1.5rem; /* 24px */
68
+ --spacing-8: 2rem; /* 32px */
69
+ --spacing-10: 2.5rem; /* 40px */
70
+ --spacing-12: 3rem; /* 48px */
71
+ --spacing-16: 4rem; /* 64px */
72
+ --spacing-20: 5rem; /* 80px */
73
+ --spacing-24: 6rem; /* 96px */
74
+ --spacing-3_5: 0.875rem; /* 14px */
75
+ --spacing-4_5: 1.125rem; /* 18px */
76
+ }
77
+
78
+
79
+ /* --- Primitive: Border Radius --- */
80
+ :root {
81
+ --radius-none: 0;
82
+ --radius-sm: 0.125rem; /* 2px */
83
+ --radius-md: 0.25rem; /* 4px */
84
+ --radius-lg: 0.5rem; /* 8px */
85
+ --radius-xl: 0.75rem; /* 12px */
86
+ --radius-2xl: 1rem; /* 16px */
87
+ --radius-3xl: 1.5rem; /* 24px */
88
+ --radius-full: 9999px;
89
+ }
90
+
91
+
92
+ /* --- Primitive: Border Widths --- */
93
+ :root {
94
+ --border-width-1: 1px;
95
+ --border-width-2: 2px;
96
+ --border-width-3: 3px;
97
+ --border-width-4: 4px;
98
+ }
99
+
100
+
101
+ /* --- Primitive: Font Families --- */
102
+ :root {
103
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
104
+ --font-mono: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace;
105
+ }
106
+
107
+
108
+ /* --- Primitive: Font Sizes --- */
109
+ :root {
110
+ --font-size-xs: 0.75rem; /* 12px */
111
+ --font-size-sm: 0.875rem; /* 14px */
112
+ --font-size-base: 1rem; /* 16px */
113
+ --font-size-lg: 1.125rem; /* 18px */
114
+ --font-size-xl: 1.25rem; /* 20px */
115
+ --font-size-2xl: 1.5rem; /* 24px */
116
+ --font-size-3xl: 1.875rem; /* 30px */
117
+ --font-size-4xl: 2.25rem; /* 36px */
118
+ }
119
+
120
+
121
+ /* --- Primitive: Font Weights --- */
122
+ :root {
123
+ --font-weight-normal: 400;
124
+ --font-weight-medium: 500;
125
+ --font-weight-semibold: 600;
126
+ --font-weight-bold: 700;
127
+ }
128
+
129
+
130
+ /* --- Primitive: Line Heights --- */
131
+ :root {
132
+ --line-height-none: 1;
133
+ --line-height-tight: 1.25;
134
+ --line-height-snug: 1.375;
135
+ --line-height-normal: 1.5;
136
+ --line-height-relaxed: 1.625;
137
+ --line-height-loose: 2;
138
+ }
139
+
140
+
141
+ /* --- Primitive: Shadows --- */
142
+ :root {
143
+ --shadow-xs: inset 0 1px 2px 0 rgba(0, 0, 0, 0.06);
144
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
145
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
146
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
147
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
148
+ }
149
+
150
+
151
+ /* --- Primitive: Z-Index --- */
152
+ :root {
153
+ --z-base: 0;
154
+ --z-raised: 1;
155
+ --z-dropdown: 1000;
156
+ --z-sticky: 1100;
157
+ --z-modal: 1300;
158
+ --z-popover: 1400;
159
+ --z-toast: 1500;
160
+ }
161
+
162
+
163
+ /* --- Primitive: Overlay --- */
164
+ :root {
165
+ --overlay-bg: rgba(0, 0, 0, 0.5);
166
+ }
167
+
168
+
169
+ /* --- Primitive: Focus Ring --- */
170
+ :root {
171
+ --focus-ring-width: 2px;
172
+ --focus-ring-offset: 2px;
173
+ }
174
+
175
+
176
+ /* --- Primitive: Motion Durations --- */
177
+ :root {
178
+ --motion-duration-100: 100ms;
179
+ --motion-duration-150: 150ms;
180
+ --motion-duration-200: 200ms;
181
+ --motion-duration-300: 300ms;
182
+ --motion-duration-500: 500ms;
183
+ --motion-duration-800: 800ms;
184
+ }
185
+
186
+
187
+ /* --- Primitive: Motion Easings --- */
188
+ :root {
189
+ --motion-easing-linear: linear;
190
+ --motion-easing-ease-in: cubic-bezier(0.4, 0, 1, 1);
191
+ --motion-easing-ease-out: cubic-bezier(0, 0, 0.2, 1);
192
+ --motion-easing-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
193
+ --motion-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
194
+ }
@@ -0,0 +1,170 @@
1
+ /* ============================================
2
+ Visor Design Tokens — Semantic
3
+ Generated by @loworbitstudio/visor-core
4
+ DO NOT EDIT — run `npm run build` to regenerate
5
+ ============================================ */
6
+
7
+ /* --- Semantic: Text --- */
8
+ :root {
9
+ --text-primary: var(--color-neutral-900);
10
+ --text-secondary: var(--color-neutral-600);
11
+ --text-tertiary: var(--color-neutral-400);
12
+ --text-disabled: var(--color-neutral-300);
13
+ --text-inverse: var(--color-white);
14
+ --text-inverse-secondary: var(--color-neutral-200);
15
+ --text-link: var(--color-primary-600);
16
+ --text-link-hover: var(--color-primary-700);
17
+ --text-success: var(--color-success-700);
18
+ --text-warning: var(--color-warning-700);
19
+ --text-error: var(--color-error-700);
20
+ --text-info: var(--color-info-700);
21
+ }
22
+
23
+
24
+ /* --- Semantic: Surface --- */
25
+ :root {
26
+ --surface-page: var(--color-white);
27
+ --surface-card: var(--color-white);
28
+ --surface-subtle: var(--color-neutral-50);
29
+ --surface-muted: var(--color-neutral-100);
30
+ --surface-overlay: var(--color-neutral-900);
31
+ --surface-popover: var(--color-white);
32
+ --surface-interactive-default: var(--color-white);
33
+ --surface-interactive-hover: var(--color-neutral-50);
34
+ --surface-interactive-active: var(--color-neutral-100);
35
+ --surface-interactive-disabled: var(--color-neutral-50);
36
+ --surface-accent-subtle: var(--color-primary-50);
37
+ --surface-accent-default: var(--color-primary-500);
38
+ --surface-accent-strong: var(--color-primary-600);
39
+ --surface-success-subtle: var(--color-success-50);
40
+ --surface-success-default: var(--color-success-500);
41
+ --surface-warning-subtle: var(--color-warning-50);
42
+ --surface-warning-default: var(--color-warning-500);
43
+ --surface-error-subtle: var(--color-error-50);
44
+ --surface-error-default: var(--color-error-500);
45
+ --surface-info-subtle: var(--color-info-50);
46
+ --surface-info-default: var(--color-info-500);
47
+ }
48
+
49
+
50
+ /* --- Semantic: Border --- */
51
+ :root {
52
+ --border-default: var(--color-neutral-200);
53
+ --border-muted: var(--color-neutral-100);
54
+ --border-strong: var(--color-neutral-300);
55
+ --border-focus: var(--color-primary-500);
56
+ --border-disabled: var(--color-neutral-100);
57
+ --border-input: var(--color-neutral-200);
58
+ --border-success: var(--color-success-500);
59
+ --border-warning: var(--color-warning-500);
60
+ --border-error: var(--color-error-500);
61
+ --border-info: var(--color-info-500);
62
+ }
63
+
64
+
65
+ /* --- Semantic: Interactive --- */
66
+ :root {
67
+ --interactive-primary-bg: var(--color-primary-600);
68
+ --interactive-primary-bg-hover: var(--color-primary-700);
69
+ --interactive-primary-bg-active: var(--color-primary-800);
70
+ --interactive-primary-text: var(--color-white);
71
+ --interactive-secondary-bg: var(--color-white);
72
+ --interactive-secondary-bg-hover: var(--color-neutral-50);
73
+ --interactive-secondary-bg-active: var(--color-neutral-100);
74
+ --interactive-secondary-text: var(--color-neutral-900);
75
+ --interactive-secondary-border: var(--color-neutral-300);
76
+ --interactive-destructive-bg: var(--color-error-600);
77
+ --interactive-destructive-bg-hover: var(--color-error-700);
78
+ --interactive-destructive-text: var(--color-white);
79
+ --interactive-ghost-bg: var(--color-white);
80
+ --interactive-ghost-bg-hover: var(--color-neutral-100);
81
+ }
82
+
83
+
84
+ /* --- Semantic: Spacing --- */
85
+ :root {
86
+ --component-xs: var(--spacing-1);
87
+ --component-sm: var(--spacing-2);
88
+ --component-md: var(--spacing-4);
89
+ --component-lg: var(--spacing-6);
90
+ --component-xl: var(--spacing-8);
91
+ --layout-sm: var(--spacing-4);
92
+ --layout-md: var(--spacing-8);
93
+ --layout-lg: var(--spacing-12);
94
+ --layout-xl: var(--spacing-16);
95
+ --layout-2xl: var(--spacing-24);
96
+ }
97
+
98
+
99
+ /* --- Semantic: Typography --- */
100
+ :root {
101
+ --font-body: var(--font-sans);
102
+ --font-heading: var(--font-sans);
103
+ --font-mono: var(--font-mono);
104
+ --size-body: var(--font-size-base);
105
+ --size-body-sm: var(--font-size-sm);
106
+ --size-label: var(--font-size-sm);
107
+ --size-caption: var(--font-size-xs);
108
+ --size-heading-sm: var(--font-size-lg);
109
+ --size-heading-md: var(--font-size-xl);
110
+ --size-heading-lg: var(--font-size-2xl);
111
+ --size-heading-xl: var(--font-size-3xl);
112
+ --weight-body: var(--font-weight-normal);
113
+ --weight-label: var(--font-weight-medium);
114
+ --weight-heading: var(--font-weight-semibold);
115
+ --weight-strong: var(--font-weight-bold);
116
+ }
117
+
118
+
119
+ /* --- Semantic: Motion Duration --- */
120
+ :root {
121
+ --motion-duration-fast: var(--motion-duration-100);
122
+ --motion-duration-normal: var(--motion-duration-200);
123
+ --motion-duration-slow: var(--motion-duration-500);
124
+ }
125
+
126
+
127
+ /* --- Semantic: Motion Easing --- */
128
+ :root {
129
+ --motion-easing-default: var(--motion-easing-ease-in-out);
130
+ --motion-easing-enter: var(--motion-easing-ease-out);
131
+ --motion-easing-exit: var(--motion-easing-ease-in);
132
+ --motion-easing-spring: var(--motion-easing-spring);
133
+ }
134
+
135
+
136
+ /* --- Semantic: Overlay --- */
137
+
138
+
139
+ /* --- Semantic: Focus Ring --- */
140
+
141
+
142
+ /* --- Semantic: Skeleton --- */
143
+ :root {
144
+ --skeleton-from: var(--surface-muted);
145
+ --skeleton-to: var(--surface-subtle);
146
+ }
147
+
148
+
149
+ /* --- Semantic: Chart --- */
150
+ :root {
151
+ --chart-1: var(--color-primary-500);
152
+ --chart-2: var(--color-success-500);
153
+ --chart-3: var(--color-warning-500);
154
+ --chart-4: var(--color-info-500);
155
+ --chart-5: var(--color-error-500);
156
+ }
157
+
158
+
159
+ /* --- Semantic: Sidebar --- */
160
+ :root {
161
+ --sidebar-bg: var(--color-neutral-50);
162
+ --sidebar-text: var(--color-neutral-700);
163
+ --sidebar-primary-bg: var(--color-primary-600);
164
+ --sidebar-primary-text: var(--color-white);
165
+ --sidebar-accent-bg: var(--color-neutral-100);
166
+ --sidebar-accent-text: var(--color-neutral-900);
167
+ --sidebar-border: var(--color-neutral-200);
168
+ --sidebar-ring: var(--color-primary-500);
169
+ --sidebar-text-muted: var(--color-neutral-500);
170
+ }