Behive Tech Registry

Base Styles

v0.3.0

pnpm add @behivetech/theme.base-styles

registry/behivetech/theme/base-styles

breakpoints.scss
1$breakpoint-sm: 40rem;
2$breakpoint-md: 48rem;
3$breakpoint-lg: 64rem;
4$breakpoint-xl: 80rem;
5$breakpoint-2xl: 96rem;
6
7@mixin sm {
8 @media (min-width: $breakpoint-sm) {
9 @content;
10 }
11}
12@mixin md {
13 @media (min-width: $breakpoint-md) {
14 @content;
15 }
16}
17@mixin lg {
18 @media (min-width: $breakpoint-lg) {
19 @content;
20 }
21}
22@mixin xl {
23 @media (min-width: $breakpoint-xl) {
24 @content;
25 }
26}
27@mixin xxl {
28 @media (min-width: $breakpoint-2xl) {
29 @content;
30 }
31}
tokens.scss
1// GENERATED by @behivetech/theme.base-styles — do not edit by hand.
2//
3// Regenerate: BRAND_SOURCE=#2C1760 BRAND_SCHEME=tonalspot \
4// pnpm --filter @behivetech/theme.base-styles tokens
5//
6// Source color: #2C1760 Scheme: tonalspot Tertiary: derived
7//
8// Both schemes are emitted from one palette. A consumer picks between them by
9// doing nothing (the `prefers-color-scheme` query answers the OS) or by setting
10// `data-theme="light" | "dark"` on a root element to force one. An app should
11// never re-declare color values to select a theme; that is what produced four
12// different accent colors across this ecosystem.
13
14:root {
15 color-scheme: light dark;
16
17 // ---- Color: light scheme -------------------------------------------------
18 --md-sys-color-primary: #64558f;
19 --md-sys-color-on-primary: #ffffff;
20 --md-sys-color-primary-container: #e8ddff;
21 --md-sys-color-on-primary-container: #4c3e76;
22 --md-sys-color-secondary: #615b71;
23 --md-sys-color-on-secondary: #ffffff;
24 --md-sys-color-secondary-container: #e8def8;
25 --md-sys-color-on-secondary-container: #494458;
26 --md-sys-color-tertiary: #7d5261;
27 --md-sys-color-on-tertiary: #ffffff;
28 --md-sys-color-tertiary-container: #ffd9e3;
29 --md-sys-color-on-tertiary-container: #633b49;
30 --md-sys-color-error: #ba1a1a;
31 --md-sys-color-on-error: #ffffff;
32 --md-sys-color-error-container: #ffdad6;
33 --md-sys-color-on-error-container: #93000a;
34 --md-sys-color-background: #f9f9f9;
35 --md-sys-color-on-background: #1b1b1b;
36 --md-sys-color-surface: #f9f9f9;
37 --md-sys-color-on-surface: #1b1b1b;
38 --md-sys-color-surface-variant: #e2e2e2;
39 --md-sys-color-on-surface-variant: #474747;
40 --md-sys-color-surface-dim: #dadada;
41 --md-sys-color-surface-bright: #f9f9f9;
42 --md-sys-color-surface-container-lowest: #ffffff;
43 --md-sys-color-surface-container-low: #f3f3f3;
44 --md-sys-color-surface-container: #eeeeee;
45 --md-sys-color-surface-container-high: #e8e8e8;
46 --md-sys-color-surface-container-highest: #e2e2e2;
47 --md-sys-color-outline: #777777;
48 --md-sys-color-outline-variant: #c6c6c6;
49 --md-sys-color-inverse-surface: #303030;
50 --md-sys-color-inverse-on-surface: #f1f1f1;
51 --md-sys-color-inverse-primary: #cebdfe;
52 --md-sys-color-scrim: #000000;
53 --md-sys-color-shadow: #000000;
54
55 // ---- Typography ----------------------------------------------------------
56 //
57 // Families are indirected through two variables so an app re-points the whole
58 // scale in two lines instead of fifteen.
59 --md-sys-typescale-body-font: "Inter", system-ui, -apple-system, sans-serif;
60 --md-sys-typescale-heading-font:
61 "Inter", system-ui, -apple-system, sans-serif;
62 --md-sys-typescale-mono-font: "JetBrains Mono", "Fira Code", monospace;
63
64 --md-sys-typescale-display-large-font: var(--md-sys-typescale-heading-font);
65 --md-sys-typescale-display-large-size: 3.5625rem;
66 --md-sys-typescale-display-large-line-height: 4rem;
67 --md-sys-typescale-display-large-weight: 400;
68 --md-sys-typescale-display-large-tracking: -0.0044em;
69
70 --md-sys-typescale-display-medium-font: var(--md-sys-typescale-heading-font);
71 --md-sys-typescale-display-medium-size: 2.8125rem;
72 --md-sys-typescale-display-medium-line-height: 3.25rem;
73 --md-sys-typescale-display-medium-weight: 400;
74 --md-sys-typescale-display-medium-tracking: 0em;
75
76 --md-sys-typescale-display-small-font: var(--md-sys-typescale-heading-font);
77 --md-sys-typescale-display-small-size: 2.25rem;
78 --md-sys-typescale-display-small-line-height: 2.75rem;
79 --md-sys-typescale-display-small-weight: 400;
80 --md-sys-typescale-display-small-tracking: 0em;
81
82 --md-sys-typescale-headline-large-font: var(--md-sys-typescale-heading-font);
83 --md-sys-typescale-headline-large-size: 2rem;
84 --md-sys-typescale-headline-large-line-height: 2.5rem;
85 --md-sys-typescale-headline-large-weight: 400;
86 --md-sys-typescale-headline-large-tracking: 0em;
87
88 --md-sys-typescale-headline-medium-font: var(--md-sys-typescale-heading-font);
89 --md-sys-typescale-headline-medium-size: 1.75rem;
90 --md-sys-typescale-headline-medium-line-height: 2.25rem;
91 --md-sys-typescale-headline-medium-weight: 400;
92 --md-sys-typescale-headline-medium-tracking: 0em;
93
94 --md-sys-typescale-headline-small-font: var(--md-sys-typescale-heading-font);
95 --md-sys-typescale-headline-small-size: 1.5rem;
96 --md-sys-typescale-headline-small-line-height: 2rem;
97 --md-sys-typescale-headline-small-weight: 400;
98 --md-sys-typescale-headline-small-tracking: 0em;
99
100 --md-sys-typescale-title-large-font: var(--md-sys-typescale-body-font);
101 --md-sys-typescale-title-large-size: 1.375rem;
102 --md-sys-typescale-title-large-line-height: 1.75rem;
103 --md-sys-typescale-title-large-weight: 400;
104 --md-sys-typescale-title-large-tracking: 0em;
105
106 --md-sys-typescale-title-medium-font: var(--md-sys-typescale-body-font);
107 --md-sys-typescale-title-medium-size: 1rem;
108 --md-sys-typescale-title-medium-line-height: 1.5rem;
109 --md-sys-typescale-title-medium-weight: 500;
110 --md-sys-typescale-title-medium-tracking: 0.0094em;
111
112 --md-sys-typescale-title-small-font: var(--md-sys-typescale-body-font);
113 --md-sys-typescale-title-small-size: 0.875rem;
114 --md-sys-typescale-title-small-line-height: 1.25rem;
115 --md-sys-typescale-title-small-weight: 500;
116 --md-sys-typescale-title-small-tracking: 0.0071em;
117
118 --md-sys-typescale-body-large-font: var(--md-sys-typescale-body-font);
119 --md-sys-typescale-body-large-size: 1rem;
120 --md-sys-typescale-body-large-line-height: 1.5rem;
121 --md-sys-typescale-body-large-weight: 400;
122 --md-sys-typescale-body-large-tracking: 0.0313em;
123
124 --md-sys-typescale-body-medium-font: var(--md-sys-typescale-body-font);
125 --md-sys-typescale-body-medium-size: 0.875rem;
126 --md-sys-typescale-body-medium-line-height: 1.25rem;
127 --md-sys-typescale-body-medium-weight: 400;
128 --md-sys-typescale-body-medium-tracking: 0.0179em;
129
130 --md-sys-typescale-body-small-font: var(--md-sys-typescale-body-font);
131 --md-sys-typescale-body-small-size: 0.75rem;
132 --md-sys-typescale-body-small-line-height: 1rem;
133 --md-sys-typescale-body-small-weight: 400;
134 --md-sys-typescale-body-small-tracking: 0.0333em;
135
136 --md-sys-typescale-label-large-font: var(--md-sys-typescale-body-font);
137 --md-sys-typescale-label-large-size: 0.875rem;
138 --md-sys-typescale-label-large-line-height: 1.25rem;
139 --md-sys-typescale-label-large-weight: 500;
140 --md-sys-typescale-label-large-tracking: 0.0071em;
141
142 --md-sys-typescale-label-medium-font: var(--md-sys-typescale-body-font);
143 --md-sys-typescale-label-medium-size: 0.75rem;
144 --md-sys-typescale-label-medium-line-height: 1rem;
145 --md-sys-typescale-label-medium-weight: 500;
146 --md-sys-typescale-label-medium-tracking: 0.0417em;
147
148 --md-sys-typescale-label-small-font: var(--md-sys-typescale-body-font);
149 --md-sys-typescale-label-small-size: 0.6875rem;
150 --md-sys-typescale-label-small-line-height: 1rem;
151 --md-sys-typescale-label-small-weight: 500;
152 --md-sys-typescale-label-small-tracking: 0.0455em;
153
154 // ---- Elevation -----------------------------------------------------------
155 --md-sys-elevation-0: none;
156 --md-sys-elevation-1:
157 0 1px 2px 0 rgba(0, 0, 0, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.15);
158 --md-sys-elevation-2:
159 0 1px 2px 0 rgba(0, 0, 0, 0.3), 0 2px 6px 2px rgba(0, 0, 0, 0.15);
160 --md-sys-elevation-3:
161 0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 4px 8px 3px rgba(0, 0, 0, 0.15);
162 --md-sys-elevation-4:
163 0 2px 3px 0 rgba(0, 0, 0, 0.3), 0 6px 10px 4px rgba(0, 0, 0, 0.15);
164 --md-sys-elevation-5:
165 0 4px 4px 0 rgba(0, 0, 0, 0.3), 0 8px 12px 6px rgba(0, 0, 0, 0.15);
166
167 // ---- Shape ---------------------------------------------------------------
168 --md-sys-shape-corner-none: 0;
169 --md-sys-shape-corner-extra-small: 4px;
170 --md-sys-shape-corner-small: 8px;
171 --md-sys-shape-corner-medium: 12px;
172 --md-sys-shape-corner-large: 16px;
173 --md-sys-shape-corner-extra-large: 28px;
174 --md-sys-shape-corner-full: 9999px;
175
176 // ---- State layers --------------------------------------------------------
177 --md-sys-state-hover-opacity: 0.08;
178 --md-sys-state-focus-opacity: 0.1;
179 --md-sys-state-pressed-opacity: 0.1;
180 --md-sys-state-dragged-opacity: 0.16;
181
182 // ---- Motion --------------------------------------------------------------
183 --md-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
184 --md-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
185 --md-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1);
186 --md-sys-motion-easing-emphasized: cubic-bezier(0.2, 0, 0, 1);
187 --md-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);
188 --md-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);
189 --md-sys-motion-easing-linear: linear;
190
191 --md-sys-motion-duration-short-1: 50ms;
192 --md-sys-motion-duration-short-2: 100ms;
193 --md-sys-motion-duration-short-3: 150ms;
194 --md-sys-motion-duration-short-4: 200ms;
195 --md-sys-motion-duration-medium-1: 250ms;
196 --md-sys-motion-duration-medium-2: 300ms;
197 --md-sys-motion-duration-medium-3: 350ms;
198 --md-sys-motion-duration-medium-4: 400ms;
199 --md-sys-motion-duration-long-1: 450ms;
200 --md-sys-motion-duration-long-2: 500ms;
201 --md-sys-motion-duration-long-3: 550ms;
202 --md-sys-motion-duration-long-4: 600ms;
203 --md-sys-motion-duration-extra-long-1: 700ms;
204 --md-sys-motion-duration-extra-long-2: 800ms;
205 --md-sys-motion-duration-extra-long-3: 900ms;
206 --md-sys-motion-duration-extra-long-4: 1000ms;
207}
208
209// ---- Color: dark scheme ----------------------------------------------------
210//
211// Applied when the OS asks for dark and the document has not forced light, or
212// when a root element forces dark outright.
213@media (prefers-color-scheme: dark) {
214 :root:not([data-theme="light"]) {
215 --md-sys-color-primary: #cebdfe;
216 --md-sys-color-on-primary: #35275d;
217 --md-sys-color-primary-container: #4c3e76;
218 --md-sys-color-on-primary-container: #e8ddff;
219 --md-sys-color-secondary: #cbc3dc;
220 --md-sys-color-on-secondary: #332e41;
221 --md-sys-color-secondary-container: #494458;
222 --md-sys-color-on-secondary-container: #e8def8;
223 --md-sys-color-tertiary: #efb8c9;
224 --md-sys-color-on-tertiary: #492532;
225 --md-sys-color-tertiary-container: #633b49;
226 --md-sys-color-on-tertiary-container: #ffd9e3;
227 --md-sys-color-error: #ffb4ab;
228 --md-sys-color-on-error: #690005;
229 --md-sys-color-error-container: #93000a;
230 --md-sys-color-on-error-container: #ffdad6;
231 --md-sys-color-background: #131313;
232 --md-sys-color-on-background: #e2e2e2;
233 --md-sys-color-surface: #131313;
234 --md-sys-color-on-surface: #e2e2e2;
235 --md-sys-color-surface-variant: #474747;
236 --md-sys-color-on-surface-variant: #c6c6c6;
237 --md-sys-color-surface-dim: #131313;
238 --md-sys-color-surface-bright: #393939;
239 --md-sys-color-surface-container-lowest: #0e0e0e;
240 --md-sys-color-surface-container-low: #1b1b1b;
241 --md-sys-color-surface-container: #1f1f1f;
242 --md-sys-color-surface-container-high: #2a2a2a;
243 --md-sys-color-surface-container-highest: #353535;
244 --md-sys-color-outline: #919191;
245 --md-sys-color-outline-variant: #474747;
246 --md-sys-color-inverse-surface: #e2e2e2;
247 --md-sys-color-inverse-on-surface: #303030;
248 --md-sys-color-inverse-primary: #64558f;
249 --md-sys-color-scrim: #000000;
250 --md-sys-color-shadow: #000000;
251 }
252}
253
254:root[data-theme="dark"] {
255 --md-sys-color-primary: #cebdfe;
256 --md-sys-color-on-primary: #35275d;
257 --md-sys-color-primary-container: #4c3e76;
258 --md-sys-color-on-primary-container: #e8ddff;
259 --md-sys-color-secondary: #cbc3dc;
260 --md-sys-color-on-secondary: #332e41;
261 --md-sys-color-secondary-container: #494458;
262 --md-sys-color-on-secondary-container: #e8def8;
263 --md-sys-color-tertiary: #efb8c9;
264 --md-sys-color-on-tertiary: #492532;
265 --md-sys-color-tertiary-container: #633b49;
266 --md-sys-color-on-tertiary-container: #ffd9e3;
267 --md-sys-color-error: #ffb4ab;
268 --md-sys-color-on-error: #690005;
269 --md-sys-color-error-container: #93000a;
270 --md-sys-color-on-error-container: #ffdad6;
271 --md-sys-color-background: #131313;
272 --md-sys-color-on-background: #e2e2e2;
273 --md-sys-color-surface: #131313;
274 --md-sys-color-on-surface: #e2e2e2;
275 --md-sys-color-surface-variant: #474747;
276 --md-sys-color-on-surface-variant: #c6c6c6;
277 --md-sys-color-surface-dim: #131313;
278 --md-sys-color-surface-bright: #393939;
279 --md-sys-color-surface-container-lowest: #0e0e0e;
280 --md-sys-color-surface-container-low: #1b1b1b;
281 --md-sys-color-surface-container: #1f1f1f;
282 --md-sys-color-surface-container-high: #2a2a2a;
283 --md-sys-color-surface-container-highest: #353535;
284 --md-sys-color-outline: #919191;
285 --md-sys-color-outline-variant: #474747;
286 --md-sys-color-inverse-surface: #e2e2e2;
287 --md-sys-color-inverse-on-surface: #303030;
288 --md-sys-color-inverse-primary: #64558f;
289 --md-sys-color-scrim: #000000;
290 --md-sys-color-shadow: #000000;
291}
292
293// ---- Compatibility aliases -------------------------------------------------
294//
295// The pre-MD3 token names, re-pointed at their nearest MD3 role so that every
296// existing component keeps working unchanged while packages migrate one at a
297// time. **These are scheduled for removal** — a component still reading
298// `--color-primary` has not been migrated yet, and grepping for these names is
299// how you find the remaining work.
300//
301// Two of them cannot be faithful and are called out rather than fudged:
302// * `--color-surface-light` had no MD3 equivalent; it maps to
303// `surface-container-high`, which is the nearest role by intent.
304// * `--color-text-disabled` was a fixed translucent black/white. MD3 expresses
305// disabled as 38% of `on-surface`, which `color-mix` reproduces exactly.
306:root {
307 --color-background: var(--md-sys-color-background);
308 --color-primary: var(--md-sys-color-primary);
309 --color-on-primary: var(--md-sys-color-on-primary);
310
311 --color-text-body: var(--md-sys-color-on-surface);
312 --color-text-heading: var(--md-sys-color-on-surface);
313 --color-text-muted: var(--md-sys-color-on-surface-variant);
314 --color-text-disabled: color-mix(
315 in srgb,
316 var(--md-sys-color-on-surface) 38%,
317 transparent
318 );
319
320 --color-link: var(--md-sys-color-primary);
321 --color-link-hover: var(--md-sys-color-primary);
322 --color-link-active: var(--md-sys-color-primary);
323 --color-link-visited: var(--md-sys-color-primary);
324
325 --color-surface: var(--md-sys-color-surface);
326 --color-on-surface: var(--md-sys-color-on-surface);
327 --color-surface-light: var(--md-sys-color-surface-container-high);
328 --color-on-surface-light: var(--md-sys-color-on-surface);
329 --color-surface-raised: var(--md-sys-color-surface-container);
330 --color-overlay: color-mix(
331 in srgb,
332 var(--md-sys-color-scrim) 50%,
333 transparent
334 );
335
336 --color-border: var(--md-sys-color-outline-variant);
337 --color-border-strong: var(--md-sys-color-outline);
338 --color-border-focus: var(--md-sys-color-primary);
339
340 --color-error: var(--md-sys-color-error);
341 --color-error-surface: var(--md-sys-color-error-container);
342 --color-success: #48bb78;
343 --color-success-surface: rgba(72, 187, 120, 0.15);
344 --color-warning: #ed8936;
345 --color-warning-surface: rgba(237, 137, 54, 0.15);
346 --color-info: var(--md-sys-color-tertiary);
347 --color-info-surface: var(--md-sys-color-tertiary-container);
348
349 // Spacing, radius, shadow, type scale and z-index keep their old names and
350 // values: nothing about them was wrong, and renaming them would churn every
351 // stylesheet for no gain. Radius and shadow stay in px on purpose — corners
352 // and shadow geometry are not text metrics and should not scale with the
353 // reader's font size. Spacing and type sizes are rem, which is why they do.
354 --spacing-1: 0.25rem;
355 --spacing-2: 0.5rem;
356 --spacing-3: 0.75rem;
357 --spacing-4: 1rem;
358 --spacing-5: 1.25rem;
359 --spacing-6: 1.5rem;
360 --spacing-8: 2rem;
361 --spacing-10: 2.5rem;
362 --spacing-12: 3rem;
363 --spacing-16: 4rem;
364 --spacing-20: 5rem;
365 --spacing-24: 6rem;
366
367 --font-body: var(--md-sys-typescale-body-font);
368 --font-heading: var(--md-sys-typescale-heading-font);
369 --font-mono: var(--md-sys-typescale-mono-font);
370
371 --text-xs: 0.75rem;
372 --text-sm: 0.875rem;
373 --text-base: 1rem;
374 --text-lg: 1.125rem;
375 --text-xl: 1.25rem;
376 --text-2xl: 1.5rem;
377 --text-3xl: 1.875rem;
378 --text-4xl: 2.25rem;
379 --text-5xl: 3rem;
380
381 --font-weight-normal: 400;
382 --font-weight-medium: 500;
383 --font-weight-semibold: 600;
384 --font-weight-bold: 700;
385
386 --leading-none: 1;
387 --leading-tight: 1.25;
388 --leading-snug: 1.375;
389 --leading-normal: 1.5;
390 --leading-relaxed: 1.625;
391 --leading-loose: 2;
392
393 --tracking-tight: -0.025em;
394 --tracking-normal: 0;
395 --tracking-wide: 0.025em;
396 --tracking-wider: 0.05em;
397 --tracking-widest: 0.1em;
398
399 --radius-sm: var(--md-sys-shape-corner-extra-small);
400 --radius-md: var(--md-sys-shape-corner-small);
401 --radius-lg: var(--md-sys-shape-corner-medium);
402 --radius-xl: var(--md-sys-shape-corner-large);
403 --radius-2xl: var(--md-sys-shape-corner-extra-large);
404 --radius-full: var(--md-sys-shape-corner-full);
405
406 --shadow-sm: var(--md-sys-elevation-1);
407 --shadow-md: var(--md-sys-elevation-2);
408 --shadow-lg: var(--md-sys-elevation-3);
409 --shadow-xl: var(--md-sys-elevation-4);
410 --shadow-inner: inset 0 2px 4px rgba(0, 0, 0, 0.3);
411
412 // Z-index is unchanged. See the note kept from the original file: surfaces
413 // (base -> modal) nest normally, while transient layers (dropdown -> tooltip)
414 // are portalled to document.body and are therefore *siblings* of the modal
415 // that opened them — raw z-index is the only thing ordering them, so every
416 // transient layer must outrank every surface.
417 --z-base: 0;
418 --z-raised: 10;
419 --z-sticky: 200;
420 --z-overlay: 300;
421 --z-modal: 400;
422 --z-dropdown: 450;
423 --z-toast: 500;
424 --z-tooltip: 600;
425
426 --transition-fast: var(--md-sys-motion-duration-short-3)
427 var(--md-sys-motion-easing-standard);
428 --transition-base: var(--md-sys-motion-duration-short-4)
429 var(--md-sys-motion-easing-standard);
430 --transition-slow: var(--md-sys-motion-duration-medium-2)
431 var(--md-sys-motion-easing-standard);
432 --transition-slower: var(--md-sys-motion-duration-long-2)
433 var(--md-sys-motion-easing-standard);
434}
435
436*,
437*::before,
438*::after {
439 box-sizing: border-box;
440}
441
442html,
443body {
444 margin: 0;
445 padding: 0;
446 border: 0;
447}
448
449html {
450 font-family: var(--md-sys-typescale-body-font);
451 font-size: var(--md-sys-typescale-body-large-size);
452 line-height: var(--md-sys-typescale-body-large-line-height);
453 letter-spacing: var(--md-sys-typescale-body-large-tracking);
454 color: var(--md-sys-color-on-background);
455 background-color: var(--md-sys-color-background);
456 -webkit-font-smoothing: antialiased;
457 -moz-osx-font-smoothing: grayscale;
458}
index.ts
1// Design tokens and breakpoints for the Behive Tech component library.
2//
3// Styles are shipped as raw SCSS and consumed directly:
4// @use '@behivetech/theme.base-styles/breakpoints' as bp; // mixins: bp.md { ... }
5// import '@behivetech/theme.base-styles/tokens.scss'; // global CSS custom properties
6//
7// This entry mirrors breakpoints.scss as JS values for use in scripts
8// (e.g. window.matchMedia) so the two never drift.
9
10export const breakpoints = {
11 sm: 640,
12 md: 768,
13 lg: 1024,
14 xl: 1280,
15 "2xl": 1536,
16} as const;
17
18export type Breakpoint = keyof typeof breakpoints;
19
20export function minWidth(bp: Breakpoint): string {
21 return `(min-width: ${breakpoints[bp]}px)`;
22}