kmcom-nuxt-layers 6.0.0 → 6.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/docs/adr/0003-modular-step-system-replaces-fluid-clamps.md +58 -0
- package/layers/core/app/assets/css/tokens/spacing-fluid.css +24 -19
- package/layers/core/app/components/Element.test.ts +2 -2
- package/layers/core/app/composables/useLayoutAttrs.test.ts +35 -5
- package/layers/core/app/composables/useLayoutAttrs.ts +1 -1
- package/layers/core/app/utils/resolveElementStyle.test.ts +2 -2
- package/layers/design-system/theming/app/types/designSystem.ts +21 -17
- package/layers/design-system/typography/app/app.config.ts +26 -0
- package/layers/design-system/typography/app/assets/css/typography.css +216 -187
- package/layers/design-system/typography/app/components/Typography/CodeBlock.vue +4 -4
- package/layers/design-system/typography/app/components/Typography/Headline.test.ts +36 -0
- package/layers/design-system/typography/app/components/Typography/Headline.vue +20 -21
- package/layers/design-system/typography/app/components/Typography/QuoteBlock.vue +4 -4
- package/layers/design-system/typography/app/components/Typography/RepeatText.vue +7 -6
- package/layers/design-system/typography/app/components/Typography/index.test.ts +31 -0
- package/layers/design-system/typography/app/components/Typography/index.vue +10 -8
- package/layers/design-system/typography/app/composables/typography.test.ts +53 -0
- package/layers/design-system/typography/app/composables/typography.ts +28 -43
- package/layers/design-system/typography/app/types/typography.ts +5 -32
- package/layers/structure/grid/app/assets/css/grid.css +11 -7
- package/package.json +1 -1
|
@@ -14,303 +14,332 @@
|
|
|
14
14
|
--font-display: system-ui, sans-serif;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/*
|
|
18
|
+
* Modular type scale — every size is a step on one ratio, not a hand-tuned clamp:
|
|
19
|
+
* font-size = round(--type-base × --type-scale ^ --step, --type-snap)
|
|
20
|
+
* 1.26 ≈ 2^(1/3), so three steps double a size. --step is set per element and the size
|
|
21
|
+
* is recomputed from the base each time, so nested steps never compound.
|
|
22
|
+
* Plain :root properties, not @theme: var(--step) must resolve on the element using it.
|
|
23
|
+
* Retune a subtree by overriding --type-base or --type-scale (both read where used);
|
|
24
|
+
* overriding --type-min/--type-max there does nothing — --type-base already substituted
|
|
25
|
+
* them at :root.
|
|
26
|
+
*/
|
|
17
27
|
:root {
|
|
18
|
-
|
|
19
|
-
--
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
--
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
--
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
don't break to one-per-line. Root font-size (rem) already scales by
|
|
38
|
-
env(preferred-text-scale); this backs that out then re-applies it at
|
|
39
|
-
half rate. No-op at 100% scale or without support (env() undefined → 1). */
|
|
40
|
-
--heading-text-scale-damp: calc(1 + (env(preferred-text-scale, 1) - 1) * 0.5);
|
|
41
|
-
|
|
42
|
-
/* Container-relative counterparts — same rem endpoints, cqi instead of vi.
|
|
43
|
-
Require a `container-type` ancestor (e.g. `@container`); with none, cqi
|
|
44
|
-
falls back to the small viewport per spec, so these are opt-in, not a
|
|
45
|
-
replacement for the vi-based scale above. */
|
|
46
|
-
/* Coefficients retuned vs the vi scale (not a straight port): small steps'
|
|
47
|
-
min→max diff is only 0.25-0.5rem (1-2 --fluid-step increments), so vi's
|
|
48
|
-
slope needs 250+rem of container width to cross even one rounding step —
|
|
49
|
-
reads as frozen. Retuned so the full min→max transition happens between
|
|
50
|
-
an 8rem and 24rem container (the actual draggable range in practice). */
|
|
51
|
-
--fluid-text-xs-cq-raw: clamp(0.5rem, 0.375rem + 1.5625cqi, 0.75rem);
|
|
52
|
-
--fluid-text-sm-cq-raw: clamp(0.75rem, 0.625rem + 1.5625cqi, 1rem);
|
|
53
|
-
--fluid-text-md-cq-raw: clamp(1rem, 0.875rem + 1.5625cqi, 1.25rem);
|
|
54
|
-
--fluid-text-lg-cq-raw: clamp(1.25rem, 1rem + 3.125cqi, 1.75rem);
|
|
55
|
-
--fluid-text-xl-cq-raw: clamp(1.5rem, 1.25rem + 1.5cqi, 2.5rem);
|
|
56
|
-
--fluid-text-2xl-cq-raw: clamp(2rem, 1.5rem + 2.5cqi, 3.5rem);
|
|
57
|
-
--fluid-text-3xl-cq-raw: clamp(2.5rem, 1.75rem + 4cqi, 5rem);
|
|
58
|
-
--fluid-text-4xl-cq-raw: clamp(3rem, 2rem + 5cqi, 6rem);
|
|
59
|
-
--fluid-text-5xl-cq-raw: clamp(3.75rem, 2.5rem + 6.5cqi, 7.5rem);
|
|
60
|
-
--fluid-text-6xl-cq-raw: clamp(4.5rem, 3rem + 8cqi, 9rem);
|
|
61
|
-
--fluid-text-7xl-cq-raw: clamp(5.5rem, 3.5rem + 10cqi, 11rem);
|
|
62
|
-
--fluid-text-8xl-cq-raw: clamp(6.75rem, 4rem + 14cqi, 13.5rem);
|
|
63
|
-
--fluid-text-9xl-cq-raw: clamp(8rem, 4.5rem + 20cqi, 16rem);
|
|
28
|
+
--type-min: 1rem; /* base below 48rem */
|
|
29
|
+
--type-max: 1.2rem; /* base from 48rem — every step jumps ×1.2 there, by design */
|
|
30
|
+
--type-base: var(--type-min);
|
|
31
|
+
--type-scale: 1.26;
|
|
32
|
+
--type-snap: 0.0625rem; /* rounding interval: rem so it scales with the root; never px, never 0 */
|
|
33
|
+
|
|
34
|
+
/* Fluid display step, 5 → 7 across 360 → 1280px. tan(atan2(length, 1rem)) casts the
|
|
35
|
+
length to the unitless exponent pow() needs; normalised by 1rem (not 1px) so the
|
|
36
|
+
exponent stays 5 → 7 whatever the user's root font size; the vw term is scaled by root / 16px so a
|
|
37
|
+
larger root doesn't lower the exponent at a given width (h1 stays visibly larger). */
|
|
38
|
+
--step-display: tan(
|
|
39
|
+
atan2(clamp(5rem, 4.2176rem + 3.4784vw * tan(atan2(1rem, 16px)), 7rem), 1rem)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (width >= 48rem) {
|
|
44
|
+
:root {
|
|
45
|
+
--type-base: var(--type-max);
|
|
46
|
+
}
|
|
64
47
|
}
|
|
65
48
|
|
|
66
49
|
/*
|
|
67
|
-
*
|
|
50
|
+
* Step utilities, parallel to Tailwind's --text-* namespace.
|
|
68
51
|
* Do not override --text-xs..--text-9xl — Nuxt UI components consume those.
|
|
69
|
-
* round()
|
|
70
|
-
*
|
|
52
|
+
* round() lives in a real declaration behind @supports, never in a custom property:
|
|
53
|
+
* an unsupported browser then keeps the plain calc() above it instead of dropping
|
|
54
|
+
* font-size entirely.
|
|
55
|
+
* Line heights fall with size: anchored on the reference's measured body 1.7, h2/h3 1.2 and
|
|
56
|
+
* h1 0.95, eased in between (sm 1.5, 0 1.6 … 4 1.15, 5 1.1, 6 1.05, 7 1).
|
|
71
57
|
*/
|
|
72
|
-
@utility text-
|
|
73
|
-
|
|
58
|
+
@utility text-step-sm {
|
|
59
|
+
--step: -1;
|
|
60
|
+
|
|
61
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
74
62
|
line-height: 1.5;
|
|
75
63
|
|
|
76
64
|
@supports (font-size: round(1rem, 1rem)) {
|
|
77
|
-
font-size: round(
|
|
65
|
+
font-size: round(
|
|
66
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
67
|
+
var(--type-snap)
|
|
68
|
+
);
|
|
78
69
|
}
|
|
79
70
|
}
|
|
80
71
|
|
|
81
|
-
@utility text-
|
|
82
|
-
|
|
83
|
-
line-height: 1.45;
|
|
84
|
-
|
|
85
|
-
@supports (font-size: round(1rem, 1rem)) {
|
|
86
|
-
font-size: round(down, var(--fluid-text-sm-raw), var(--fluid-step));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
72
|
+
@utility text-step-0 {
|
|
73
|
+
--step: 0;
|
|
89
74
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
line-height: 1.4;
|
|
75
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
76
|
+
line-height: 1.6;
|
|
93
77
|
|
|
94
78
|
@supports (font-size: round(1rem, 1rem)) {
|
|
95
|
-
font-size: round(
|
|
79
|
+
font-size: round(
|
|
80
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
81
|
+
var(--type-snap)
|
|
82
|
+
);
|
|
96
83
|
}
|
|
97
84
|
}
|
|
98
85
|
|
|
99
|
-
@utility text-
|
|
100
|
-
|
|
101
|
-
line-height: 1.25;
|
|
102
|
-
|
|
103
|
-
@supports (font-size: round(1rem, 1rem)) {
|
|
104
|
-
font-size: round(down, var(--fluid-text-lg-raw), var(--fluid-step));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
86
|
+
@utility text-step-1 {
|
|
87
|
+
--step: 1;
|
|
107
88
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
line-height: 1.15;
|
|
89
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
90
|
+
line-height: 1.7;
|
|
111
91
|
|
|
112
92
|
@supports (font-size: round(1rem, 1rem)) {
|
|
113
|
-
font-size: round(
|
|
93
|
+
font-size: round(
|
|
94
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
95
|
+
var(--type-snap)
|
|
96
|
+
);
|
|
114
97
|
}
|
|
115
98
|
}
|
|
116
99
|
|
|
117
|
-
@utility text-
|
|
118
|
-
|
|
119
|
-
line-height: 1.1;
|
|
120
|
-
|
|
121
|
-
@supports (font-size: round(1rem, 1rem)) {
|
|
122
|
-
font-size: round(down, var(--fluid-text-2xl-raw), var(--fluid-step));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
100
|
+
@utility text-step-2 {
|
|
101
|
+
--step: 2;
|
|
125
102
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
line-height: 1.05;
|
|
103
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
104
|
+
line-height: 1.2;
|
|
129
105
|
|
|
130
106
|
@supports (font-size: round(1rem, 1rem)) {
|
|
131
|
-
font-size: round(
|
|
107
|
+
font-size: round(
|
|
108
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
109
|
+
var(--type-snap)
|
|
110
|
+
);
|
|
132
111
|
}
|
|
133
112
|
}
|
|
134
113
|
|
|
135
|
-
@utility text-
|
|
136
|
-
|
|
137
|
-
|
|
114
|
+
@utility text-step-3 {
|
|
115
|
+
--step: 3;
|
|
116
|
+
|
|
117
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
118
|
+
line-height: 1.2;
|
|
138
119
|
|
|
139
120
|
@supports (font-size: round(1rem, 1rem)) {
|
|
140
|
-
font-size:
|
|
141
|
-
|
|
121
|
+
font-size: round(
|
|
122
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
123
|
+
var(--type-snap)
|
|
142
124
|
);
|
|
143
125
|
}
|
|
144
126
|
}
|
|
145
127
|
|
|
146
|
-
@utility text-
|
|
147
|
-
|
|
148
|
-
|
|
128
|
+
@utility text-step-4 {
|
|
129
|
+
--step: 4;
|
|
130
|
+
|
|
131
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
132
|
+
line-height: 1.15;
|
|
149
133
|
|
|
150
134
|
@supports (font-size: round(1rem, 1rem)) {
|
|
151
|
-
font-size:
|
|
152
|
-
|
|
135
|
+
font-size: round(
|
|
136
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
137
|
+
var(--type-snap)
|
|
153
138
|
);
|
|
154
139
|
}
|
|
155
140
|
}
|
|
156
141
|
|
|
157
|
-
@utility text-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
@utility text-step-5 {
|
|
143
|
+
--step: 5;
|
|
144
|
+
|
|
145
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
146
|
+
line-height: 1.1;
|
|
160
147
|
|
|
161
148
|
@supports (font-size: round(1rem, 1rem)) {
|
|
162
|
-
font-size:
|
|
163
|
-
|
|
149
|
+
font-size: round(
|
|
150
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
151
|
+
var(--type-snap)
|
|
164
152
|
);
|
|
165
153
|
}
|
|
166
154
|
}
|
|
167
155
|
|
|
168
|
-
@utility text-
|
|
169
|
-
|
|
170
|
-
|
|
156
|
+
@utility text-step-6 {
|
|
157
|
+
--step: 6;
|
|
158
|
+
|
|
159
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
160
|
+
line-height: 1.05;
|
|
171
161
|
|
|
172
162
|
@supports (font-size: round(1rem, 1rem)) {
|
|
173
|
-
font-size:
|
|
174
|
-
|
|
163
|
+
font-size: round(
|
|
164
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
165
|
+
var(--type-snap)
|
|
175
166
|
);
|
|
176
167
|
}
|
|
177
168
|
}
|
|
178
169
|
|
|
179
|
-
@utility text-
|
|
180
|
-
|
|
170
|
+
@utility text-step-7 {
|
|
171
|
+
--step: 7;
|
|
172
|
+
|
|
173
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
181
174
|
line-height: 1;
|
|
182
175
|
|
|
183
176
|
@supports (font-size: round(1rem, 1rem)) {
|
|
184
|
-
font-size:
|
|
185
|
-
|
|
177
|
+
font-size: round(
|
|
178
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
179
|
+
var(--type-snap)
|
|
186
180
|
);
|
|
187
181
|
}
|
|
188
182
|
}
|
|
189
183
|
|
|
190
|
-
@utility text-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
@utility text-step-8 {
|
|
185
|
+
--step: 8;
|
|
186
|
+
|
|
187
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
188
|
+
line-height: 0.95;
|
|
193
189
|
|
|
194
190
|
@supports (font-size: round(1rem, 1rem)) {
|
|
195
|
-
font-size:
|
|
196
|
-
|
|
191
|
+
font-size: round(
|
|
192
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
193
|
+
var(--type-snap)
|
|
197
194
|
);
|
|
198
195
|
}
|
|
199
196
|
}
|
|
200
197
|
|
|
201
|
-
@utility text-
|
|
202
|
-
|
|
203
|
-
line-height: 1.5;
|
|
198
|
+
@utility text-step-9 {
|
|
199
|
+
--step: 9;
|
|
204
200
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
@utility text-fluid-sm-cq {
|
|
211
|
-
font-size: var(--fluid-text-sm-cq-raw);
|
|
212
|
-
line-height: 1.45;
|
|
201
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
202
|
+
line-height: 0.95;
|
|
213
203
|
|
|
214
204
|
@supports (font-size: round(1rem, 1rem)) {
|
|
215
|
-
font-size: round(
|
|
205
|
+
font-size: round(
|
|
206
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
207
|
+
var(--type-snap)
|
|
208
|
+
);
|
|
216
209
|
}
|
|
217
210
|
}
|
|
218
211
|
|
|
219
|
-
@utility text-
|
|
220
|
-
|
|
221
|
-
line-height: 1.4;
|
|
212
|
+
@utility text-step-10 {
|
|
213
|
+
--step: 10;
|
|
222
214
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
@utility text-fluid-lg-cq {
|
|
229
|
-
font-size: var(--fluid-text-lg-cq-raw);
|
|
230
|
-
line-height: 1.25;
|
|
215
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
216
|
+
line-height: 0.95;
|
|
231
217
|
|
|
232
218
|
@supports (font-size: round(1rem, 1rem)) {
|
|
233
|
-
font-size: round(
|
|
219
|
+
font-size: round(
|
|
220
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
221
|
+
var(--type-snap)
|
|
222
|
+
);
|
|
234
223
|
}
|
|
235
224
|
}
|
|
236
225
|
|
|
237
|
-
@utility text-
|
|
238
|
-
|
|
239
|
-
|
|
226
|
+
@utility text-step-11 {
|
|
227
|
+
--step: 11;
|
|
228
|
+
|
|
229
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
230
|
+
line-height: 0.95;
|
|
240
231
|
|
|
241
232
|
@supports (font-size: round(1rem, 1rem)) {
|
|
242
|
-
font-size: round(
|
|
233
|
+
font-size: round(
|
|
234
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
235
|
+
var(--type-snap)
|
|
236
|
+
);
|
|
243
237
|
}
|
|
244
238
|
}
|
|
245
239
|
|
|
246
|
-
@utility text-
|
|
247
|
-
|
|
248
|
-
|
|
240
|
+
@utility text-step-12 {
|
|
241
|
+
--step: 12;
|
|
242
|
+
|
|
243
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
244
|
+
line-height: 0.95;
|
|
249
245
|
|
|
250
246
|
@supports (font-size: round(1rem, 1rem)) {
|
|
251
|
-
font-size: round(
|
|
247
|
+
font-size: round(
|
|
248
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
249
|
+
var(--type-snap)
|
|
250
|
+
);
|
|
252
251
|
}
|
|
253
252
|
}
|
|
254
253
|
|
|
255
|
-
@utility text-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
@utility text-step-display {
|
|
255
|
+
--step: var(--step-display);
|
|
256
|
+
|
|
257
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
258
|
+
line-height: 0.95;
|
|
258
259
|
|
|
259
260
|
@supports (font-size: round(1rem, 1rem)) {
|
|
260
|
-
font-size: round(
|
|
261
|
+
font-size: round(
|
|
262
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
263
|
+
var(--type-snap)
|
|
264
|
+
);
|
|
261
265
|
}
|
|
262
266
|
}
|
|
263
267
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
268
|
+
/*
|
|
269
|
+
* Element defaults: body text at step 1, headings at their own step. Only body and
|
|
270
|
+
* h1–h6 set --step/font-size — descendants inherit the computed size normally; a
|
|
271
|
+
* universal `body *` rule would fight component CSS. @layer base, so any Tailwind or
|
|
272
|
+
* Nuxt UI text-* utility on an element still wins. Heading margins stay in core/base.css.
|
|
273
|
+
* Author headings only: Nuxt UI renders its own titles (UModal, USlideover, …) as
|
|
274
|
+
* h1–h6 carrying a data-slot attribute and often no size class, so they keep inheriting.
|
|
275
|
+
* :where() keeps the specificity of a bare type selector.
|
|
276
|
+
*/
|
|
277
|
+
@layer base {
|
|
278
|
+
body {
|
|
279
|
+
--step: 1;
|
|
267
280
|
|
|
268
|
-
|
|
269
|
-
font-size: round(down, var(--fluid-text-4xl-cq-raw), var(--fluid-step));
|
|
281
|
+
line-height: 1.7;
|
|
270
282
|
}
|
|
271
|
-
}
|
|
272
283
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
284
|
+
/* Same expressions as the text-step-* utilities. h1 uses the display step. */
|
|
285
|
+
h1:where(:not([data-slot])) {
|
|
286
|
+
--step: var(--step-display);
|
|
276
287
|
|
|
277
|
-
|
|
278
|
-
|
|
288
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
289
|
+
line-height: 0.95;
|
|
290
|
+
text-wrap: balance;
|
|
279
291
|
}
|
|
280
|
-
}
|
|
281
292
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
line-height: 1;
|
|
293
|
+
h2:where(:not([data-slot])) {
|
|
294
|
+
--step: 3;
|
|
285
295
|
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
line-height: 1.2;
|
|
297
|
+
text-wrap: balance;
|
|
288
298
|
}
|
|
289
|
-
}
|
|
290
299
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
line-height: 1;
|
|
300
|
+
h3:where(:not([data-slot])) {
|
|
301
|
+
--step: 2;
|
|
294
302
|
|
|
295
|
-
|
|
296
|
-
|
|
303
|
+
line-height: 1.2;
|
|
304
|
+
text-wrap: balance;
|
|
297
305
|
}
|
|
298
|
-
}
|
|
299
306
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
307
|
+
h4:where(:not([data-slot])) {
|
|
308
|
+
--step: 1;
|
|
309
|
+
}
|
|
303
310
|
|
|
304
|
-
|
|
305
|
-
|
|
311
|
+
h5:where(:not([data-slot])),
|
|
312
|
+
h6:where(:not([data-slot])) {
|
|
313
|
+
--step: 0;
|
|
306
314
|
}
|
|
307
|
-
}
|
|
308
315
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
316
|
+
body,
|
|
317
|
+
h2:where(:not([data-slot])),
|
|
318
|
+
h3:where(:not([data-slot])),
|
|
319
|
+
h4:where(:not([data-slot])),
|
|
320
|
+
h5:where(:not([data-slot])),
|
|
321
|
+
h6:where(:not([data-slot])) {
|
|
322
|
+
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
323
|
+
}
|
|
312
324
|
|
|
313
325
|
@supports (font-size: round(1rem, 1rem)) {
|
|
314
|
-
|
|
326
|
+
body,
|
|
327
|
+
h2:where(:not([data-slot])),
|
|
328
|
+
h3:where(:not([data-slot])),
|
|
329
|
+
h4:where(:not([data-slot])),
|
|
330
|
+
h5:where(:not([data-slot])),
|
|
331
|
+
h6:where(:not([data-slot])) {
|
|
332
|
+
font-size: round(
|
|
333
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
334
|
+
var(--type-snap)
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
h1:where(:not([data-slot])) {
|
|
339
|
+
font-size: round(
|
|
340
|
+
calc(var(--type-base) * pow(var(--type-scale), var(--step))),
|
|
341
|
+
var(--type-snap)
|
|
342
|
+
);
|
|
343
|
+
}
|
|
315
344
|
}
|
|
316
345
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { useTypography } from '../../composables/typography'
|
|
4
4
|
import type { UiColors } from '../../types/colors'
|
|
5
5
|
import type {
|
|
6
|
-
FluidFontSize,
|
|
7
6
|
FontFamily,
|
|
8
7
|
FontLeading,
|
|
9
8
|
FontSize,
|
|
@@ -13,6 +12,7 @@
|
|
|
13
12
|
FontWidth,
|
|
14
13
|
TextAlign,
|
|
15
14
|
TextTransform,
|
|
15
|
+
TypeStep,
|
|
16
16
|
} from '../../types/typography'
|
|
17
17
|
|
|
18
18
|
const {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
transform = 'none',
|
|
27
27
|
color = 'default',
|
|
28
28
|
size = undefined,
|
|
29
|
-
|
|
29
|
+
step = undefined,
|
|
30
30
|
font = 'mono',
|
|
31
31
|
} = defineProps<{
|
|
32
32
|
language?: string
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
transform?: TextTransform
|
|
40
40
|
color?: UiColors
|
|
41
41
|
size?: FontSize
|
|
42
|
-
|
|
42
|
+
step?: TypeStep
|
|
43
43
|
font?: FontFamily
|
|
44
44
|
}>()
|
|
45
45
|
const { classes } = useTypography(() => ({
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
transform,
|
|
53
53
|
font,
|
|
54
54
|
...(size !== undefined && { size }),
|
|
55
|
-
...(
|
|
55
|
+
...(step !== undefined && { step }),
|
|
56
56
|
}))
|
|
57
57
|
const colorClass = useColor(() => color, 'text')
|
|
58
58
|
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import { describe, expect, it } from 'vite-plus/test'
|
|
3
|
+
|
|
4
|
+
import Headline from './Headline.vue'
|
|
5
|
+
|
|
6
|
+
const render = (props: Record<string, unknown>) =>
|
|
7
|
+
mount(Headline, { props, slots: { default: 'Title' } })
|
|
8
|
+
const classesOf = (props: Record<string, unknown>) => render(props).classes()
|
|
9
|
+
const styleOf = (props: Record<string, unknown>) => render(props).attributes('style') ?? ''
|
|
10
|
+
|
|
11
|
+
describe('Headline step', () => {
|
|
12
|
+
it('steps each level down from the display step by default', () => {
|
|
13
|
+
expect(styleOf({ level: 1 })).toContain('--step: var(--step-display)')
|
|
14
|
+
expect(styleOf({ level: 2 })).toContain('--step: calc(var(--step-display) - 1)')
|
|
15
|
+
expect(styleOf({ level: 6 })).toContain('--step: calc(var(--step-display) - 5)')
|
|
16
|
+
expect(classesOf({ level: 2 }).filter((c) => c.startsWith('text-step-'))).toEqual([])
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('drops the default step when an explicit size is given', () => {
|
|
20
|
+
const wrapper = render({ level: 2, size: 'sm' })
|
|
21
|
+
expect(wrapper.classes()).toContain('text-sm')
|
|
22
|
+
expect(wrapper.attributes('style') ?? '').not.toContain('--step')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('leaves line height to the step unless leading is given', () => {
|
|
26
|
+
expect(classesOf({ level: 2 }).filter((c) => c.startsWith('leading-'))).toEqual([])
|
|
27
|
+
expect(classesOf({ level: 2, leading: 'leading-tight' })).toContain('leading-tight')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('lets an explicit step win over size and the default', () => {
|
|
31
|
+
const wrapper = render({ level: 2, size: 'sm', step: 5 })
|
|
32
|
+
expect(wrapper.classes()).toContain('text-step-5')
|
|
33
|
+
expect(wrapper.classes()).not.toContain('text-sm')
|
|
34
|
+
expect(wrapper.attributes('style') ?? '').not.toContain('--step')
|
|
35
|
+
})
|
|
36
|
+
})
|