@mastors/core 1.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/LICENSE +21 -0
- package/README.md +940 -0
- package/api/_index.scss +5 -0
- package/dist/mastors-core.css +7419 -0
- package/dist/mastors-core.css.map +1 -0
- package/package.json +73 -0
- package/postinstall.js +41 -0
- package/scripts/generate-tokens.js +259 -0
- package/scss/abstracts/_index.scss +6 -0
- package/scss/abstracts/_maps.scss +9 -0
- package/scss/abstracts/_placeholders.scss +7 -0
- package/scss/accessibility/_focus.scss +21 -0
- package/scss/accessibility/_index.scss +7 -0
- package/scss/accessibility/_motion.scss +14 -0
- package/scss/accessibility/_print.scss +52 -0
- package/scss/accessibility/_screen-reader.scss +31 -0
- package/scss/api/_index.scss +14 -0
- package/scss/base/_box-sizing.scss +6 -0
- package/scss/base/_index.scss +7 -0
- package/scss/base/_reset.scss +59 -0
- package/scss/base/_root.scss +43 -0
- package/scss/base/_typography-base.scss +40 -0
- package/scss/config/_flags.scss +13 -0
- package/scss/config/_index.scss +12 -0
- package/scss/config/_settings.scss +18 -0
- package/scss/functions/_color.scss +66 -0
- package/scss/functions/_em.scss +28 -0
- package/scss/functions/_index.scss +15 -0
- package/scss/functions/_map-helpers.scss +29 -0
- package/scss/functions/_math.scss +40 -0
- package/scss/functions/_rem.scss +27 -0
- package/scss/functions/_string.scss +57 -0
- package/scss/functions/_vars.scss +49 -0
- package/scss/generators/_class-generator.scss +83 -0
- package/scss/generators/_custom-property-generator.scss +29 -0
- package/scss/generators/_index.scss +6 -0
- package/scss/generators/_responsive-generator.scss +28 -0
- package/scss/helpers/_clearfix.scss +9 -0
- package/scss/helpers/_index.scss +7 -0
- package/scss/helpers/_ratio.scss +22 -0
- package/scss/helpers/_truncate.scss +25 -0
- package/scss/helpers/_visually-hidden.scss +39 -0
- package/scss/index.scss +41 -0
- package/scss/mixins/_breakpoint.scss +33 -0
- package/scss/mixins/_container.scss +20 -0
- package/scss/mixins/_elevation.scss +12 -0
- package/scss/mixins/_index.scss +9 -0
- package/scss/mixins/_pseudo.scss +13 -0
- package/scss/mixins/_theme.scss +31 -0
- package/scss/mixins/_transition.scss +20 -0
- package/scss/responsive/_container-queries.scss +31 -0
- package/scss/responsive/_engine.scss +65 -0
- package/scss/responsive/_fluid-type.scss +40 -0
- package/scss/responsive/_index.scss +6 -0
- package/scss/semantic/_colors.scss +29 -0
- package/scss/semantic/_index.scss +6 -0
- package/scss/semantic/_spacing.scss +13 -0
- package/scss/semantic/_typography.scss +13 -0
- package/scss/themes/_base-theme.scss +28 -0
- package/scss/themes/_dark.scss +59 -0
- package/scss/themes/_index.scss +6 -0
- package/scss/themes/_light.scss +31 -0
- package/scss/tokens/_color.scss +100 -0
- package/scss/tokens/_index.scss +12 -0
- package/scss/tokens/_opacity.scss +28 -0
- package/scss/tokens/_radii.scss +21 -0
- package/scss/tokens/_shadows.scss +20 -0
- package/scss/tokens/_sizing.scss +47 -0
- package/scss/tokens/_spacing.scss +48 -0
- package/scss/tokens/_transitions.scss +27 -0
- package/scss/tokens/_typography.scss +63 -0
- package/scss/tokens/_z-index.scss +21 -0
- package/scss/utilities/_animation.scss +125 -0
- package/scss/utilities/_borders.scss +55 -0
- package/scss/utilities/_colors.scss +42 -0
- package/scss/utilities/_cursor.scss +28 -0
- package/scss/utilities/_display.scss +26 -0
- package/scss/utilities/_index.scss +20 -0
- package/scss/utilities/_interaction.scss +156 -0
- package/scss/utilities/_layout.scss +162 -0
- package/scss/utilities/_opacity.scss +9 -0
- package/scss/utilities/_overflow.scss +36 -0
- package/scss/utilities/_pointer-events.scss +6 -0
- package/scss/utilities/_position.scss +32 -0
- package/scss/utilities/_shadows.scss +11 -0
- package/scss/utilities/_sizing.scss +40 -0
- package/scss/utilities/_spacing.scss +42 -0
- package/scss/utilities/_transform.scss +43 -0
- package/scss/utilities/_typography.scss +163 -0
- package/scss/utilities/_z-index.scss +9 -0
- package/scss/variables/_breakpoints.scss +14 -0
- package/scss/variables/_container.scss +13 -0
- package/scss/variables/_global.scss +8 -0
- package/scss/variables/_grid.scss +7 -0
- package/scss/variables/_index.scss +7 -0
- package/scss/vendors/_index.scss +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
# @mastors/core
|
|
2
|
+
|
|
3
|
+
> The foundational layer of the Mastors ecosystem — design tokens, SCSS functions, mixins, generators, reset, responsive engine, and theme system.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@mastors/core)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
[](https://sass-lang.com)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Overview](#overview)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Usage](#usage)
|
|
16
|
+
- [Full stylesheet import](#full-stylesheet-import)
|
|
17
|
+
- [Public API (zero output)](#public-api-zero-output)
|
|
18
|
+
- [TypeScript / JavaScript](#typescript--javascript)
|
|
19
|
+
- [Configuration](#configuration)
|
|
20
|
+
- [Feature flags](#feature-flags)
|
|
21
|
+
- [Dark mode strategy](#dark-mode-strategy)
|
|
22
|
+
- [Class prefix](#class-prefix)
|
|
23
|
+
- [Config via public API](#config-via-public-api)
|
|
24
|
+
- [Design Tokens](#design-tokens)
|
|
25
|
+
- [Color](#color)
|
|
26
|
+
- [Spacing](#spacing)
|
|
27
|
+
- [Typography](#typography)
|
|
28
|
+
- [Border Radius](#border-radius)
|
|
29
|
+
- [Shadows](#shadows)
|
|
30
|
+
- [Z-Index](#z-index)
|
|
31
|
+
- [Opacity](#opacity)
|
|
32
|
+
- [Transitions](#transitions)
|
|
33
|
+
- [Functions](#functions)
|
|
34
|
+
- [vars()](#vars)
|
|
35
|
+
- [Mixins](#mixins)
|
|
36
|
+
- [Breakpoints](#breakpoints)
|
|
37
|
+
- [Theme](#theme)
|
|
38
|
+
- [Elevation](#elevation)
|
|
39
|
+
- [Transition](#transition)
|
|
40
|
+
- [Container](#container)
|
|
41
|
+
- [Pseudo](#pseudo)
|
|
42
|
+
- [Responsive Engine](#responsive-engine)
|
|
43
|
+
- [Container Queries](#container-queries)
|
|
44
|
+
- [Fluid Typography](#fluid-typography)
|
|
45
|
+
- [Theme System](#theme-system)
|
|
46
|
+
- [Base Layer](#base-layer)
|
|
47
|
+
- [Utility Classes](#utility-classes)
|
|
48
|
+
- [Helpers](#helpers)
|
|
49
|
+
- [Accessibility](#accessibility)
|
|
50
|
+
- [Generator Engine](#generator-engine)
|
|
51
|
+
- [Semantic Layer](#semantic-layer)
|
|
52
|
+
- [Known Stubs](#known-stubs)
|
|
53
|
+
- [Package Exports](#package-exports)
|
|
54
|
+
- [Peer Dependencies](#peer-dependencies)
|
|
55
|
+
- [Changelog](#changelog)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Overview
|
|
60
|
+
|
|
61
|
+
`@mastors/core` is the only required package in the Mastors ecosystem. It provides:
|
|
62
|
+
|
|
63
|
+
- **Design tokens** — color, spacing, typography, radius, shadows, z-index, opacity, and transitions as SCSS maps
|
|
64
|
+
- **Functions** — `rem()`, `em()`, `color()`, `spacing()`, `tint()`, `shade()`, `alpha()`, `contrast()`, `fluid()`, `map-deep-get()`, `map-collect()`, `str-replace()`, `vars()`
|
|
65
|
+
- **Mixins** — `bp()`, `dark-mode()`, `light-mode()`, `theme()`, `elevation()`, `transition()`, `container()`, `pseudo()`
|
|
66
|
+
- **Generator engine** — `generate-utilities()`, `emit-custom-properties()`, and responsive-generator mixins used by all utility packages
|
|
67
|
+
- **Reset** — modern CSS reset and document defaults
|
|
68
|
+
- **Theme system** — CSS custom property-based light/dark theming with a full semantic contract
|
|
69
|
+
- **Responsive engine** — breakpoint-aware utility variant generation (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
|
|
70
|
+
- **Container queries** — `.cq-inline`, `.cq-size`, `cq()` mixin for `@container` rules
|
|
71
|
+
- **Fluid typography** — `fluid-type()` mixin and function using `clamp()`
|
|
72
|
+
- **Utility classes** — display, position, overflow, spacing, sizing, colors, borders (full directional radius scale), shadows, opacity, cursor, z-index, transforms, typography, animation, interaction, layout (aspect-ratio, object-fit/position, blend modes)
|
|
73
|
+
- **Accessibility** — focus ring, reduced-motion, screen-reader utilities, print layer
|
|
74
|
+
- **TypeScript types and runtime token mirror**
|
|
75
|
+
|
|
76
|
+
All other `@mastors/*` packages consume `@mastors/core/api` for shared tokens, functions, and mixins.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Installation
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install @mastors/core sass
|
|
84
|
+
# or
|
|
85
|
+
pnpm add @mastors/core sass
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`sass >= 1.80.0` is required as a peer dependency.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Full stylesheet import
|
|
95
|
+
|
|
96
|
+
Import the complete compiled stylesheet — reset, tokens, themes, utilities, helpers, and accessibility:
|
|
97
|
+
|
|
98
|
+
```scss
|
|
99
|
+
@use "@mastors/core/scss";
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Public API (zero output)
|
|
103
|
+
|
|
104
|
+
Import only the public API surface. No CSS is emitted — you get access to all tokens, functions, mixins, and config:
|
|
105
|
+
|
|
106
|
+
```scss
|
|
107
|
+
@use "@mastors/core/api" as m;
|
|
108
|
+
|
|
109
|
+
.card {
|
|
110
|
+
padding: m.spacing(6);
|
|
111
|
+
background-color: m.color("neutral", 50);
|
|
112
|
+
border-radius: m.radius("xl");
|
|
113
|
+
box-shadow: m.vars(shadow-md);
|
|
114
|
+
transition: box-shadow m.vars(duration-200) m.vars(ease-out);
|
|
115
|
+
|
|
116
|
+
@include m.bp("lg") {
|
|
117
|
+
padding: m.spacing(10);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@include m.dark-mode {
|
|
121
|
+
background-color: m.color("neutral", 800);
|
|
122
|
+
color: m.color("neutral", 100);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### TypeScript / JavaScript
|
|
128
|
+
|
|
129
|
+
Access design token values at runtime for CSS-in-JS, design tools, or testing:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { tokens } from '@mastors/core'
|
|
133
|
+
|
|
134
|
+
const primary600 = tokens.color.primary['600'] // '#2563eb'
|
|
135
|
+
const spacing4 = tokens.spacing['4'] // '1rem'
|
|
136
|
+
const shadowMd = tokens.shadow.md // '0 4px 6px ...'
|
|
137
|
+
const radiusXl = tokens.radius.xl // '0.75rem'
|
|
138
|
+
const duration200 = tokens.duration['200'] // '200ms'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Import TypeScript types:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import type {
|
|
145
|
+
MastorsConfig,
|
|
146
|
+
Breakpoint,
|
|
147
|
+
ThemeMode,
|
|
148
|
+
Tokens,
|
|
149
|
+
ColorPalette,
|
|
150
|
+
SpacingKey,
|
|
151
|
+
RadiusKey,
|
|
152
|
+
} from '@mastors/core'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
Override the global config map before importing core to customise behaviour. The config must be set before any `@use "@mastors/core"` statement in your project.
|
|
160
|
+
|
|
161
|
+
```scss
|
|
162
|
+
// styles/_config.scss — set BEFORE @use "@mastors/core"
|
|
163
|
+
@use "@mastors/core/scss/config/settings" with (
|
|
164
|
+
$mastors-config: (
|
|
165
|
+
"prefix": "", // optional class prefix, e.g. "m-" -> .m-flex
|
|
166
|
+
"important": false, // append !important to all utility declarations
|
|
167
|
+
"dark-mode": "class", // "class" | "media"
|
|
168
|
+
"rtl": false, // enable RTL logical property variants
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Feature flags
|
|
174
|
+
|
|
175
|
+
Disable any layer you don't need to reduce output size:
|
|
176
|
+
|
|
177
|
+
```scss
|
|
178
|
+
@use "@mastors/core/scss/config/flags" with (
|
|
179
|
+
$enable-utilities: true,
|
|
180
|
+
$enable-responsive: true,
|
|
181
|
+
$enable-helpers: true,
|
|
182
|
+
$enable-a11y: true,
|
|
183
|
+
$enable-themes: true,
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Dark mode strategy
|
|
188
|
+
|
|
189
|
+
**Class-based** (default) — add `.dark` or `data-theme="dark"` to `<html>`:
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<html class="dark">...</html>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Media-query** — responds automatically to the OS preference:
|
|
196
|
+
|
|
197
|
+
```scss
|
|
198
|
+
@use "@mastors/core/scss/config/settings" with (
|
|
199
|
+
$mastors-config: ("dark-mode": "media")
|
|
200
|
+
);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Class prefix
|
|
204
|
+
|
|
205
|
+
Add a prefix to every generated utility class to prevent collisions:
|
|
206
|
+
|
|
207
|
+
```scss
|
|
208
|
+
$mastors-config: ("prefix": "m-") !default;
|
|
209
|
+
// .m-flex, .m-block, .m-grid-cols-3, ...
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Config via public API
|
|
213
|
+
|
|
214
|
+
As of v1.2, both the `$mastors-config` map / `config()` accessor and all `$enable-*` flags are forwarded through the public API surface. Downstream consumers no longer need a direct partial import to read them:
|
|
215
|
+
|
|
216
|
+
```scss
|
|
217
|
+
@use "@mastors/core/api" as m;
|
|
218
|
+
|
|
219
|
+
// Read a config value
|
|
220
|
+
$prefix: m.config("prefix");
|
|
221
|
+
|
|
222
|
+
// Read feature flags
|
|
223
|
+
@if m.$enable-responsive {
|
|
224
|
+
// emit responsive variants
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Design Tokens
|
|
231
|
+
|
|
232
|
+
All tokens are available via the public API after `@use "@mastors/core/api" as m`.
|
|
233
|
+
|
|
234
|
+
### Color
|
|
235
|
+
|
|
236
|
+
Six semantic palettes, each with 11 shades (50-950), plus `white`, `black`, and `transparent`.
|
|
237
|
+
|
|
238
|
+
```scss
|
|
239
|
+
m.color("primary", 600) // #2563eb
|
|
240
|
+
m.color("neutral", 100) // #f3f4f6
|
|
241
|
+
m.color("success", 500) // #22c55e
|
|
242
|
+
m.color("warning", 400) // #fbbf24
|
|
243
|
+
m.color("error", 600) // #dc2626
|
|
244
|
+
m.color("info", 500) // #06b6d4
|
|
245
|
+
m.color("white") // #ffffff
|
|
246
|
+
m.color("black") // #000000
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Palettes: `primary` - `neutral` - `success` - `warning` - `error` - `info`
|
|
250
|
+
|
|
251
|
+
### Spacing
|
|
252
|
+
|
|
253
|
+
35-step scale from `0` to `96` (matching Tailwind's spacing scale):
|
|
254
|
+
|
|
255
|
+
```scss
|
|
256
|
+
m.spacing(0) // 0px
|
|
257
|
+
m.spacing(1) // 0.25rem
|
|
258
|
+
m.spacing(4) // 1rem
|
|
259
|
+
m.spacing(8) // 2rem
|
|
260
|
+
m.spacing(16) // 4rem
|
|
261
|
+
m.spacing(96) // 24rem
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Half-step keys (`0.5`, `1.5`, `2.5`, `3.5`) are also available:
|
|
265
|
+
|
|
266
|
+
```scss
|
|
267
|
+
m.spacing("0.5") // 0.125rem
|
|
268
|
+
m.spacing("1.5") // 0.375rem
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Typography
|
|
272
|
+
|
|
273
|
+
```scss
|
|
274
|
+
// Font sizes (xs -> 9xl)
|
|
275
|
+
m.font-size("sm") // 0.875rem
|
|
276
|
+
m.font-size("base") // 1rem
|
|
277
|
+
m.font-size("2xl") // 1.5rem
|
|
278
|
+
m.font-size("5xl") // 3rem
|
|
279
|
+
|
|
280
|
+
// Font families
|
|
281
|
+
m.font-family("sans") // system-ui, -apple-system, ...
|
|
282
|
+
m.font-family("mono") // ui-monospace, SFMono-Regular, ...
|
|
283
|
+
|
|
284
|
+
// Font weights
|
|
285
|
+
m.font-weight("semibold") // 600
|
|
286
|
+
m.font-weight("bold") // 700
|
|
287
|
+
|
|
288
|
+
// Line heights
|
|
289
|
+
m.line-height("tight") // 1.25
|
|
290
|
+
m.line-height("normal") // 1.5
|
|
291
|
+
|
|
292
|
+
// Letter spacing
|
|
293
|
+
m.letter-spacing("wide") // 0.025em
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Border Radius
|
|
297
|
+
|
|
298
|
+
```scss
|
|
299
|
+
m.radius("none") // 0px
|
|
300
|
+
m.radius("sm") // 0.125rem
|
|
301
|
+
m.radius("md") // 0.375rem
|
|
302
|
+
m.radius("lg") // 0.5rem
|
|
303
|
+
m.radius("xl") // 0.75rem
|
|
304
|
+
m.radius("2xl") // 1rem
|
|
305
|
+
m.radius("3xl") // 1.5rem
|
|
306
|
+
m.radius("full") // 9999px
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Shadows
|
|
310
|
+
|
|
311
|
+
```scss
|
|
312
|
+
m.shadow("xs") // subtle shadow
|
|
313
|
+
m.shadow("sm") // small shadow
|
|
314
|
+
m.shadow("md") // medium shadow (default)
|
|
315
|
+
m.shadow("lg") // large shadow
|
|
316
|
+
m.shadow("xl") // extra large shadow
|
|
317
|
+
m.shadow("2xl") // page-level shadow
|
|
318
|
+
m.shadow("inner") // inset shadow
|
|
319
|
+
m.shadow("none") // none
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Z-Index
|
|
323
|
+
|
|
324
|
+
```scss
|
|
325
|
+
m.z("base") // 0
|
|
326
|
+
m.z("raised") // 10
|
|
327
|
+
m.z("dropdown") // 100
|
|
328
|
+
m.z("sticky") // 200
|
|
329
|
+
m.z("overlay") // 300
|
|
330
|
+
m.z("modal") // 400
|
|
331
|
+
m.z("toast") // 500
|
|
332
|
+
m.z("tooltip") // 600
|
|
333
|
+
m.z("max") // 9999
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Opacity
|
|
337
|
+
|
|
338
|
+
```scss
|
|
339
|
+
m.opacity("0") // 0
|
|
340
|
+
m.opacity("50") // 0.5
|
|
341
|
+
m.opacity("75") // 0.75
|
|
342
|
+
m.opacity("100") // 1
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Transitions
|
|
346
|
+
|
|
347
|
+
```scss
|
|
348
|
+
m.duration("150") // 150ms
|
|
349
|
+
m.duration("200") // 200ms
|
|
350
|
+
m.duration("300") // 300ms
|
|
351
|
+
|
|
352
|
+
m.easing("in-out") // cubic-bezier(0.4, 0, 0.2, 1)
|
|
353
|
+
m.easing("out") // cubic-bezier(0, 0, 0.2, 1)
|
|
354
|
+
m.easing("bounce") // cubic-bezier(0.34, 1.56, 0.64, 1)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Functions
|
|
360
|
+
|
|
361
|
+
| Function | Description | Example |
|
|
362
|
+
|---|---|---|
|
|
363
|
+
| `rem($px)` | Convert px to rem | `rem(16px)` -> `1rem` |
|
|
364
|
+
| `em($px)` | Convert px to em | `em(16px)` -> `1em` |
|
|
365
|
+
| `color($palette, $shade)` | Get a color token | `color("primary", 600)` |
|
|
366
|
+
| `spacing($key)` | Get a spacing token | `spacing(4)` -> `1rem` |
|
|
367
|
+
| `radius($key)` | Get a radius token | `radius("xl")` -> `0.75rem` |
|
|
368
|
+
| `shadow($key)` | Get a shadow token | `shadow("md")` |
|
|
369
|
+
| `z($key)` | Get a z-index token | `z("modal")` -> `400` |
|
|
370
|
+
| `opacity($key)` | Get an opacity token | `opacity("50")` -> `0.5` |
|
|
371
|
+
| `duration($key)` | Get a duration token | `duration("200")` -> `200ms` |
|
|
372
|
+
| `easing($key)` | Get an easing token | `easing("in-out")` |
|
|
373
|
+
| `tint($c, $pct)` | Mix color with white | `tint(blue, 20%)` |
|
|
374
|
+
| `shade($c, $pct)` | Mix color with black | `shade(blue, 20%)` |
|
|
375
|
+
| `alpha($c, $a)` | Adjust alpha channel | `alpha(blue, 0.5)` |
|
|
376
|
+
| `contrast($bg)` | Black or white for contrast (1) | `contrast(#1e40af)` -> white |
|
|
377
|
+
| `fluid($min, $max)` | Clamp-based fluid value | `fluid(1rem, 2rem)` |
|
|
378
|
+
| `map-deep-get($map, $keys...)` | Deep nested map access | `map-deep-get($tokens, "primary", "600")` |
|
|
379
|
+
| `map-collect($maps...)` | Shallow-merge multiple maps | `map-collect($a, $b)` |
|
|
380
|
+
| `str-replace($str, $search)` | Replace substring | `str-replace("a-b", "-", "_")` |
|
|
381
|
+
| `vars($token, $fallback?)` | CSS custom property reference | `vars(shadow-md)` -> `var(--mastors-shadow-md)` |
|
|
382
|
+
|
|
383
|
+
(1) `contrast()` uses a simplified linear luminance approximation without sRGB gamma expansion. The threshold is set to `0.35` (not the WCAG `0.179`) to compensate for the missing gamma step — this gives correct results across the neutral scale. Suitable for UI decisions; implement full sRGB linearisation for strict WCAG 2.1 contrast-ratio auditing.
|
|
384
|
+
|
|
385
|
+
### vars()
|
|
386
|
+
|
|
387
|
+
`vars()` lets you reference any emitted design token as a CSS custom property by name, without hard-coding the `--mastors-` prefix. If the token name ever changes or the prefix is reconfigured, only the function implementation needs to update — all call sites stay the same.
|
|
388
|
+
|
|
389
|
+
```scss
|
|
390
|
+
@use "@mastors/core/api" as m;
|
|
391
|
+
|
|
392
|
+
.button {
|
|
393
|
+
// Basic token reference
|
|
394
|
+
color: m.vars(accent);
|
|
395
|
+
box-shadow: m.vars(shadow-sm);
|
|
396
|
+
|
|
397
|
+
// With CSS fallback (passed through verbatim)
|
|
398
|
+
background: m.vars(surface-raised, #f9fafb);
|
|
399
|
+
transition: opacity m.vars(duration-150) m.vars(ease-out);
|
|
400
|
+
|
|
401
|
+
&:hover {
|
|
402
|
+
box-shadow: m.vars(shadow-md);
|
|
403
|
+
transform: translateY(-1px);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Composes cleanly with other values in shorthand properties
|
|
408
|
+
.chip {
|
|
409
|
+
border: 1px solid m.vars(border);
|
|
410
|
+
padding: m.rem(4px) m.rem(10px);
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Token names follow the same `--mastors-{name}` convention used in `:root`. Common examples:
|
|
415
|
+
|
|
416
|
+
| Call | Emits |
|
|
417
|
+
|---|---|
|
|
418
|
+
| `m.vars(accent)` | `var(--mastors-accent)` |
|
|
419
|
+
| `m.vars(surface)` | `var(--mastors-surface)` |
|
|
420
|
+
| `m.vars(shadow-lg)` | `var(--mastors-shadow-lg)` |
|
|
421
|
+
| `m.vars(duration-200)` | `var(--mastors-duration-200)` |
|
|
422
|
+
| `m.vars(ease-in-out)` | `var(--mastors-ease-in-out)` |
|
|
423
|
+
| `m.vars(border, #e5e7eb)` | `var(--mastors-border, #e5e7eb)` |
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Mixins
|
|
428
|
+
|
|
429
|
+
### Breakpoints
|
|
430
|
+
|
|
431
|
+
Mobile-first, min-width media queries using the named breakpoint map.
|
|
432
|
+
|
|
433
|
+
```scss
|
|
434
|
+
// Breakpoints: xs (0px) - sm (640px) - md (768px) - lg (1024px) - xl (1280px) - 2xl (1536px)
|
|
435
|
+
|
|
436
|
+
@include m.bp("md") {
|
|
437
|
+
// Applies at 768px and above
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
@include m.breakpoint-down("lg") {
|
|
441
|
+
// Applies below 1024px
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Aliases
|
|
445
|
+
@include m.respond-to("xl") { ... }
|
|
446
|
+
@include m.breakpoint-up("sm") { ... }
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Theme
|
|
450
|
+
|
|
451
|
+
```scss
|
|
452
|
+
@include m.dark-mode {
|
|
453
|
+
// Activates when .dark is on <html> (class mode)
|
|
454
|
+
// or prefers-color-scheme: dark (media mode)
|
|
455
|
+
background-color: m.color("neutral", 900);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
@include m.light-mode {
|
|
459
|
+
background-color: m.color("white");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
@include m.theme("ocean") {
|
|
463
|
+
// Activates under [data-theme="ocean"]
|
|
464
|
+
--accent: #0891b2;
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Elevation
|
|
469
|
+
|
|
470
|
+
```scss
|
|
471
|
+
@include m.elevation("sm"); // box-shadow: 0 1px 3px ...
|
|
472
|
+
@include m.elevation("lg"); // box-shadow: 0 10px 15px ...
|
|
473
|
+
@include m.elevation("none"); // box-shadow: none
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Transition
|
|
477
|
+
|
|
478
|
+
```scss
|
|
479
|
+
// All properties, 200ms, in-out easing (defaults)
|
|
480
|
+
@include m.transition();
|
|
481
|
+
|
|
482
|
+
// Specific properties
|
|
483
|
+
@include m.transition((color, background-color), "150", "out");
|
|
484
|
+
|
|
485
|
+
// Custom combination
|
|
486
|
+
@include m.transition((transform, opacity), "300", "bounce");
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Container
|
|
490
|
+
|
|
491
|
+
```scss
|
|
492
|
+
.page-section {
|
|
493
|
+
@include m.container();
|
|
494
|
+
// max-width per breakpoint, auto horizontal margins, configurable padding
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Pseudo
|
|
499
|
+
|
|
500
|
+
```scss
|
|
501
|
+
.icon::before {
|
|
502
|
+
@include m.pseudo();
|
|
503
|
+
// Sets display: block, position: absolute, content: ""
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## Responsive Engine
|
|
510
|
+
|
|
511
|
+
The engine in `responsive/_engine.scss` wraps utility maps in breakpoint media queries. Sub-packages can call `@include engine.run($utilities)` directly for standalone use.
|
|
512
|
+
|
|
513
|
+
For the standard workflow, responsive variant generation is built into `generate-utilities()` — any utility entry that declares `responsive: true` automatically emits both base classes and breakpoint-prefixed variants in a single call. No separate invocation is required.
|
|
514
|
+
|
|
515
|
+
Generated class pattern: `.{breakpoint}\:{class}`
|
|
516
|
+
|
|
517
|
+
```html
|
|
518
|
+
<!-- Responsive display -->
|
|
519
|
+
<div class="hidden md:block lg:flex">...</div>
|
|
520
|
+
|
|
521
|
+
<!-- Responsive position -->
|
|
522
|
+
<div class="relative md:absolute lg:sticky">...</div>
|
|
523
|
+
|
|
524
|
+
<!-- Responsive layout (from @mastors/flexer or @mastors/gridder) -->
|
|
525
|
+
<div class="flex flex-col md:flex-row lg:gap-8">...</div>
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Utilities with responsive support at v1.0: `display`, `position`.
|
|
529
|
+
Additional responsive utilities added in v1.2: `text-align`, `float`, `flex-direction` (via flexer), `grid-template-columns` (via gridder).
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Container Queries
|
|
534
|
+
|
|
535
|
+
Container queries are supported via `responsive/_container-queries.scss`.
|
|
536
|
+
|
|
537
|
+
**Setup classes:**
|
|
538
|
+
|
|
539
|
+
| Class | Effect |
|
|
540
|
+
|---|---|
|
|
541
|
+
| `.cq-inline` | `container-type: inline-size` |
|
|
542
|
+
| `.cq-size` | `container-type: size` |
|
|
543
|
+
| `.cq-normal` | `container-type: normal` |
|
|
544
|
+
| `[data-container]` | `container-type: inline-size` (attribute-based) |
|
|
545
|
+
|
|
546
|
+
**Usage:**
|
|
547
|
+
|
|
548
|
+
```html
|
|
549
|
+
<div class="cq-inline">
|
|
550
|
+
<div class="child">Responds to container width, not viewport</div>
|
|
551
|
+
</div>
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
```scss
|
|
555
|
+
@use "@mastors/core/api" as m;
|
|
556
|
+
|
|
557
|
+
.child {
|
|
558
|
+
font-size: 1rem;
|
|
559
|
+
|
|
560
|
+
@include m.cq(40rem) {
|
|
561
|
+
font-size: 1.25rem;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Named container query
|
|
565
|
+
@include m.cq(30rem, "card") {
|
|
566
|
+
padding: m.spacing(6);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Fluid Typography
|
|
574
|
+
|
|
575
|
+
`responsive/_fluid-type.scss` provides clamp()-based fluid font sizes that scale between two viewport widths without media queries.
|
|
576
|
+
|
|
577
|
+
```scss
|
|
578
|
+
@use "@mastors/core/api" as m;
|
|
579
|
+
|
|
580
|
+
// As a mixin (applies font-size property)
|
|
581
|
+
h1 { @include m.fluid-type(2rem, 3.75rem); }
|
|
582
|
+
|
|
583
|
+
// As a function (use in any property value)
|
|
584
|
+
h1 { font-size: m.fluid-type(2rem, 3.75rem); }
|
|
585
|
+
|
|
586
|
+
// Custom viewport range
|
|
587
|
+
h2 { @include m.fluid-type(1.5rem, 3rem, 480px, 1440px); }
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Opt-in preset scale for all heading levels:
|
|
591
|
+
|
|
592
|
+
```scss
|
|
593
|
+
@use "@mastors/core/scss/responsive/fluid-type" as ft;
|
|
594
|
+
@include ft.fluid-scale();
|
|
595
|
+
// Applies fluid-type() to h1-h6 and p
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## Theme System
|
|
601
|
+
|
|
602
|
+
Core emits all design tokens as `--mastors-*` CSS custom properties on `:root`. Theme layers override a semantic subset.
|
|
603
|
+
|
|
604
|
+
**Default (light) theme properties:**
|
|
605
|
+
|
|
606
|
+
```css
|
|
607
|
+
:root {
|
|
608
|
+
--mastors-bg: #ffffff;
|
|
609
|
+
--mastors-bg-subtle: #f9fafb;
|
|
610
|
+
--mastors-surface: #ffffff;
|
|
611
|
+
--mastors-surface-raised: #f9fafb;
|
|
612
|
+
--mastors-surface-overlay: #f3f4f6;
|
|
613
|
+
--mastors-text: #111827;
|
|
614
|
+
--mastors-text-muted: #6b7280;
|
|
615
|
+
--mastors-text-subtle: #9ca3af;
|
|
616
|
+
--mastors-text-inverse: #ffffff;
|
|
617
|
+
--mastors-border: #e5e7eb;
|
|
618
|
+
--mastors-border-strong: #9ca3af;
|
|
619
|
+
--mastors-accent: #2563eb;
|
|
620
|
+
--mastors-accent-hover: #1d4ed8;
|
|
621
|
+
--mastors-accent-subtle: #eff6ff;
|
|
622
|
+
--mastors-accent-text: #ffffff;
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**Dark theme** activates via `.dark` on `<html>` (or `prefers-color-scheme` in media mode):
|
|
627
|
+
|
|
628
|
+
```html
|
|
629
|
+
<html class="dark">...</html>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
Use semantic custom properties directly in your CSS for automatic theme switching:
|
|
633
|
+
|
|
634
|
+
```css
|
|
635
|
+
.card {
|
|
636
|
+
background-color: var(--mastors-surface);
|
|
637
|
+
color: var(--mastors-text);
|
|
638
|
+
border-color: var(--mastors-border);
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
Or use `vars()` in SCSS for the same result without the prefix noise:
|
|
643
|
+
|
|
644
|
+
```scss
|
|
645
|
+
.card {
|
|
646
|
+
background-color: m.vars(surface);
|
|
647
|
+
color: m.vars(text);
|
|
648
|
+
border-color: m.vars(border);
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
Custom themes can be applied with any `data-theme` attribute:
|
|
653
|
+
|
|
654
|
+
```scss
|
|
655
|
+
@use "@mastors/core/api" as m;
|
|
656
|
+
|
|
657
|
+
@include m.theme("ocean") {
|
|
658
|
+
--mastors-accent: #0891b2;
|
|
659
|
+
--mastors-accent-hover: #0e7490;
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
```html
|
|
664
|
+
<div data-theme="ocean">
|
|
665
|
+
<!-- accent color is teal inside here -->
|
|
666
|
+
</div>
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
## Base Layer
|
|
672
|
+
|
|
673
|
+
The base layer emits a modern CSS reset and document defaults when you import the full stylesheet:
|
|
674
|
+
|
|
675
|
+
- `box-sizing: border-box` on all elements (declared once in `_reset.scss`)
|
|
676
|
+
- Zero margin and padding on all elements
|
|
677
|
+
- `img`, `video`, `canvas`, `svg` set to `display: block; max-width: 100%`
|
|
678
|
+
- `input`, `button`, `textarea`, `select` inherit font
|
|
679
|
+
- Smooth scroll behaviour on `html`
|
|
680
|
+
- `-webkit-font-smoothing: antialiased` on `body`
|
|
681
|
+
- Base `color` and `background-color` on `html` driven by semantic custom properties
|
|
682
|
+
- Heading sizes (h1-h6) driven by the typography token scale
|
|
683
|
+
- Code/pre elements default to the mono font family
|
|
684
|
+
|
|
685
|
+
---
|
|
686
|
+
|
|
687
|
+
## Utility Classes
|
|
688
|
+
|
|
689
|
+
When importing the full stylesheet, core emits these utility classes:
|
|
690
|
+
|
|
691
|
+
| Group | Classes |
|
|
692
|
+
|---|---|
|
|
693
|
+
| Display | `.block` `.inline-block` `.inline` `.flex` `.inline-flex` `.grid` `.inline-grid` `.hidden` `.contents` `.table` `.table-cell` `.table-row` |
|
|
694
|
+
| Position | `.static` `.relative` `.absolute` `.fixed` `.sticky` - `.inset-*` `.top-*` `.right-*` `.bottom-*` `.left-*` |
|
|
695
|
+
| Overflow | `.overflow-auto/hidden/scroll/visible/clip` - `.overflow-x-*` `.overflow-y-*` |
|
|
696
|
+
| Spacing | `.m-*` `.mx-*` `.my-*` `.mt/r/b/l/s/e-*` - `.p-*` `.px-*` `.py-*` `.pt/r/b/l/s/e-*` - `.gap-*` `.gap-x-*` `.gap-y-*` |
|
|
697
|
+
| Sizing | `.w-*` `.h-*` - `.min-w-*` `.max-w-*` `.min-h-*` `.max-h-*` |
|
|
698
|
+
| Colors | `.text-*` `.bg-*` (all palettes x all shades + semantic) |
|
|
699
|
+
| Borders | `.border` `.border-*` `.rounded-*` `.rounded-{t\|b\|l\|r}-*` (full scale, all token steps) |
|
|
700
|
+
| Shadows | `.shadow-*` |
|
|
701
|
+
| Opacity | `.opacity-*` |
|
|
702
|
+
| Cursor | `.cursor-pointer` `.cursor-not-allowed` `.cursor-grab` etc. |
|
|
703
|
+
| Pointer events | `.pointer-events-none` `.pointer-events-auto` |
|
|
704
|
+
| Z-index | `.z-base` `.z-dropdown` `.z-modal` `.z-tooltip` etc. |
|
|
705
|
+
| Transforms | `.translate-x-*` `.translate-y-*` `.rotate-*` `.scale-*` `.origin-*` `.transform-gpu` `.transform-none` |
|
|
706
|
+
| Typography | `.text-{left\|center\|right\|justify\|start\|end}` (responsive) · `.text-{xs…9xl}` · `.font-{thin…black}` · `.font-{sans\|mono\|display}` · `.italic` `.not-italic` · `.leading-*` · `.tracking-*` · `.underline` `.overline` `.line-through` `.no-underline` · `.decoration-{solid\|dashed\|dotted\|double\|wavy}` · `.decoration-{1\|2\|4\|8}` · `.uppercase` `.lowercase` `.capitalize` `.normal-case` · `.text-ellipsis` `.text-clip` · `.whitespace-*` · `.break-normal` `.break-words` `.break-all` `.break-keep` · `.align-{baseline\|top\|middle\|bottom}` · `.list-none` `.list-disc` `.list-decimal` · `.antialiased` `.subpixel-antialiased` |
|
|
707
|
+
| Animation | `.transition` `.transition-{colors\|opacity\|shadow\|transform\|none\|all}` · `.duration-*` · `.ease-*` · `.delay-*` · `.animate-{spin\|ping\|pulse\|bounce\|fade-in\|fade-out\|slide-up\|slide-down\|scale-in\|none}` · `.fill-{none\|forwards\|backwards\|both}` · `.animation-{running\|paused}` · `.animate-repeat-{0\|1\|infinite}` |
|
|
708
|
+
| Interaction | `.select-{none\|text\|all\|auto}` · `.resize-{none\|x\|y}` `.resize` · `.scroll-{auto\|smooth}` · `.snap-{none\|x\|y\|both\|mandatory\|proximity}` · `.snap-{start\|end\|center}` · `.snap-stop-{always\|normal}` · `.scroll-m-*` `.scroll-p-*` · `.touch-{auto\|none\|pan-x\|pan-y\|manipulation}` · `hover:opacity-*` `hover:bg-accent` `hover:underline` `hover:shadow-lg` `hover:scale-{105\|110}` `hover:-translate-y-1` · `focus:ring` `focus:ring-2` `focus:ring-offset-2` `focus:ring-none` · `disabled:opacity-50` `disabled:cursor-not-allowed` `disabled:pointer-events-none` |
|
|
709
|
+
| Layout | `.aspect-{auto\|square\|video\|4-3\|3-2\|21-9\|9-16\|golden}` · `.object-{contain\|cover\|fill\|none\|scale-down}` · `.object-{center\|top\|bottom\|left\|right\|…}` · `.float-{left\|right\|none\|start\|end}` (responsive) · `.clear-*` · `.isolate` `.isolation-auto` · `.mix-blend-*` · `.bg-blend-*` · `.box-decoration-{clone\|slice}` · `.appearance-{none\|auto}` · `.will-change-{auto\|scroll\|contents\|transform}` |
|
|
710
|
+
|
|
711
|
+
Display and position utilities support responsive prefixes (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`). Text-align and float also support responsive prefixes.
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Helpers
|
|
716
|
+
|
|
717
|
+
| Class | Effect |
|
|
718
|
+
|---|---|
|
|
719
|
+
| `.visually-hidden`, `.vh` | Visually hidden, screen-reader accessible |
|
|
720
|
+
| `.visually-hidden-focusable` | Hidden until focused (use for skip links) |
|
|
721
|
+
| `.truncate` | Single-line text truncation with ellipsis |
|
|
722
|
+
| `.line-clamp-{1-6}` | Multi-line text clamp |
|
|
723
|
+
| `.break-words` | `overflow-wrap: break-word` |
|
|
724
|
+
| `.break-all` | `word-break: break-all` |
|
|
725
|
+
| `.break-keep` | `word-break: keep-all` |
|
|
726
|
+
| `.ratio-auto` | `aspect-ratio: auto` |
|
|
727
|
+
| `.ratio-square` | `aspect-ratio: 1 / 1` |
|
|
728
|
+
| `.ratio-video` | `aspect-ratio: 16 / 9` |
|
|
729
|
+
| `.ratio-portrait` | `aspect-ratio: 3 / 4` |
|
|
730
|
+
| `.ratio-wide` | `aspect-ratio: 21 / 9` |
|
|
731
|
+
| `.ratio-golden` | `aspect-ratio: 1.618 / 1` |
|
|
732
|
+
| `.clearfix` | Float clearfix via `::after` |
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## Accessibility
|
|
737
|
+
|
|
738
|
+
| Class / Rule | Effect |
|
|
739
|
+
|---|---|
|
|
740
|
+
| `.sr-only` | Visually hidden, announced by screen readers |
|
|
741
|
+
| `.not-sr-only` | Undoes `.sr-only` |
|
|
742
|
+
| `.visually-hidden`, `.vh` | Equivalent to `.sr-only` with `!important` guards |
|
|
743
|
+
| `.visually-hidden-focusable` | Hidden until focused (skip-link pattern) |
|
|
744
|
+
| `:focus-visible` | 2px primary-500 ring, 2px offset — keyboard only |
|
|
745
|
+
| `:focus:not(:focus-visible)` | Removes ring for mouse/pointer users |
|
|
746
|
+
| `prefers-reduced-motion: reduce` | Collapses all animation/transition durations to 0.01ms |
|
|
747
|
+
| `.print\:hidden` | `display: none` inside `@media print` |
|
|
748
|
+
| `.screen\:hidden` | `display: none` outside `@media print` (print-only element) |
|
|
749
|
+
| `.print\:break-inside-avoid` | Prevents page breaks inside the element when printing |
|
|
750
|
+
| `.print\:break-before` | Forces a page break before the element |
|
|
751
|
+
| `.print\:break-after` | Forces a page break after the element |
|
|
752
|
+
| `.print\:text-black` | Forces `color: #000` for print output |
|
|
753
|
+
| `.print\:bg-white` | Forces `background: #fff` for print output |
|
|
754
|
+
| `.print\:border-none` | Removes borders for print output |
|
|
755
|
+
| `.print\:shadow-none` | Removes box-shadow for print output |
|
|
756
|
+
| `a[href]::after` *(print)* | Appends `(url)` after links so destinations are visible on paper |
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## Generator Engine
|
|
761
|
+
|
|
762
|
+
The three generator mixins are the engine behind all utility class output in the Mastors ecosystem.
|
|
763
|
+
|
|
764
|
+
### `generate-utilities($utilities)`
|
|
765
|
+
|
|
766
|
+
Generates utility classes from a configuration map. Used by `@mastors/flexer`, `@mastors/gridder`, and all core utility partials.
|
|
767
|
+
|
|
768
|
+
The mixin runs in two passes:
|
|
769
|
+
- **Pass 1** — emits base (unprefixed) classes for every entry.
|
|
770
|
+
- **Pass 2** — for every entry with `responsive: true`, iterates all breakpoints (skipping `xs`/0px) and emits breakpoint-prefixed variants inside `@media` blocks. Respects the `$enable-responsive` flag and the global prefix/`!important` config.
|
|
771
|
+
|
|
772
|
+
```scss
|
|
773
|
+
@use "@mastors/core/scss/generators/class-generator" as gen;
|
|
774
|
+
|
|
775
|
+
@include gen.generate-utilities((
|
|
776
|
+
"text-align": (
|
|
777
|
+
property: text-align,
|
|
778
|
+
prefix: "text",
|
|
779
|
+
responsive: true,
|
|
780
|
+
values: (
|
|
781
|
+
"left": left,
|
|
782
|
+
"center": center,
|
|
783
|
+
"right": right,
|
|
784
|
+
),
|
|
785
|
+
),
|
|
786
|
+
));
|
|
787
|
+
// Emits: .text-left, .text-center, .text-right
|
|
788
|
+
// And: .sm\:text-left, .md\:text-left, … for all breakpoints
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
### `emit-custom-properties($map, $prefix)`
|
|
792
|
+
|
|
793
|
+
Emits flat CSS custom properties from a token map onto the current selector.
|
|
794
|
+
|
|
795
|
+
```scss
|
|
796
|
+
:root {
|
|
797
|
+
@include gen.emit-custom-properties($spacing-tokens, "mastors-spacing");
|
|
798
|
+
// -> --mastors-spacing-4: 1rem; etc.
|
|
799
|
+
}
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### `emit-nested-custom-properties($map, $prefix)`
|
|
803
|
+
|
|
804
|
+
Recursively emits custom properties from a nested map (e.g. color palettes).
|
|
805
|
+
|
|
806
|
+
```scss
|
|
807
|
+
:root {
|
|
808
|
+
@include gen.emit-nested-custom-properties($color-tokens, "mastors-color");
|
|
809
|
+
// -> --mastors-color-primary-500: #3b82f6; etc.
|
|
810
|
+
}
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
---
|
|
814
|
+
|
|
815
|
+
## Semantic Layer
|
|
816
|
+
|
|
817
|
+
The semantic layer in `semantic/` provides role-based SCSS variable aliases on top of the raw token maps. Use these in component SCSS instead of raw token references to get automatic theme compatibility.
|
|
818
|
+
|
|
819
|
+
**Colors:**
|
|
820
|
+
|
|
821
|
+
```scss
|
|
822
|
+
@use "@mastors/core/scss/semantic/colors" as sem;
|
|
823
|
+
|
|
824
|
+
.my-card {
|
|
825
|
+
background: sem.$color-surface; // var(--mastors-surface)
|
|
826
|
+
color: sem.$color-text; // var(--mastors-text)
|
|
827
|
+
border: 1px solid sem.$color-border; // var(--mastors-border)
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Spacing:**
|
|
832
|
+
|
|
833
|
+
```scss
|
|
834
|
+
@use "@mastors/core/scss/semantic/spacing" as sem;
|
|
835
|
+
|
|
836
|
+
.section {
|
|
837
|
+
padding: sem.$space-section; // spacing(16) = 4rem
|
|
838
|
+
gap: sem.$space-component; // spacing(4) = 1rem
|
|
839
|
+
}
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
**Typography:**
|
|
843
|
+
|
|
844
|
+
```scss
|
|
845
|
+
@use "@mastors/core/scss/semantic/typography" as sem;
|
|
846
|
+
|
|
847
|
+
body { font-family: sem.$font-body; } // system-ui stack
|
|
848
|
+
code { font-family: sem.$font-mono; } // monospace stack
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
## Known Stubs
|
|
854
|
+
|
|
855
|
+
Two files are intentionally empty at v1.0 and act as reserved extension points:
|
|
856
|
+
|
|
857
|
+
| File | Purpose |
|
|
858
|
+
|---|---|
|
|
859
|
+
| `abstracts/_maps.scss` | Shared utility maps consumed by 3+ unrelated files. Empty until such maps exist. |
|
|
860
|
+
| `vendors/_index.scss` | Third-party CSS overrides. Add a partial and `@forward` it here when needed. |
|
|
861
|
+
| `base/_box-sizing.scss` | Retained as a named path slot; box-sizing is declared in `_reset.scss`. |
|
|
862
|
+
|
|
863
|
+
These stubs are documented in each file's header comment.
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
## Package Exports
|
|
868
|
+
|
|
869
|
+
```scss
|
|
870
|
+
/* Full stylesheet — reset + tokens + themes + utilities */
|
|
871
|
+
@use "@mastors/core/scss";
|
|
872
|
+
|
|
873
|
+
/* Public API — zero CSS output, all tokens/mixins/functions/config */
|
|
874
|
+
@use "@mastors/core/api" as m;
|
|
875
|
+
|
|
876
|
+
/* Individual partials */
|
|
877
|
+
@use "@mastors/core/scss/tokens/color" as ct;
|
|
878
|
+
@use "@mastors/core/scss/mixins/breakpoint" as bp;
|
|
879
|
+
@use "@mastors/core/scss/functions/rem" as r;
|
|
880
|
+
@use "@mastors/core/scss/functions/vars"; /* vars() standalone */
|
|
881
|
+
@use "@mastors/core/scss/responsive/fluid-type" as ft;
|
|
882
|
+
@use "@mastors/core/scss/config/settings"; /* $mastors-config, config() */
|
|
883
|
+
@use "@mastors/core/scss/config/flags"; /* $enable-* flags */
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
```ts
|
|
887
|
+
// Runtime token access
|
|
888
|
+
import { tokens } from '@mastors/core'
|
|
889
|
+
|
|
890
|
+
// TypeScript types
|
|
891
|
+
import type { MastorsConfig, Breakpoint, ThemeMode, Tokens } from '@mastors/core'
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
---
|
|
895
|
+
|
|
896
|
+
## Peer Dependencies
|
|
897
|
+
|
|
898
|
+
| Package | Version |
|
|
899
|
+
|---|---|
|
|
900
|
+
| `sass` | `>= 1.80.0` |
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
## Changelog
|
|
905
|
+
|
|
906
|
+
### v1.2.0
|
|
907
|
+
|
|
908
|
+
- **Added:** `vars($token, $fallback?)` function in `functions/_vars.scss` — wraps the `--mastors-` namespace so downstream consumers reference tokens as `var(--mastors-{name})` without hard-coding the prefix. Namespace stored in `$-namespace: "mastors" !default`. Forwarded through `functions/_index.scss` and exposed via `@use "@mastors/core/api"`.
|
|
909
|
+
- **Added:** `config/_index.scss` shim — `@forward`s both `_settings.scss` and `_flags.scss`. `api/_index.scss` now includes `@forward "../config/index"`, exposing `config()` accessor and all `$enable-*` flags through the public API surface without a direct partial import.
|
|
910
|
+
- **Added:** `utilities/_typography.scss` — full typography utility surface covering text-align (responsive), font-size (token-driven `@each`), font-weight (token-driven), font-family (token-driven), font-style (`.italic` / `.not-italic`), line-height / leading (token-driven), letter-spacing / tracking (token-driven), text-decoration (line + style + thickness), text-transform, text-overflow, white-space, word-break, text-indent, vertical-align, list-style, font-smoothing.
|
|
911
|
+
- **Added:** `utilities/_animation.scss` — transition-property presets (`.transition`, `.transition-colors`, `.transition-opacity`, `.transition-shadow`, `.transition-transform`, `.transition-none`, `.transition-all`), token-driven `.duration-*` and `.delay-*`, token-driven `.ease-*`, named animation presets (`.animate-spin/ping/pulse/bounce/fade-in/fade-out/slide-up/slide-down/scale-in/none`), full `@keyframes` definitions prefixed `mastors-*`, animation fill-mode / play-state / iteration utilities.
|
|
912
|
+
- **Added:** `utilities/_interaction.scss` — user-select, resize, scroll-behavior (`.scroll-auto` / `.scroll-smooth`), scroll-snap (type + align + stop + scroll-margin/padding), touch-action, and state-variant pseudo-class utilities: `hover:opacity-*`, `hover:bg-accent`, `hover:text-accent`, `hover:underline`, `hover:no-underline`, `hover:shadow-lg`, `hover:scale-105`, `hover:scale-110`, `hover:-translate-y-1`, `focus:ring`, `focus:ring-2`, `focus:ring-offset-2`, `focus:ring-none`, `disabled:opacity-50`, `disabled:cursor-not-allowed`, `disabled:pointer-events-none`.
|
|
913
|
+
- **Added:** `utilities/_layout.scss` — aspect-ratio block (`.aspect-auto`, `.aspect-square`, `.aspect-video`, `.aspect-4-3`, `.aspect-3-2`, `.aspect-21-9`, `.aspect-9-16`, `.aspect-golden`; the `$-aspect-ratios` map is `!default`-overridable). Documented alongside object-fit and object-position which were already present.
|
|
914
|
+
- **Added:** `accessibility/_print.scss` — `print:hidden`, `screen:hidden`, `print:break-inside-avoid`, `print:break-before`, `print:break-after`, `print:text-black`, `print:bg-white`, `print:border-none`, `print:shadow-none`, automatic `a[href]::after` link expansion, suppression for `#` and `javascript:` links.
|
|
915
|
+
|
|
916
|
+
### v1.0.0
|
|
917
|
+
|
|
918
|
+
- Initial public release
|
|
919
|
+
- Full token system: color, spacing, typography, radii, shadows, z-index, opacity, transitions, sizing
|
|
920
|
+
- Complete functions layer: `rem`, `em`, `color`, `spacing`, `radius`, `shadow`, `z`, `opacity`, `duration`, `easing`, `tint`, `shade`, `alpha`, `contrast`, `fluid`, `map-deep-get`, `map-collect`, `str-replace`
|
|
921
|
+
- Complete mixins layer: `bp`, `respond-to`, `breakpoint-up`, `breakpoint-down`, `dark-mode`, `light-mode`, `theme`, `elevation`, `transition`, `container`, `pseudo`
|
|
922
|
+
- **Fixed:** `generate-utilities()` now runs a two-pass emit — Pass 1 outputs base classes, Pass 2 automatically emits breakpoint-prefixed responsive variants for all entries with `responsive: true`. Previously responsive variants were silently not emitted.
|
|
923
|
+
- **Fixed:** `generators/_responsive-generator.scss` replaced the `@content`-based no-op stub with a thin wrapper that correctly delegates to `engine.run()` for backward compatibility.
|
|
924
|
+
- **Fixed:** `contrast()` luminance threshold corrected from `0.179` (WCAG linearised) to `0.35` (calibrated for the simplified non-gamma-expanded approximation in use). Prevents wrong light/dark decisions on mid-grey backgrounds.
|
|
925
|
+
- **Added:** `stylelint` linting with `stylelint-config-standard-scss` — `pnpm lint` now runs real SCSS style checks. `postcss-scss`, `stylelint`, and `stylelint-config-standard-scss` added to `devDependencies`; `.stylelintrc.json` added to `packages/core`.
|
|
926
|
+
- Generator engine: `generate-utilities` (with integrated responsive Pass 2), `emit-custom-properties`, `emit-nested-custom-properties`
|
|
927
|
+
- Responsive engine with correct numeric breakpoint escaping (`2xl:` prefix)
|
|
928
|
+
- Container queries: `.cq-inline`, `.cq-size`, `.cq-normal`, `[data-container]`, `cq()` mixin
|
|
929
|
+
- Fluid typography: `fluid-type()` mixin + function + `fluid-scale()` preset
|
|
930
|
+
- Full directional border-radius utility scale — all four sides x all token steps
|
|
931
|
+
- Light and dark themes via CSS custom property semantic contract (15 semantic props)
|
|
932
|
+
- Modern CSS reset — no duplicate `box-sizing` declarations
|
|
933
|
+
- Accessibility layer: `:focus-visible` ring, `prefers-reduced-motion` override, `.sr-only`, `.visually-hidden`
|
|
934
|
+
- Dual dark-mode strategy: class-based and media-query, configurable via `$mastors-config`
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
## License
|
|
939
|
+
|
|
940
|
+
MIT (c) Mastors Contributors
|