@hanzo/design 0.5.7 → 0.5.9
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/dist/preference.d.ts +19 -0
- package/dist/preference.d.ts.map +1 -1
- package/dist/preference.js +16 -0
- package/dist/tokens.gen.d.ts +2 -0
- package/dist/tokens.gen.d.ts.map +1 -1
- package/dist/tokens.gen.js +2 -0
- package/package.json +2 -2
- package/scripts/gen-tokens.mjs +25 -1
- package/scripts/lint.mjs +17 -8
- package/src/preference.ts +24 -0
- package/src/tokens.gen.ts +2 -0
- package/styles.css +38 -13
- package/tailwind.css +38 -13
- package/tokens/typography.css +38 -13
package/dist/preference.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export type Density = "compact" | "default" | "comfortable";
|
|
|
29
29
|
export interface Preference {
|
|
30
30
|
/** Multiplier on the type ramp. 1 is the published scale. */
|
|
31
31
|
type?: number;
|
|
32
|
+
/**
|
|
33
|
+
* How far APART the rungs sit — the ramp's contrast, where `type` is its size.
|
|
34
|
+
* 1 is the published scale; below 1 flattens it toward a uniform register,
|
|
35
|
+
* above 1 opens the display end and tightens the small one.
|
|
36
|
+
*/
|
|
37
|
+
ratio?: number;
|
|
32
38
|
density?: Density;
|
|
33
39
|
/** A CSS colour for --primary / --accent. Rejected unless it is one. */
|
|
34
40
|
accent?: string;
|
|
@@ -44,6 +50,19 @@ export interface Preference {
|
|
|
44
50
|
*/
|
|
45
51
|
export declare const TYPE_MIN = 0.85;
|
|
46
52
|
export declare const TYPE_MAX = 1.4;
|
|
53
|
+
/**
|
|
54
|
+
* The ratio's bounds are looser than type's, because the ramp defends its own
|
|
55
|
+
* floor.
|
|
56
|
+
*
|
|
57
|
+
* `tokens/typography.css` floors --text-xs/sm with `max()`, so the failure mode
|
|
58
|
+
* that forces type's tight clamp — a knob quietly rendering 9px labels — cannot
|
|
59
|
+
* happen on this axis however it combines with type. What is left to bound is
|
|
60
|
+
* only whether the ramp still READS as a ramp: at 0.75 the app register is
|
|
61
|
+
* within a hair of uniform, and past 1.5 a page's h2 has left its own body text
|
|
62
|
+
* behind entirely.
|
|
63
|
+
*/
|
|
64
|
+
export declare const RATIO_MIN = 0.75;
|
|
65
|
+
export declare const RATIO_MAX = 1.5;
|
|
47
66
|
/**
|
|
48
67
|
* Is this a colour, or is it something being smuggled into a style attribute?
|
|
49
68
|
*
|
package/dist/preference.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preference.d.ts","sourceRoot":"","sources":["../src/preference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"preference.d.ts","sourceRoot":"","sources":["../src/preference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,SAAS,MAAM,CAAC;AAqB7B;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAS1C;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuB1D;AAED,2EAA2E;AAC3E,wBAAgB,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,SAAc,GAAG,MAAM,CAKjE"}
|
package/dist/preference.js
CHANGED
|
@@ -36,6 +36,19 @@
|
|
|
36
36
|
*/
|
|
37
37
|
export const TYPE_MIN = 0.85;
|
|
38
38
|
export const TYPE_MAX = 1.4;
|
|
39
|
+
/**
|
|
40
|
+
* The ratio's bounds are looser than type's, because the ramp defends its own
|
|
41
|
+
* floor.
|
|
42
|
+
*
|
|
43
|
+
* `tokens/typography.css` floors --text-xs/sm with `max()`, so the failure mode
|
|
44
|
+
* that forces type's tight clamp — a knob quietly rendering 9px labels — cannot
|
|
45
|
+
* happen on this axis however it combines with type. What is left to bound is
|
|
46
|
+
* only whether the ramp still READS as a ramp: at 0.75 the app register is
|
|
47
|
+
* within a hair of uniform, and past 1.5 a page's h2 has left its own body text
|
|
48
|
+
* behind entirely.
|
|
49
|
+
*/
|
|
50
|
+
export const RATIO_MIN = 0.75;
|
|
51
|
+
export const RATIO_MAX = 1.5;
|
|
39
52
|
/**
|
|
40
53
|
* Density moves SPACING only, and its range is much tighter than type's.
|
|
41
54
|
*
|
|
@@ -81,6 +94,9 @@ export function vars(p) {
|
|
|
81
94
|
if (typeof p.type === "number" && Number.isFinite(p.type)) {
|
|
82
95
|
out["--type-scale"] = round(clamp(p.type, TYPE_MIN, TYPE_MAX));
|
|
83
96
|
}
|
|
97
|
+
if (typeof p.ratio === "number" && Number.isFinite(p.ratio)) {
|
|
98
|
+
out["--type-ratio"] = round(clamp(p.ratio, RATIO_MIN, RATIO_MAX));
|
|
99
|
+
}
|
|
84
100
|
if (p.density && p.density in DENSITY) {
|
|
85
101
|
out["--density"] = round(DENSITY[p.density]);
|
|
86
102
|
}
|
package/dist/tokens.gen.d.ts
CHANGED
|
@@ -92,6 +92,7 @@ export declare const colors: {
|
|
|
92
92
|
/** typography tokens (from tokens/typography.css). Values are raw CSS. */
|
|
93
93
|
export declare const typography: {
|
|
94
94
|
readonly 'type-scale': "1";
|
|
95
|
+
readonly 'type-ratio': "1";
|
|
95
96
|
readonly 'text-xs': "0.6875rem";
|
|
96
97
|
readonly 'leading-xs': "1rem";
|
|
97
98
|
readonly 'text-sm': "0.8125rem";
|
|
@@ -384,6 +385,7 @@ export declare const cssVars: {
|
|
|
384
385
|
readonly '--chrome-dot-yellow': "rgb(234 179 8 / .6)";
|
|
385
386
|
readonly '--chrome-dot-green': "rgb(34 197 94 / .6)";
|
|
386
387
|
readonly '--type-scale': "1";
|
|
388
|
+
readonly '--type-ratio': "1";
|
|
387
389
|
readonly '--text-xs': "0.6875rem";
|
|
388
390
|
readonly '--leading-xs': "1rem";
|
|
389
391
|
readonly '--text-sm': "0.8125rem";
|
package/dist/tokens.gen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.gen.d.ts","sourceRoot":"","sources":["../src/tokens.gen.ts"],"names":[],"mappings":"AAIA,kEAAkE;AAClE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFT,CAAA;AAEV,0EAA0E;AAC1E,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"tokens.gen.d.ts","sourceRoot":"","sources":["../src/tokens.gen.ts"],"names":[],"mappings":"AAIA,kEAAkE;AAClE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFT,CAAA;AAEV,0EAA0E;AAC1E,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiEb,CAAA;AAEV,oEAAoE;AACpE,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CV,CAAA;AAEV,8DAA8D;AAC9D,eAAO,MAAM,IAAI;;;;;;;;;;;;CAYP,CAAA;AAEV,kEAAkE;AAClE,eAAO,MAAM,MAAM;;;;;;;;;CAST,CAAA;AAEV,wEAAwE;AACxE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BZ,CAAA;AAEV,kEAAkE;AAClE,eAAO,MAAM,MAAM;;;;;;;;;;;;;CAaT,CAAA;AAEV,6DAA6D;AAC7D,eAAO,MAAM,MAAM;;;;;;;;;;;;CAYT,CAAA;AAEV,gEAAgE;AAChE,eAAO,MAAM,KAAK;;;;;;CAMR,CAAA;AAEV,8DAA8D;AAC9D,eAAO,MAAM,IAAI,IAEP,CAAA;AAEV,sFAAsF;AACtF,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4QV,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAA"}
|
package/dist/tokens.gen.js
CHANGED
|
@@ -95,6 +95,7 @@ export const colors = {
|
|
|
95
95
|
/** typography tokens (from tokens/typography.css). Values are raw CSS. */
|
|
96
96
|
export const typography = {
|
|
97
97
|
'type-scale': '1',
|
|
98
|
+
'type-ratio': '1',
|
|
98
99
|
'text-xs': '0.6875rem',
|
|
99
100
|
'leading-xs': '1rem',
|
|
100
101
|
'text-sm': '0.8125rem',
|
|
@@ -387,6 +388,7 @@ export const cssVars = {
|
|
|
387
388
|
'--chrome-dot-yellow': 'rgb(234 179 8 / .6)',
|
|
388
389
|
'--chrome-dot-green': 'rgb(34 197 94 / .6)',
|
|
389
390
|
'--type-scale': '1',
|
|
391
|
+
'--type-ratio': '1',
|
|
390
392
|
'--text-xs': '0.6875rem',
|
|
391
393
|
'--leading-xs': '1rem',
|
|
392
394
|
'--text-sm': '0.8125rem',
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/design",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"packageManager": "pnpm@11.17.0",
|
|
5
|
-
"description": "Hanzo Design System
|
|
5
|
+
"description": "Hanzo Design System — monochrome, dark-default tokens + components + brand assets, the single source of truth for every Hanzo surface. CSS + typed programmatic tokens.",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
package/scripts/gen-tokens.mjs
CHANGED
|
@@ -52,9 +52,33 @@ function parse(css) {
|
|
|
52
52
|
* The shape is exact (`calc(<value> * var(--<knob>, 1))`) and only that shape is
|
|
53
53
|
* unwrapped; a genuinely composite calc (`calc(var(--fold) - 1px)`) is untouched.
|
|
54
54
|
* check-tokens.mjs holds it: no emitted value may name a knob.
|
|
55
|
+
*
|
|
56
|
+
* The type ramp adds a second knob INSIDE the first — a rung is
|
|
57
|
+
* `calc((<anchor> ± <delta> * var(--type-ratio, 1)) * var(--type-scale, 1))`, and
|
|
58
|
+
* the small rungs wrap that in a `max()` floor. Both are peeled here, in the
|
|
59
|
+
* order they nest, and the arithmetic is then done at the published defaults
|
|
60
|
+
* (both knobs 1) so the table carries exactly the rung the sheet renders — which
|
|
61
|
+
* is the same number it carried before the ratio existed. The floor is DROPPED
|
|
62
|
+
* rather than evaluated: it exists to catch a person's settings compounding, and
|
|
63
|
+
* at the defaults it never binds, so keeping it would put a guard in the table
|
|
64
|
+
* against a knob the table does not have.
|
|
55
65
|
*/
|
|
56
66
|
const KNOB = /^calc\(\s*([^*]+?)\s*\*\s*var\(--(?:type-scale|density),\s*1\)\s*\)$/
|
|
57
|
-
const
|
|
67
|
+
const FLOOR = /^max\(\s*[\d.]+[a-z%]*\s*,\s*(calc\(.+\))\s*\)$/
|
|
68
|
+
const RUNG =
|
|
69
|
+
/^calc\(\(\s*([\d.]+)(r?em|px)\s*([+-])\s*([\d.]+)(?:r?em|px)\s*\*\s*var\(--type-ratio,\s*1\)\s*\)\s*\*\s*var\(--type-scale,\s*1\)\s*\)$/
|
|
70
|
+
|
|
71
|
+
const scale = (v) => {
|
|
72
|
+
const inner = v.match(FLOOR)?.[1] ?? v
|
|
73
|
+
const r = inner.match(RUNG)
|
|
74
|
+
if (r) {
|
|
75
|
+
const [, anchor, unit, sign, delta] = r
|
|
76
|
+
const n = sign === '-' ? Number(anchor) - Number(delta) : Number(anchor) + Number(delta)
|
|
77
|
+
// 4dp, then trim — 0.875 + 0.75 must read `1.625rem`, not `1.6250000000000002rem`.
|
|
78
|
+
return `${Number(n.toFixed(4))}${unit}`
|
|
79
|
+
}
|
|
80
|
+
return inner.match(KNOB)?.[1] ?? inner
|
|
81
|
+
}
|
|
58
82
|
|
|
59
83
|
const groupMaps = {} // groupName -> Map(name->value), first-wins
|
|
60
84
|
const flatMap = new Map() // '--name' -> value, first-wins
|
package/scripts/lint.mjs
CHANGED
|
@@ -291,10 +291,18 @@ const RULES = [
|
|
|
291
291
|
*
|
|
292
292
|
* { "raw-color": 412, "redeclared-token": 6 }
|
|
293
293
|
*
|
|
294
|
-
* A count
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
294
|
+
* A count UNDER its allowance is REPORTED, loudly, and does not fail. That was
|
|
295
|
+
* the other way round for one release and it froze hanzo.app's: the count a tree
|
|
296
|
+
* produces is not identical everywhere — a working copy holds files a fresh
|
|
297
|
+
* checkout does not — so an allowance that has to match EXACTLY turns a
|
|
298
|
+
* difference of environment into a red release. Every gate this package exists
|
|
299
|
+
* to add has to be worth more than the shipping it stops, and a stale number is
|
|
300
|
+
* never worth that.
|
|
301
|
+
*
|
|
302
|
+
* So: over the allowance FAILS — that violation was written today and there is
|
|
303
|
+
* nothing environmental about it. Under it prints the number to write down. The
|
|
304
|
+
* ratchet is still a ratchet, because the allowance can only be lowered by hand
|
|
305
|
+
* and this line tells you exactly what to lower it to.
|
|
298
306
|
*
|
|
299
307
|
* A rule with no entry is allowed ZERO, so a new rule is live everywhere the
|
|
300
308
|
* day it ships and no surface has to opt in.
|
|
@@ -333,15 +341,16 @@ if (unknown.length) {
|
|
|
333
341
|
process.exit(1)
|
|
334
342
|
}
|
|
335
343
|
|
|
336
|
-
|
|
344
|
+
for (const r of under)
|
|
345
|
+
console.log(` ${r}: ${count[r]} found against ${allow[r] ?? 0} allowed — ${(allow[r] ?? 0) - count[r]} fixed. ` +
|
|
346
|
+
`Lower it to ${count[r]} in ${RATCHET}.`)
|
|
347
|
+
|
|
348
|
+
if (!over.length) {
|
|
337
349
|
const owed = RULES.reduce((a, r) => a + (allow[r] ?? 0), 0)
|
|
338
350
|
console.log(`hanzo-design-lint: ${scanned} files, clean${owed ? ` (${owed} allowed by ${RATCHET})` : ''}`)
|
|
339
351
|
process.exit(0)
|
|
340
352
|
}
|
|
341
353
|
for (const r of over)
|
|
342
354
|
console.log(`\n ${r}: ${count[r]} found, ${allow[r] ?? 0} allowed — a NEW violation. Fix it.`)
|
|
343
|
-
for (const r of under)
|
|
344
|
-
console.log(`\n ${r}: ${count[r]} found, ${allow[r] ?? 0} allowed — you fixed ${(allow[r] ?? 0) - count[r]}. ` +
|
|
345
|
-
`Lower it in ${RATCHET}; the allowance only shrinks.`)
|
|
346
355
|
console.log(`\n${findings.length} violation(s) across ${scanned} files`)
|
|
347
356
|
process.exit(1)
|
package/src/preference.ts
CHANGED
|
@@ -31,6 +31,12 @@ export type Density = "compact" | "default" | "comfortable";
|
|
|
31
31
|
export interface Preference {
|
|
32
32
|
/** Multiplier on the type ramp. 1 is the published scale. */
|
|
33
33
|
type?: number;
|
|
34
|
+
/**
|
|
35
|
+
* How far APART the rungs sit — the ramp's contrast, where `type` is its size.
|
|
36
|
+
* 1 is the published scale; below 1 flattens it toward a uniform register,
|
|
37
|
+
* above 1 opens the display end and tightens the small one.
|
|
38
|
+
*/
|
|
39
|
+
ratio?: number;
|
|
34
40
|
density?: Density;
|
|
35
41
|
/** A CSS colour for --primary / --accent. Rejected unless it is one. */
|
|
36
42
|
accent?: string;
|
|
@@ -48,6 +54,20 @@ export interface Preference {
|
|
|
48
54
|
export const TYPE_MIN = 0.85;
|
|
49
55
|
export const TYPE_MAX = 1.4;
|
|
50
56
|
|
|
57
|
+
/**
|
|
58
|
+
* The ratio's bounds are looser than type's, because the ramp defends its own
|
|
59
|
+
* floor.
|
|
60
|
+
*
|
|
61
|
+
* `tokens/typography.css` floors --text-xs/sm with `max()`, so the failure mode
|
|
62
|
+
* that forces type's tight clamp — a knob quietly rendering 9px labels — cannot
|
|
63
|
+
* happen on this axis however it combines with type. What is left to bound is
|
|
64
|
+
* only whether the ramp still READS as a ramp: at 0.75 the app register is
|
|
65
|
+
* within a hair of uniform, and past 1.5 a page's h2 has left its own body text
|
|
66
|
+
* behind entirely.
|
|
67
|
+
*/
|
|
68
|
+
export const RATIO_MIN = 0.75;
|
|
69
|
+
export const RATIO_MAX = 1.5;
|
|
70
|
+
|
|
51
71
|
/**
|
|
52
72
|
* Density moves SPACING only, and its range is much tighter than type's.
|
|
53
73
|
*
|
|
@@ -99,6 +119,10 @@ export function vars(p: Preference): Record<string, string> {
|
|
|
99
119
|
out["--type-scale"] = round(clamp(p.type, TYPE_MIN, TYPE_MAX));
|
|
100
120
|
}
|
|
101
121
|
|
|
122
|
+
if (typeof p.ratio === "number" && Number.isFinite(p.ratio)) {
|
|
123
|
+
out["--type-ratio"] = round(clamp(p.ratio, RATIO_MIN, RATIO_MAX));
|
|
124
|
+
}
|
|
125
|
+
|
|
102
126
|
if (p.density && p.density in DENSITY) {
|
|
103
127
|
out["--density"] = round(DENSITY[p.density]);
|
|
104
128
|
}
|
package/src/tokens.gen.ts
CHANGED
|
@@ -97,6 +97,7 @@ export const colors = {
|
|
|
97
97
|
/** typography tokens (from tokens/typography.css). Values are raw CSS. */
|
|
98
98
|
export const typography = {
|
|
99
99
|
'type-scale': '1',
|
|
100
|
+
'type-ratio': '1',
|
|
100
101
|
'text-xs': '0.6875rem',
|
|
101
102
|
'leading-xs': '1rem',
|
|
102
103
|
'text-sm': '0.8125rem',
|
|
@@ -400,6 +401,7 @@ export const cssVars = {
|
|
|
400
401
|
'--chrome-dot-yellow': 'rgb(234 179 8 / .6)',
|
|
401
402
|
'--chrome-dot-green': 'rgb(34 197 94 / .6)',
|
|
402
403
|
'--type-scale': '1',
|
|
404
|
+
'--type-ratio': '1',
|
|
403
405
|
'--text-xs': '0.6875rem',
|
|
404
406
|
'--leading-xs': '1rem',
|
|
405
407
|
'--text-sm': '0.8125rem',
|
package/styles.css
CHANGED
|
@@ -296,19 +296,44 @@
|
|
|
296
296
|
@hanzo/design's `vars({type})` emits exactly this name. */
|
|
297
297
|
--type-scale:1;
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
299
|
+
/* The CONTRAST knob — how far apart the rungs sit, where --type-scale is how
|
|
300
|
+
big they all are. Two different questions, and only the first one was
|
|
301
|
+
askable: a surface could take the whole ramp up 15% but could not flatten a
|
|
302
|
+
dense table's steps or open up a marketing page's, so both settled for the
|
|
303
|
+
app register's tight default.
|
|
304
|
+
|
|
305
|
+
It is authored as a TRANSFORM and not as a generated ramp, which is the
|
|
306
|
+
whole point. `base + (authored - base) * ratio` keeps each rung's authored
|
|
307
|
+
value as the INPUT, so ratio 1 reduces to exactly the published number by
|
|
308
|
+
algebra rather than by care — the deltas below are just `authored - 0.875`.
|
|
309
|
+
The alternative, deriving each rung as base * ratio^n, would restate the
|
|
310
|
+
ramp in a second place, and this scale is not geometric anyway: the app
|
|
311
|
+
register (11/13/14/15/17) is near-linear on purpose and a ratio applied to
|
|
312
|
+
it would erase the 1px steps the compact register is FOR. That drift is not
|
|
313
|
+
hypothetical here — see src/preference.ts, where a recomputed copy of this
|
|
314
|
+
ramp shipped `lg: 16px` against this file's 15px.
|
|
315
|
+
|
|
316
|
+
A rung is one place, so a rung added later needs a delta and nothing else. */
|
|
317
|
+
--type-ratio:1;
|
|
318
|
+
|
|
319
|
+
/* --text-xs/sm carry a floor because the knobs COMPOUND: a flat ratio shrinks
|
|
320
|
+
the small end while a small scale shrinks everything, and the two multiply.
|
|
321
|
+
Clamping each knob's range separately cannot fix that (0.85 x 0.9 is inside
|
|
322
|
+
both bounds and lands at 8.5px); flooring the RESULT can, so no combination
|
|
323
|
+
of a person's settings and an org's renders its own labels illegible. */
|
|
324
|
+
--text-xs:max(0.625rem, calc((0.875rem - 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-xs:calc((1.35rem - 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 11px — eyebrows / section labels */
|
|
325
|
+
--text-sm:max(0.6875rem, calc((0.875rem - 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-sm:calc((1.35rem - 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 13px — nav labels, dense body */
|
|
326
|
+
--text-base:calc(0.875rem * var(--type-scale, 1)); --leading-base:calc(1.35rem * var(--type-scale, 1)); /* 14px — the ANCHOR: the rung the ratio pivots on, so it carries no ratio term */
|
|
327
|
+
--text-lg:calc((0.875rem + 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-lg:calc((1.35rem + 0.05rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 15px */
|
|
328
|
+
--text-xl:calc((0.875rem + 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-xl:calc((1.35rem + 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 17px */
|
|
329
|
+
--text-2xl:calc((0.875rem + 0.4375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-2xl:calc((1.35rem + 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 21px */
|
|
330
|
+
--text-3xl:calc((0.875rem + 0.75rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-3xl:calc((1.35rem + 0.6rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 26px */
|
|
331
|
+
--text-4xl:calc((0.875rem + 1.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-4xl:calc((1.35rem + 0.9rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 32px */
|
|
332
|
+
--text-5xl:calc((0.875rem + 1.625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-5xl:1.05; /* 40px — display leading is unitless, so it tracks its own size */
|
|
333
|
+
--text-6xl:calc((0.875rem + 2.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-6xl:1; /* 52px */
|
|
334
|
+
--text-7xl:calc((0.875rem + 3.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-7xl:1; /* 64px */
|
|
335
|
+
--text-8xl:calc((0.875rem + 4.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-8xl:1; /* 84px */
|
|
336
|
+
--text-9xl:calc((0.875rem + 6.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-9xl:1; /* 112px */
|
|
312
337
|
|
|
313
338
|
/* The SAME scale under @hanzo/brand's spelling. @hanzo/gui's shell theme and
|
|
314
339
|
Hanzo Studio address the ramp as --font-size-*; both names are one value, so
|
package/tailwind.css
CHANGED
|
@@ -319,19 +319,44 @@
|
|
|
319
319
|
@hanzo/design's `vars({type})` emits exactly this name. */
|
|
320
320
|
--type-scale:1;
|
|
321
321
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
322
|
+
/* The CONTRAST knob — how far apart the rungs sit, where --type-scale is how
|
|
323
|
+
big they all are. Two different questions, and only the first one was
|
|
324
|
+
askable: a surface could take the whole ramp up 15% but could not flatten a
|
|
325
|
+
dense table's steps or open up a marketing page's, so both settled for the
|
|
326
|
+
app register's tight default.
|
|
327
|
+
|
|
328
|
+
It is authored as a TRANSFORM and not as a generated ramp, which is the
|
|
329
|
+
whole point. `base + (authored - base) * ratio` keeps each rung's authored
|
|
330
|
+
value as the INPUT, so ratio 1 reduces to exactly the published number by
|
|
331
|
+
algebra rather than by care — the deltas below are just `authored - 0.875`.
|
|
332
|
+
The alternative, deriving each rung as base * ratio^n, would restate the
|
|
333
|
+
ramp in a second place, and this scale is not geometric anyway: the app
|
|
334
|
+
register (11/13/14/15/17) is near-linear on purpose and a ratio applied to
|
|
335
|
+
it would erase the 1px steps the compact register is FOR. That drift is not
|
|
336
|
+
hypothetical here — see src/preference.ts, where a recomputed copy of this
|
|
337
|
+
ramp shipped `lg: 16px` against this file's 15px.
|
|
338
|
+
|
|
339
|
+
A rung is one place, so a rung added later needs a delta and nothing else. */
|
|
340
|
+
--type-ratio:1;
|
|
341
|
+
|
|
342
|
+
/* --text-xs/sm carry a floor because the knobs COMPOUND: a flat ratio shrinks
|
|
343
|
+
the small end while a small scale shrinks everything, and the two multiply.
|
|
344
|
+
Clamping each knob's range separately cannot fix that (0.85 x 0.9 is inside
|
|
345
|
+
both bounds and lands at 8.5px); flooring the RESULT can, so no combination
|
|
346
|
+
of a person's settings and an org's renders its own labels illegible. */
|
|
347
|
+
--text-xs:max(0.625rem, calc((0.875rem - 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-xs:calc((1.35rem - 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 11px — eyebrows / section labels */
|
|
348
|
+
--text-sm:max(0.6875rem, calc((0.875rem - 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-sm:calc((1.35rem - 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 13px — nav labels, dense body */
|
|
349
|
+
--text-base:calc(0.875rem * var(--type-scale, 1)); --leading-base:calc(1.35rem * var(--type-scale, 1)); /* 14px — the ANCHOR: the rung the ratio pivots on, so it carries no ratio term */
|
|
350
|
+
--text-lg:calc((0.875rem + 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-lg:calc((1.35rem + 0.05rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 15px */
|
|
351
|
+
--text-xl:calc((0.875rem + 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-xl:calc((1.35rem + 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 17px */
|
|
352
|
+
--text-2xl:calc((0.875rem + 0.4375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-2xl:calc((1.35rem + 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 21px */
|
|
353
|
+
--text-3xl:calc((0.875rem + 0.75rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-3xl:calc((1.35rem + 0.6rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 26px */
|
|
354
|
+
--text-4xl:calc((0.875rem + 1.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-4xl:calc((1.35rem + 0.9rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 32px */
|
|
355
|
+
--text-5xl:calc((0.875rem + 1.625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-5xl:1.05; /* 40px — display leading is unitless, so it tracks its own size */
|
|
356
|
+
--text-6xl:calc((0.875rem + 2.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-6xl:1; /* 52px */
|
|
357
|
+
--text-7xl:calc((0.875rem + 3.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-7xl:1; /* 64px */
|
|
358
|
+
--text-8xl:calc((0.875rem + 4.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-8xl:1; /* 84px */
|
|
359
|
+
--text-9xl:calc((0.875rem + 6.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-9xl:1; /* 112px */
|
|
335
360
|
|
|
336
361
|
/* The SAME scale under @hanzo/brand's spelling. @hanzo/gui's shell theme and
|
|
337
362
|
Hanzo Studio address the ramp as --font-size-*; both names are one value, so
|
package/tokens/typography.css
CHANGED
|
@@ -11,19 +11,44 @@
|
|
|
11
11
|
@hanzo/design's `vars({type})` emits exactly this name. */
|
|
12
12
|
--type-scale:1;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
/* The CONTRAST knob — how far apart the rungs sit, where --type-scale is how
|
|
15
|
+
big they all are. Two different questions, and only the first one was
|
|
16
|
+
askable: a surface could take the whole ramp up 15% but could not flatten a
|
|
17
|
+
dense table's steps or open up a marketing page's, so both settled for the
|
|
18
|
+
app register's tight default.
|
|
19
|
+
|
|
20
|
+
It is authored as a TRANSFORM and not as a generated ramp, which is the
|
|
21
|
+
whole point. `base + (authored - base) * ratio` keeps each rung's authored
|
|
22
|
+
value as the INPUT, so ratio 1 reduces to exactly the published number by
|
|
23
|
+
algebra rather than by care — the deltas below are just `authored - 0.875`.
|
|
24
|
+
The alternative, deriving each rung as base * ratio^n, would restate the
|
|
25
|
+
ramp in a second place, and this scale is not geometric anyway: the app
|
|
26
|
+
register (11/13/14/15/17) is near-linear on purpose and a ratio applied to
|
|
27
|
+
it would erase the 1px steps the compact register is FOR. That drift is not
|
|
28
|
+
hypothetical here — see src/preference.ts, where a recomputed copy of this
|
|
29
|
+
ramp shipped `lg: 16px` against this file's 15px.
|
|
30
|
+
|
|
31
|
+
A rung is one place, so a rung added later needs a delta and nothing else. */
|
|
32
|
+
--type-ratio:1;
|
|
33
|
+
|
|
34
|
+
/* --text-xs/sm carry a floor because the knobs COMPOUND: a flat ratio shrinks
|
|
35
|
+
the small end while a small scale shrinks everything, and the two multiply.
|
|
36
|
+
Clamping each knob's range separately cannot fix that (0.85 x 0.9 is inside
|
|
37
|
+
both bounds and lands at 8.5px); flooring the RESULT can, so no combination
|
|
38
|
+
of a person's settings and an org's renders its own labels illegible. */
|
|
39
|
+
--text-xs:max(0.625rem, calc((0.875rem - 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-xs:calc((1.35rem - 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 11px — eyebrows / section labels */
|
|
40
|
+
--text-sm:max(0.6875rem, calc((0.875rem - 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1))); --leading-sm:calc((1.35rem - 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 13px — nav labels, dense body */
|
|
41
|
+
--text-base:calc(0.875rem * var(--type-scale, 1)); --leading-base:calc(1.35rem * var(--type-scale, 1)); /* 14px — the ANCHOR: the rung the ratio pivots on, so it carries no ratio term */
|
|
42
|
+
--text-lg:calc((0.875rem + 0.0625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-lg:calc((1.35rem + 0.05rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 15px */
|
|
43
|
+
--text-xl:calc((0.875rem + 0.1875rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-xl:calc((1.35rem + 0.2rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 17px */
|
|
44
|
+
--text-2xl:calc((0.875rem + 0.4375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-2xl:calc((1.35rem + 0.35rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 21px */
|
|
45
|
+
--text-3xl:calc((0.875rem + 0.75rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-3xl:calc((1.35rem + 0.6rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 26px */
|
|
46
|
+
--text-4xl:calc((0.875rem + 1.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-4xl:calc((1.35rem + 0.9rem * var(--type-ratio, 1)) * var(--type-scale, 1)); /* 32px */
|
|
47
|
+
--text-5xl:calc((0.875rem + 1.625rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-5xl:1.05; /* 40px — display leading is unitless, so it tracks its own size */
|
|
48
|
+
--text-6xl:calc((0.875rem + 2.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-6xl:1; /* 52px */
|
|
49
|
+
--text-7xl:calc((0.875rem + 3.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-7xl:1; /* 64px */
|
|
50
|
+
--text-8xl:calc((0.875rem + 4.375rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-8xl:1; /* 84px */
|
|
51
|
+
--text-9xl:calc((0.875rem + 6.125rem * var(--type-ratio, 1)) * var(--type-scale, 1)); --leading-9xl:1; /* 112px */
|
|
27
52
|
|
|
28
53
|
/* The SAME scale under @hanzo/brand's spelling. @hanzo/gui's shell theme and
|
|
29
54
|
Hanzo Studio address the ramp as --font-size-*; both names are one value, so
|