@kolkrabbi/kol-theme 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.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # @kolkrabbi/kol-theme
2
+
3
+ Brand-neutral tokens + base CSS for the KOL (Kolkrabbi) design system. The cascade layer every other KOL package and consumer builds on — design tokens, color/opacity scales, typography, and the canonical `kol-*` component classes.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm i @kolkrabbi/kol-theme
9
+ ```
10
+
11
+ ## Use
12
+
13
+ In a Vite + Tailwind v4 app, import the barrel after Tailwind:
14
+
15
+ ```css
16
+ @import "tailwindcss";
17
+ @import "@kolkrabbi/kol-theme";
18
+ ```
19
+
20
+ Cascade order is load-bearing — `kol-theme` must come after Tailwind so its component classes and tokens resolve correctly. Individual files are also reachable (`@kolkrabbi/kol-theme/kol-color.css`, etc.) if you need finer control.
21
+
22
+ ## Fonts
23
+
24
+ The typography CSS references the brand fonts at absolute paths (`/fonts/Right-Grotesk/…`, `/fonts/jetbrains-mono/…`). **The package does not ship the font files** — your app must serve them from `/fonts/` (e.g. drop them in your `public/` dir). The showcase in this repo does exactly that. Without them, type falls back to system fonts.
25
+
26
+ Pure CSS — no JS, no dependencies.
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @kol/theme — Canonical neutral surface base (shared)
3
+ *
4
+ * The brand-NEUTRAL tokens that are identical across apps/web and apps/brand:
5
+ * the surface elevation tiers and theme-invariant absolutes. These are the real
6
+ * drift surface (page bg/fg colors) and they carry no brand identity, so they
7
+ * are safe to share as the single canonical source — kolkrabbi and any
8
+ * scaffolded client render on the same surface base.
9
+ *
10
+ * Deliberately NOT here: accent (kolkrabbi yellow in web; neutral-ink default +
11
+ * brand-layer rebind in brand), fonts, and brand color primitives — those are
12
+ * brand-specific and stay with each app's own theme layer.
13
+ *
14
+ * Plain :root (not @theme): these tokens aren't in Tailwind's --color-*
15
+ * namespace, so they generate no utilities either way — consumed as
16
+ * var(--kol-surface-*) by hand-written utilities + components in both apps.
17
+ * Dark selector matches brand's mechanism: [data-theme="dark"], .dark.
18
+ */
19
+
20
+ :root {
21
+ /* Absolutes (theme-invariant) */
22
+ --kol-color-absolute-white: #ffffff;
23
+ --kol-color-absolute-black: #000000;
24
+
25
+ /* Surface tiers (page-level) — Light Mode (default) */
26
+ --kol-surface-primary: #fafafa;
27
+ --kol-surface-on-primary: #121215;
28
+
29
+ --kol-surface-secondary: #f2f2f2;
30
+ --kol-surface-on-secondary: #19191d;
31
+
32
+ --kol-surface-tertiary: #ffffff;
33
+ --kol-surface-on-tertiary: #0e0e11;
34
+
35
+ --kol-surface-inverse: #0e0e11;
36
+ --kol-surface-on-inverse: #fcfbf8;
37
+
38
+ --kol-surface-secondary-inverse: #212121;
39
+ --kol-surface-tertiary-inverse: #424242;
40
+
41
+ --kol-surface-contrast: #f2f2f2;
42
+
43
+ /* Surface split tokens */
44
+ --kol-surface-support-split: #eeeeee;
45
+ --kol-surface-support-split-inverse: #202026;
46
+ --kol-surface-absolute-split: #ffffff;
47
+ --kol-surface-absolute-split-inverse: #000000;
48
+ }
49
+
50
+ /* Dark Mode — surface overrides */
51
+ :is([data-theme="dark"], .dark) {
52
+ --kol-surface-primary: #121215;
53
+ --kol-surface-on-primary: #fafafa;
54
+
55
+ --kol-surface-secondary: #19191d;
56
+ --kol-surface-on-secondary: #f8f8f8;
57
+
58
+ --kol-surface-tertiary: #0e0e11;
59
+ --kol-surface-on-tertiary: #ffffff;
60
+
61
+ --kol-surface-inverse: #fcfbf8;
62
+ --kol-surface-on-inverse: #0e0e11;
63
+
64
+ --kol-surface-secondary-inverse: #e0e0e0;
65
+ --kol-surface-tertiary-inverse: #d4d4d8;
66
+
67
+ --kol-surface-contrast: #0b0b0c;
68
+
69
+ /* Surface split tokens - Dark Mode */
70
+ --kol-surface-support-split: #202026;
71
+ --kol-surface-support-split-inverse: #eeeeee;
72
+ --kol-surface-absolute-split: #000000;
73
+ --kol-surface-absolute-split-inverse: #ffffff;
74
+ }
package/kol-color.css ADDED
@@ -0,0 +1,280 @@
1
+ /**
2
+ * KOL Color System — DS theme layer (brand-neutral).
3
+ *
4
+ * Surface tiers, ink-based accent default, ui-state, borders, opacity ramp
5
+ * re-declarations for surface-inverse contexts. Brand identity (hue ramps,
6
+ * cream ramp, brand-primary/secondary roles, accent rebind) lives in the
7
+ * sibling `kol-brand-color.css` and mirrors the `kol-brand` package — loaded
8
+ * explicitly by `index.css` for this repo (the brand showcase). A scaffolded
9
+ * project that does NOT pull `kol-brand` skips the brand import and renders
10
+ * brand-neutral with `--kol-accent-*` defaulting to surface ink.
11
+ *
12
+ * Dark mode toggle:
13
+ * document.documentElement.setAttribute('data-theme', 'dark')
14
+ */
15
+
16
+ /* =============================================================================
17
+ * LIGHT MODE (Default)
18
+ * ============================================================================= */
19
+
20
+ :root {
21
+ /* Absolutes + surface elevation tiers now come from
22
+ * @kol/theme/kol-base-tokens.css (imported first by kol-theme.css) — the
23
+ * shared canonical neutral base, identical to apps/web. */
24
+
25
+ /* ---------------------------------------------------------------------------
26
+ * ACCENT (interactive role — buttons, toggles, focus rings)
27
+ *
28
+ * Brand-neutral default: points at the surface ink color so the DS works
29
+ * without a brand layer. kol-brand-color.css overrides these to point at
30
+ * --brand-primary / --brand-on-primary / a brand-strong stop.
31
+ * --------------------------------------------------------------------------- */
32
+
33
+ --kol-accent-primary: var(--kol-surface-on-primary);
34
+ --kol-accent-on-primary: var(--kol-surface-primary);
35
+ --kol-accent-primary-strong: color-mix(in srgb, var(--kol-surface-on-primary) 80%, transparent);
36
+
37
+ /* ---------------------------------------------------------------------------
38
+ * UI STATE — error / warning / info / success.
39
+ * Direct hex (not ramp-dependent). Intentionally not part of the brand layer
40
+ * so consumers get sensible defaults out of the box.
41
+ * --------------------------------------------------------------------------- */
42
+
43
+ --ui-error: #B91C1C;
44
+ --ui-warning: #EAB308;
45
+ --ui-info: #1D4ED8;
46
+ --ui-success: #15803D;
47
+
48
+ /* ---------------------------------------------------------------------------
49
+ * BORDER
50
+ * --------------------------------------------------------------------------- */
51
+
52
+ --kol-border-default: color-mix(in srgb, var(--kol-surface-on-primary) 8%, transparent);
53
+ --kol-border-focus: color-mix(in srgb, var(--kol-accent-primary) 70%, var(--kol-surface-on-primary));
54
+ --kol-focus-ring: var(--kol-accent-primary);
55
+ }
56
+
57
+ :root[data-theme="light"] {
58
+ --ui-error: #DC2626;
59
+ --ui-warning: #CA8A04;
60
+ --ui-info: #2563EB;
61
+ --ui-success: #16A34A;
62
+ }
63
+
64
+ /* =============================================================================
65
+ * DARK MODE
66
+ * Explicit dark-mode surface overrides ([data-theme="dark"], .dark) now come
67
+ * from @kol/theme/kol-base-tokens.css (shared with apps/web). The system-
68
+ * preference auto-dark block below stays brand-local — web has no equivalent.
69
+ * ============================================================================= */
70
+
71
+ /* =============================================================================
72
+ * SYSTEM PREFERENCE (Automatic Dark Mode)
73
+ * ============================================================================= */
74
+
75
+ @media (prefers-color-scheme: dark) {
76
+ :root:not([data-theme="light"]) {
77
+ --kol-surface-primary: #121215;
78
+ --kol-surface-on-primary: #FAFAFA;
79
+
80
+ --kol-surface-secondary: #19191D;
81
+ --kol-surface-on-secondary: #F8F8F8;
82
+
83
+ --kol-surface-tertiary: #0E0E11;
84
+ --kol-surface-on-tertiary: #FFFFFF;
85
+
86
+ --kol-surface-inverse: #FCFBF8;
87
+ --kol-surface-on-inverse: #0E0E11;
88
+ }
89
+ }
90
+
91
+ /* =============================================================================
92
+ * CONTEXT-AWARE SURFACE INVERSE
93
+ * ============================================================================= */
94
+
95
+ .bg-surface-inverse {
96
+ background-color: var(--kol-surface-inverse);
97
+ color: var(--kol-surface-on-inverse);
98
+
99
+ --kol-surface-primary: var(--kol-surface-inverse);
100
+ --kol-surface-on-primary: var(--kol-surface-on-inverse);
101
+ --kol-surface-secondary: var(--kol-surface-secondary);
102
+ --kol-surface-on-secondary: var(--kol-surface-on-inverse);
103
+ --kol-surface-tertiary: var(--kol-surface-tertiary);
104
+ --kol-surface-on-tertiary: var(--kol-surface-on-inverse);
105
+ --kol-border-default: color-mix(in srgb, var(--kol-surface-on-inverse) 8%, transparent);
106
+
107
+ /* Re-declare fg-ramp against on-inverse so opacity tokens flip with surface.
108
+ * CSS substitutes inner var() at the declaration site, so the :root declarations
109
+ * bake the on-primary color and don't re-resolve here. Redeclaring here lets every
110
+ * --kol-fg-* consumer (borders, dividers, dimmed text) automatically contrast-flip. */
111
+ --kol-fg-01: color-mix(in srgb, var(--kol-surface-on-inverse) 1%, transparent);
112
+ --kol-fg-02: color-mix(in srgb, var(--kol-surface-on-inverse) 2%, transparent);
113
+ --kol-fg-04: color-mix(in srgb, var(--kol-surface-on-inverse) 4%, transparent);
114
+ --kol-fg-08: color-mix(in srgb, var(--kol-surface-on-inverse) 8%, transparent);
115
+ --kol-fg-12: color-mix(in srgb, var(--kol-surface-on-inverse) 12%, transparent);
116
+ --kol-fg-16: color-mix(in srgb, var(--kol-surface-on-inverse) 16%, transparent);
117
+ --kol-fg-24: color-mix(in srgb, var(--kol-surface-on-inverse) 24%, transparent);
118
+ --kol-fg-32: color-mix(in srgb, var(--kol-surface-on-inverse) 32%, transparent);
119
+ --kol-fg-40: color-mix(in srgb, var(--kol-surface-on-inverse) 40%, transparent);
120
+ --kol-fg-48: color-mix(in srgb, var(--kol-surface-on-inverse) 48%, transparent);
121
+ --kol-fg-64: color-mix(in srgb, var(--kol-surface-on-inverse) 64%, transparent);
122
+ --kol-fg-80: color-mix(in srgb, var(--kol-surface-on-inverse) 80%, transparent);
123
+ --kol-fg-88: color-mix(in srgb, var(--kol-surface-on-inverse) 88%, transparent);
124
+ --kol-fg-96: color-mix(in srgb, var(--kol-surface-on-inverse) 96%, transparent);
125
+ }
126
+
127
+ /* =============================================================================
128
+ * UTILITY CLASSES (HEAVILY USED — Based on usage audit)
129
+ *
130
+ * - .text-fg-* (594 references) live in kol-opacity.css
131
+ * - .border-fg-* / .bg-fg-* live in kol-opacity.css
132
+ *
133
+ * Below: surface + elevation + basic + state classes that consume the surface
134
+ * tier directly (not through opacity ramps).
135
+ * ============================================================================= */
136
+
137
+ /* ---------------------------------------------------------------------------
138
+ * Surface Utilities
139
+ * --------------------------------------------------------------------------- */
140
+
141
+ .bg-surface-primary {
142
+ background-color: var(--kol-surface-primary);
143
+ color: var(--kol-surface-on-primary);
144
+ }
145
+
146
+ .bg-surface-secondary {
147
+ background-color: var(--kol-surface-secondary);
148
+ color: var(--kol-surface-on-secondary);
149
+ }
150
+
151
+ .bg-surface-tertiary {
152
+ background-color: var(--kol-surface-tertiary);
153
+ color: var(--kol-surface-on-tertiary);
154
+ }
155
+
156
+ .bg-surface-inverse {
157
+ background-color: var(--kol-surface-inverse);
158
+ color: var(--kol-surface-on-inverse);
159
+ }
160
+
161
+ /* ---------------------------------------------------------------------------
162
+ * Elevation Utilities
163
+ * --------------------------------------------------------------------------- */
164
+
165
+ .elevation-base {
166
+ background-color: var(--kol-surface-primary);
167
+ color: var(--kol-surface-on-primary);
168
+ }
169
+
170
+ .elevation-raised {
171
+ background-color: var(--kol-surface-secondary);
172
+ color: var(--kol-surface-on-secondary);
173
+ }
174
+
175
+ .elevation-elevated {
176
+ background-color: var(--kol-surface-tertiary);
177
+ color: var(--kol-surface-on-tertiary);
178
+ }
179
+
180
+ /* ---------------------------------------------------------------------------
181
+ * Basic Utilities
182
+ * --------------------------------------------------------------------------- */
183
+
184
+ .text-auto {
185
+ color: var(--kol-surface-on-primary);
186
+ }
187
+
188
+ .text-inverse {
189
+ color: var(--kol-surface-on-inverse);
190
+ }
191
+
192
+ .bg-auto {
193
+ background-color: var(--kol-surface-primary);
194
+ }
195
+
196
+ .bg-fg {
197
+ background-color: var(--kol-surface-on-primary);
198
+ }
199
+
200
+ .border-auto {
201
+ border-color: var(--kol-border-default);
202
+ }
203
+
204
+ .divider-auto {
205
+ border-color: var(--kol-border-default);
206
+ border-width: 1px;
207
+ }
208
+
209
+ /* ---------------------------------------------------------------------------
210
+ * Surface-based Borders (for contrast on bg-fg fills)
211
+ * --------------------------------------------------------------------------- */
212
+
213
+ .border-surface {
214
+ border-color: var(--kol-surface-primary);
215
+ }
216
+
217
+ .border-surface-08 {
218
+ border-color: color-mix(in srgb, var(--kol-surface-primary) 8%, transparent);
219
+ }
220
+
221
+ .border-surface-16 {
222
+ border-color: color-mix(in srgb, var(--kol-surface-primary) 16%, transparent);
223
+ }
224
+
225
+ /* ---------------------------------------------------------------------------
226
+ * State Utilities
227
+ * --------------------------------------------------------------------------- */
228
+
229
+ .hover\:border-hover:hover {
230
+ border-color: var(--kol-border-default);
231
+ }
232
+
233
+ .focus\:border-focus:focus {
234
+ border-color: var(--kol-border-focus);
235
+ }
236
+
237
+ .focus-visible\:border-focus:focus-visible {
238
+ border-color: var(--kol-border-focus);
239
+ }
240
+
241
+ .focus-visible\:ring-focus:focus-visible {
242
+ outline: 2px solid var(--kol-focus-ring);
243
+ outline-offset: 2px;
244
+ }
245
+
246
+ /* ---------------------------------------------------------------------------
247
+ * Absolute Colors
248
+ * --------------------------------------------------------------------------- */
249
+
250
+ .bg-absolute-white {
251
+ background-color: var(--kol-color-absolute-white);
252
+ }
253
+
254
+ .bg-absolute-black {
255
+ background-color: var(--kol-color-absolute-black);
256
+ }
257
+
258
+ .text-absolute-white {
259
+ color: var(--kol-color-absolute-white);
260
+ }
261
+
262
+ .text-absolute-black {
263
+ color: var(--kol-color-absolute-black);
264
+ }
265
+
266
+ /* =============================================================================
267
+ * TAILWIND CONTRACT — color exposures (DS layer)
268
+ *
269
+ * Tailwind v4 generates utilities from --color-* tokens. UI state lives here
270
+ * (DS-level). Brand role + brand ramps + cream are registered in
271
+ * kol-brand-color.css (loaded after this file when client branding is desired).
272
+ * ============================================================================= */
273
+
274
+ @theme {
275
+ /* UI state — conventional Tailwind hexes, disconnected from brand ramps. */
276
+ --color-ui-error: var(--ui-error);
277
+ --color-ui-warning: var(--ui-warning);
278
+ --color-ui-info: var(--ui-info);
279
+ --color-ui-success: var(--ui-success);
280
+ }