@multiplatform.one/theme 7.4.1 → 7.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +5 -5
- package/src/audit/index.ts +19 -0
- package/src/audit/themeMatrix.spec.ts +274 -0
- package/src/audit/themeMatrix.ts +630 -0
- package/src/figma/figmaTokens.spec.ts +25 -21
- package/src/figma/figmaTokens.ts +2 -2
- package/src/font.ts +37 -25
- package/src/index.ts +12 -0
- package/src/keyboardFocusRing.ts +12 -6
- package/src/theme/FontKnobStyles.tsx +14 -31
- package/src/theme/Tint.tsx +3 -2
- package/src/theme/animations/css.ts +14 -1
- package/src/theme/colorRules.spec.ts +306 -2
- package/src/theme/colorRules.ts +118 -0
- package/src/theme/cornerSmoothing.native.ts +39 -2
- package/src/theme/cornerSmoothing.spec.ts +270 -3
- package/src/theme/cornerSmoothing.ts +147 -10
- package/src/theme/createDefaultThemeConfig.spec.ts +107 -1
- package/src/theme/createDefaultThemeConfig.ts +27 -8
- package/src/theme/defaults/builderOptions.ts +23 -10
- package/src/theme/defaults/categoryFonts.ts +24 -0
- package/src/theme/defaults/fonts.spec.ts +163 -10
- package/src/theme/defaults/fonts.theme.spec.tsx +139 -0
- package/src/theme/defaults/fonts.ts +214 -50
- package/src/theme/defaults/index.ts +1 -0
- package/src/theme/devtools/ThemeDevtoolsPanel.tsx +0 -11
- package/src/theme/focusState.spec.ts +119 -1
- package/src/theme/focusState.ts +32 -7
- package/src/theme/fontCategoryMetrics.ts +57 -0
- package/src/theme/fontCategoryStacks.ts +37 -0
- package/src/theme/fontKnobStyles.spec.ts +15 -2
- package/src/theme/glyphPaint.spec.ts +26 -0
- package/src/theme/glyphPaint.ts +46 -0
- package/src/theme/index.ts +4 -0
- package/src/theme/knobs.ts +18 -2
- package/src/theme/layoutTokens.spec.ts +3 -1
- package/src/theme/layoutTokens.ts +47 -4
- package/src/theme/mpo13Proof.spec.ts +3 -3
- package/src/theme/mpo19Proof.spec.ts +285 -0
- package/src/theme/presets.ts +1 -1
- package/src/theme/radiusClass.spec.ts +394 -0
- package/src/theme/radiusClass.ts +203 -4
- package/src/theme/radiusClassTable.generated.ts +121 -0
- package/src/theme/recipeInputs.ts +223 -36
- package/src/theme/recipes.ts +68 -4
- package/src/theme/resolveKnobs.spec.ts +155 -13
- package/src/theme/resolveKnobs.ts +193 -27
- package/src/theme/sizeLadder.spec.ts +84 -0
- package/src/theme/sizeRecipes.spec.ts +19 -6
- package/src/theme/sizeRecipes.ts +43 -13
- package/src/theme/theme.native.tsx +2 -0
- package/src/theme/theme.provider.spec.ts +9 -0
- package/src/theme/theme.tsx +6 -3
- package/src/theme/tint.spec.tsx +36 -35
- package/src/theme/useResolvedKnobs.ts +6 -3
- package/types/audit/index.d.ts +2 -0
- package/types/audit/index.d.ts.map +1 -1
- package/types/audit/themeMatrix.d.ts +172 -0
- package/types/audit/themeMatrix.d.ts.map +1 -0
- package/types/figma/figmaTokens.d.ts +1 -1
- package/types/figma/figmaTokens.d.ts.map +1 -1
- package/types/font.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/keyboardFocusRing.d.ts +11 -5
- package/types/keyboardFocusRing.d.ts.map +1 -1
- package/types/theme/FontKnobStyles.d.ts +8 -12
- package/types/theme/FontKnobStyles.d.ts.map +1 -1
- package/types/theme/Tint.d.ts +2 -1
- package/types/theme/Tint.d.ts.map +1 -1
- package/types/theme/animations/css.d.ts +15 -2
- package/types/theme/animations/css.d.ts.map +1 -1
- package/types/theme/colorRules.d.ts +59 -1
- package/types/theme/colorRules.d.ts.map +1 -1
- package/types/theme/cornerSmoothing.d.ts +42 -20
- package/types/theme/cornerSmoothing.d.ts.map +1 -1
- package/types/theme/cornerSmoothing.native.d.ts +22 -2
- package/types/theme/cornerSmoothing.native.d.ts.map +1 -1
- package/types/theme/createDefaultThemeConfig.d.ts +21 -3
- package/types/theme/createDefaultThemeConfig.d.ts.map +1 -1
- package/types/theme/defaults/builderOptions.d.ts.map +1 -1
- package/types/theme/defaults/categoryFonts.d.ts +23 -0
- package/types/theme/defaults/categoryFonts.d.ts.map +1 -0
- package/types/theme/defaults/fonts.d.ts +140 -2
- package/types/theme/defaults/fonts.d.ts.map +1 -1
- package/types/theme/defaults/index.d.ts +1 -0
- package/types/theme/defaults/index.d.ts.map +1 -1
- package/types/theme/devtools/ThemeDevtoolsPanel.d.ts.map +1 -1
- package/types/theme/focusState.d.ts +32 -6
- package/types/theme/focusState.d.ts.map +1 -1
- package/types/theme/fontCategoryMetrics.d.ts +36 -0
- package/types/theme/fontCategoryMetrics.d.ts.map +1 -0
- package/types/theme/fontCategoryStacks.d.ts +24 -0
- package/types/theme/fontCategoryStacks.d.ts.map +1 -0
- package/types/theme/glyphPaint.d.ts +16 -0
- package/types/theme/glyphPaint.d.ts.map +1 -0
- package/types/theme/index.d.ts +4 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/knobs.d.ts +10 -2
- package/types/theme/knobs.d.ts.map +1 -1
- package/types/theme/layoutTokens.d.ts +46 -4
- package/types/theme/layoutTokens.d.ts.map +1 -1
- package/types/theme/radiusClass.d.ts +96 -4
- package/types/theme/radiusClass.d.ts.map +1 -1
- package/types/theme/radiusClassTable.generated.d.ts +146 -0
- package/types/theme/radiusClassTable.generated.d.ts.map +1 -0
- package/types/theme/recipeInputs.d.ts +85 -14
- package/types/theme/recipeInputs.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +78 -4
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +12 -1
- package/types/theme/resolveKnobs.d.ts.map +1 -1
- package/types/theme/sizeRecipes.d.ts +27 -14
- package/types/theme/sizeRecipes.d.ts.map +1 -1
- package/types/theme/theme.d.ts.map +1 -1
- package/types/theme/theme.native.d.ts.map +1 -1
- package/types/theme/useResolvedKnobs.d.ts +2 -2
- package/types/theme/useResolvedKnobs.d.ts.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Colors from "@tamagui/colors";
|
|
2
|
-
import {
|
|
2
|
+
import { defaultConfig } from "@tamagui/config/v5";
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
import { normalizeToHex } from "../theme/colorRules";
|
|
5
5
|
import { defaultAccentTheme } from "../theme/defaults/accent";
|
|
@@ -89,13 +89,13 @@ describe("buildFigmaTokens", () => {
|
|
|
89
89
|
|
|
90
90
|
describe("semantic", () => {
|
|
91
91
|
it("derives the current interaction-ramp aliases (post-knobs rebuild)", () => {
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
// MPO-19 X4: the seven pinned ramp steps were deleted from
|
|
93
|
+
// `defaultBuilderOptions.getTheme`, so these aliases are the theme
|
|
94
|
+
// BUILDER's derivation again rather than mpo's re-anchoring. That is
|
|
95
|
+
// the correction landing, and what this pins is that it landed —
|
|
96
|
+
// borderColor back off color5, the background states no longer forced.
|
|
97
|
+
expect(result.semantic.borderColor?.alias).toBe("color4");
|
|
96
98
|
expect(result.semantic.textMuted?.alias).toBe("color11");
|
|
97
|
-
expect(result.semantic.backgroundPress?.alias).toBe("color5");
|
|
98
|
-
expect(result.semantic.backgroundActive?.alias).toBe("color4");
|
|
99
99
|
expect(result.semantic.placeholderColor?.alias).toBe("color10");
|
|
100
100
|
expect(result.semantic.surfaceMuted?.alias).toBe("color10");
|
|
101
101
|
expect(result.semantic.borderStrong?.alias).toBe("color7");
|
|
@@ -135,13 +135,16 @@ describe("buildFigmaTokens", () => {
|
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
describe("sizing", () => {
|
|
138
|
-
it("mirrors
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
expect(result.sizing["
|
|
138
|
+
it("mirrors the v5 defaultConfig tokens with figma-safe names", () => {
|
|
139
|
+
// Read against the ERA the package pins (MPO-19 X13), not against a
|
|
140
|
+
// transcribed table: v5 keys carry the `$`, values are raw numbers.
|
|
141
|
+
const size = defaultConfig.tokens.size as Record<string, number>;
|
|
142
|
+
expect(result.sizing["size-true"]).toBe(size.$true);
|
|
143
|
+
expect(result.sizing["radius-4"]).toBe(
|
|
144
|
+
(defaultConfig.tokens.radius as Record<string, number>)["4"],
|
|
145
|
+
);
|
|
143
146
|
expect(result.sizing["space-1-5"]).toBe(
|
|
144
|
-
(tokens.space as Record<string,
|
|
147
|
+
(defaultConfig.tokens.space as Record<string, number>)["$1.5"],
|
|
145
148
|
);
|
|
146
149
|
});
|
|
147
150
|
|
|
@@ -181,7 +184,7 @@ describe("buildFigmaTokens", () => {
|
|
|
181
184
|
const { modes } = result.knobs.elevation;
|
|
182
185
|
expect(modes.none).toEqual({ sizeToken: null, px: null });
|
|
183
186
|
expect(modes.small.sizeToken).toBe("$1");
|
|
184
|
-
expect(modes.small.px).toBe((tokens.size as Record<string,
|
|
187
|
+
expect(modes.small.px).toBe((defaultConfig.tokens.size as Record<string, number>).$1);
|
|
185
188
|
expect(modes.medium.sizeToken).toBe("$2");
|
|
186
189
|
expect(modes.large.sizeToken).toBe("$4");
|
|
187
190
|
});
|
|
@@ -216,17 +219,18 @@ describe("buildFigmaTokens", () => {
|
|
|
216
219
|
|
|
217
220
|
describe("typography (closes deferred task 10.0)", () => {
|
|
218
221
|
it("exports heading/body size + lineHeight tables from the built default fonts", () => {
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
expect(result.typography.body.
|
|
224
|
-
expect(result.typography.
|
|
222
|
+
// MPO-19 X8/X9: heading rides the body scale now, so H1 $10 is 40 at
|
|
223
|
+
// weight 800 rather than 64 at 400, and body $true is v5's 15 with the
|
|
224
|
+
// tapering leading instead of v4's 14 with `size + 10`.
|
|
225
|
+
expect(result.typography.heading.size["10"]).toBe(40);
|
|
226
|
+
expect(result.typography.body.size.true).toBe(15);
|
|
227
|
+
expect(result.typography.body.lineHeight.true).toBe(23);
|
|
228
|
+
expect(result.typography.heading.lineHeight["10"]).toBe(50);
|
|
225
229
|
});
|
|
226
230
|
|
|
227
231
|
it("exports Inter dynamic tracking per size", () => {
|
|
228
232
|
const body = result.typography.body;
|
|
229
|
-
expect(body.letterSpacing.true).toBe(interTrackingPx(
|
|
233
|
+
expect(body.letterSpacing.true).toBe(interTrackingPx(15));
|
|
230
234
|
expect(Object.keys(body.letterSpacing).length).toBeGreaterThanOrEqual(16);
|
|
231
235
|
});
|
|
232
236
|
|
package/src/figma/figmaTokens.ts
CHANGED
|
@@ -93,7 +93,7 @@ export interface FigmaRadiusMode {
|
|
|
93
93
|
/** `Sizing` collection variable to alias (e.g. `radius-4`). */
|
|
94
94
|
figmaName: string;
|
|
95
95
|
px: number;
|
|
96
|
-
/** Outer/nested radius fragment (`knobProps.
|
|
96
|
+
/** Outer/nested radius fragment (`knobProps.borderRadiusNested`). */
|
|
97
97
|
outerToken: string;
|
|
98
98
|
outerFigmaName: string;
|
|
99
99
|
outerPx: number;
|
|
@@ -344,7 +344,7 @@ function buildKnobs(): FigmaKnobsExport {
|
|
|
344
344
|
for (const mode of RADIUS_KNOB_MODES) {
|
|
345
345
|
const { knobProps } = resolveKnobs({ ...defaultKnobs, borderRadius: mode });
|
|
346
346
|
const token = String(knobProps.borderRadius.borderRadius);
|
|
347
|
-
const outerToken = String(knobProps.
|
|
347
|
+
const outerToken = String(knobProps.borderRadiusNested.borderRadius);
|
|
348
348
|
borderRadius[mode] = {
|
|
349
349
|
token,
|
|
350
350
|
figmaName: tokenToFigma(token, "radius"),
|
package/src/font.ts
CHANGED
|
@@ -1,33 +1,38 @@
|
|
|
1
1
|
import type { GenericFont } from "@tamagui/web";
|
|
2
2
|
import { createFont } from "@tamagui/web";
|
|
3
|
+
import {
|
|
4
|
+
bodyFontLineHeights,
|
|
5
|
+
bodyFontSizes,
|
|
6
|
+
bodyLineHeightPx,
|
|
7
|
+
categoryLineHeights,
|
|
8
|
+
} from "./theme/defaults/fonts";
|
|
3
9
|
|
|
4
10
|
const defaults = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
11: 52,
|
|
17
|
-
12: 62,
|
|
18
|
-
13: 72,
|
|
19
|
-
14: 92,
|
|
20
|
-
15: 114,
|
|
21
|
-
16: 124,
|
|
22
|
-
} as const,
|
|
11
|
+
// The era's `$body` ladder, including `true`. A missing `true` key is what
|
|
12
|
+
// collapsed `$serif`/`$mono`/`$rounded` to -apple-system 14px/normal on the
|
|
13
|
+
// label text node (MPO-44); a DIFFERENT ladder is the follow-on defect —
|
|
14
|
+
// a family knob that also resizes the label is still moving type off the
|
|
15
|
+
// ramp. A consumer font registered through this helper lands exactly where
|
|
16
|
+
// the built-in category fonts do.
|
|
17
|
+
size: bodyFontSizes,
|
|
18
|
+
// Floored at the generic body ratio (LC-11). `createDefaultFont` does not
|
|
19
|
+
// know which category it is building, so it takes the sans-serif floor;
|
|
20
|
+
// `defaults/fonts.ts` applies the per-category ones.
|
|
21
|
+
lineHeight: categoryLineHeights("sans-serif"),
|
|
23
22
|
// Neutral by default (LC-11): tracking is a per-family function of size,
|
|
24
23
|
// so a shared constant table is always wrong for someone — the previous
|
|
25
24
|
// Inter-ish table leaked +3px tracking into mono/script faces at $5/$6
|
|
26
|
-
// (see p-results/fixes-polish2-codeblock-density.md).
|
|
27
|
-
//
|
|
28
|
-
|
|
25
|
+
// (see p-results/fixes-polish2-codeblock-density.md). Explicit zeros, not
|
|
26
|
+
// an empty table: an empty table emits no `--f-letterSpacing-*` and the
|
|
27
|
+
// value falls through to the `:root` Inter curve.
|
|
28
|
+
letterSpacing: Object.fromEntries(Object.keys(bodyFontSizes).map((k) => [k, 0])) as Record<
|
|
29
|
+
string | number,
|
|
30
|
+
number
|
|
31
|
+
>,
|
|
32
|
+
// The era's body weight. Was 300, which is off the reference's 400 label
|
|
33
|
+
// weight in the light direction and made a bodyFont flip change weight.
|
|
29
34
|
weight: {
|
|
30
|
-
4: "
|
|
35
|
+
4: "400",
|
|
31
36
|
} as const,
|
|
32
37
|
};
|
|
33
38
|
|
|
@@ -35,10 +40,17 @@ export function createDefaultFont<A extends GenericFont>(
|
|
|
35
40
|
font: Partial<A> & { family: A["family"] },
|
|
36
41
|
): A {
|
|
37
42
|
const size = font.size || defaults.size;
|
|
43
|
+
const lineHeight =
|
|
44
|
+
size === defaults.size
|
|
45
|
+
? defaults.lineHeight
|
|
46
|
+
: (Object.fromEntries(
|
|
47
|
+
Object.entries(size).map(([k, v]) => [
|
|
48
|
+
k,
|
|
49
|
+
typeof v === "number" ? (bodyFontLineHeights[k] ?? bodyLineHeightPx(v)) : v,
|
|
50
|
+
]),
|
|
51
|
+
) as typeof size);
|
|
38
52
|
return createFont({
|
|
39
|
-
lineHeight
|
|
40
|
-
Object.entries(size).map(([k, v]) => [k, typeof v === "number" ? v * 1.2 + 6 : v]),
|
|
41
|
-
) as typeof size,
|
|
53
|
+
lineHeight,
|
|
42
54
|
letterSpacing: defaults.letterSpacing,
|
|
43
55
|
weight: defaults.weight,
|
|
44
56
|
...font,
|
package/src/index.ts
CHANGED
|
@@ -7,5 +7,17 @@ export * from "./menuRow";
|
|
|
7
7
|
export * from "./font";
|
|
8
8
|
export * from "./fonts/index";
|
|
9
9
|
|
|
10
|
+
// Contrast + matrix assertions downstream repos call (MPO-18). The full
|
|
11
|
+
// audit surface including the browser-side capturer stays on ./audit.
|
|
12
|
+
export { diffGeometry, evaluateNoBreakage, evaluateTextContrast } from "./audit";
|
|
13
|
+
export type {
|
|
14
|
+
GeometryDiff,
|
|
15
|
+
MatrixTextSample,
|
|
16
|
+
NoBreakageInput,
|
|
17
|
+
NoBreakageResult,
|
|
18
|
+
TextContrastResult,
|
|
19
|
+
TextContrastViolation,
|
|
20
|
+
} from "./audit";
|
|
21
|
+
|
|
10
22
|
// Thin type re-exports so packages/apps never import @tamagui/web directly.
|
|
11
23
|
export type { GenericFonts, MediaQueryKey, ThemeName } from "@tamagui/web";
|
package/src/keyboardFocusRing.ts
CHANGED
|
@@ -36,15 +36,21 @@ export function wasKeyboardFocus(): boolean {
|
|
|
36
36
|
return lastInputWasKeyboard;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
import {
|
|
39
|
+
import { FOCUS_VISIBLE_RING_INSET } from "./theme/focusState";
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Standard manual ring props — the
|
|
43
|
-
* (2px solid `$outlineColor`,
|
|
44
|
-
*
|
|
42
|
+
* Standard manual ring props — the INSET ring geometry
|
|
43
|
+
* (`FOCUS_VISIBLE_RING_INSET`: 2px solid `$outlineColor`, offset −2), spread
|
|
44
|
+
* here so manually-painted rings can never drift from the theme contract.
|
|
45
|
+
* Manual painting exists for roving-focus / activedescendant composites
|
|
46
|
+
* (ToggleGroup segments inside a clipped Group, menu/listbox rows under a
|
|
47
|
+
* clipped overlay, table rows and cells) — items inside clipping ancestors,
|
|
48
|
+
* which is exactly the LC-71 §4 inset carve-out; an offset-0 band there
|
|
49
|
+
* would be severed by the clip. Standalone controls take the offset-0
|
|
50
|
+
* `FOCUS_VISIBLE_RING` via `focusVisibleStyle` / `ensureFocusVisibleRing()`.
|
|
45
51
|
*/
|
|
46
52
|
export const keyboardFocusRingProps = {
|
|
47
|
-
...
|
|
53
|
+
...FOCUS_VISIBLE_RING_INSET,
|
|
48
54
|
} as const;
|
|
49
55
|
|
|
50
56
|
/**
|
|
@@ -85,7 +91,7 @@ export const compositeFocusRingCss = `/* LC-71: ring on the composite outer box;
|
|
|
85
91
|
}
|
|
86
92
|
.mp-chip-dismiss:focus-visible .mp-chip-dismiss-ring {
|
|
87
93
|
outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));
|
|
88
|
-
outline-offset:
|
|
94
|
+
outline-offset: 0;
|
|
89
95
|
}`;
|
|
90
96
|
|
|
91
97
|
const COMPOSITE_RING_STYLE_ID = "mp-composite-focus-ring";
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { getConfig } from "@tamagui/web";
|
|
29
29
|
import { useEffect } from "react";
|
|
30
|
+
import { fontCategoryMetrics, flooredLineHeight } from "./fontCategoryMetrics";
|
|
31
|
+
import { fontCategoryStacks } from "./fontCategoryStacks";
|
|
30
32
|
import type { FontCategory } from "./knobs";
|
|
31
33
|
import { defaultKnobs } from "./knobs";
|
|
32
34
|
import { usePresetContext } from "./PresetContext";
|
|
@@ -34,32 +36,12 @@ import { usePresetContext } from "./PresetContext";
|
|
|
34
36
|
const STYLE_TAG_ID = "mp-font-knob-styles";
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* `
|
|
40
|
-
*
|
|
41
|
-
* and connected-script families). "sans-serif" is the default scope (never
|
|
42
|
-
* overridden), listed for completeness.
|
|
39
|
+
* Re-exported so `@multiplatform.one/theme` consumers keep the historical
|
|
40
|
+
* import path. The table itself lives in `fontCategoryMetrics.ts` because
|
|
41
|
+
* `defaults/fonts.ts` bakes the same floors into the registered category
|
|
42
|
+
* fonts and the two must not drift (LC-11).
|
|
43
43
|
*/
|
|
44
|
-
export
|
|
45
|
-
FontCategory,
|
|
46
|
-
{ heading: number; body: number; letterSpacing: "inherit" | "neutral" }
|
|
47
|
-
> = {
|
|
48
|
-
"sans-serif": { heading: 1.15, body: 1.4, letterSpacing: "inherit" },
|
|
49
|
-
serif: { heading: 1.2, body: 1.4, letterSpacing: "inherit" },
|
|
50
|
-
mono: { heading: 1.25, body: 1.45, letterSpacing: "neutral" },
|
|
51
|
-
// Heading floors below are sized to each configured face's em box
|
|
52
|
-
// (ascent+descent) so display headings never clip (LC-11): Roboto Slab
|
|
53
|
-
// ≈1.32, Nunito ≈1.36, Silkscreen ≈1.3, Poppins/Futura ≈1.4.
|
|
54
|
-
slab: { heading: 1.35, body: 1.4, letterSpacing: "inherit" },
|
|
55
|
-
rounded: { heading: 1.4, body: 1.4, letterSpacing: "inherit" },
|
|
56
|
-
condensed: { heading: 1.15, body: 1.4, letterSpacing: "inherit" },
|
|
57
|
-
cursive: { heading: 1.3, body: 1.5, letterSpacing: "neutral" },
|
|
58
|
-
handwriting: { heading: 1.25, body: 1.45, letterSpacing: "neutral" },
|
|
59
|
-
pixel: { heading: 1.35, body: 1.4, letterSpacing: "neutral" },
|
|
60
|
-
blackletter: { heading: 1.3, body: 1.45, letterSpacing: "neutral" },
|
|
61
|
-
geometric: { heading: 1.45, body: 1.4, letterSpacing: "inherit" },
|
|
62
|
-
};
|
|
44
|
+
export { fontCategoryMetrics };
|
|
63
45
|
|
|
64
46
|
// Default leading for font-scoped text that carries no explicit lineHeight
|
|
65
47
|
// (e.g. `Text fontFamily="$body" fontSize=…` renders `line-height: normal`
|
|
@@ -90,7 +72,8 @@ export interface FontScopeTables {
|
|
|
90
72
|
/**
|
|
91
73
|
* Resolve the concrete font-family stack registered in the Tamagui config for
|
|
92
74
|
* a font category. Returns undefined when the category font is not registered
|
|
93
|
-
* (the caller then
|
|
75
|
+
* (the caller then uses `fontCategoryStacks` so the knob still writes
|
|
76
|
+
* `--f-family` — live SHC console had the style tag and skipped the family).
|
|
94
77
|
*/
|
|
95
78
|
export function getConfiguredFontFamily(category: FontCategory): string | undefined {
|
|
96
79
|
let config: ReturnType<typeof getConfig> | undefined;
|
|
@@ -164,9 +147,9 @@ function buildScopeRule(
|
|
|
164
147
|
for (const [key, size] of Object.entries(tables.size)) {
|
|
165
148
|
const baseLineHeight = tables.lineHeight[key];
|
|
166
149
|
if (typeof baseLineHeight !== "number") continue;
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
decls.push(`--f-lineHeight-${key}: ${
|
|
150
|
+
const floored = flooredLineHeight(size, baseLineHeight, minRatio);
|
|
151
|
+
if (floored > baseLineHeight) {
|
|
152
|
+
decls.push(`--f-lineHeight-${key}: ${floored}px !important`);
|
|
170
153
|
}
|
|
171
154
|
}
|
|
172
155
|
if (metrics.letterSpacing === "neutral" && tables.letterSpacing) {
|
|
@@ -202,13 +185,13 @@ export function buildFontKnobCss(
|
|
|
202
185
|
defaultLeadingRule("body", bodyFont),
|
|
203
186
|
];
|
|
204
187
|
if (headingFont !== "sans-serif") {
|
|
205
|
-
const family = resolveFamily(headingFont);
|
|
188
|
+
const family = resolveFamily(headingFont) ?? fontCategoryStacks[headingFont];
|
|
206
189
|
if (family) {
|
|
207
190
|
rules.push(buildScopeRule("heading", headingFont, family, resolveTables("heading")));
|
|
208
191
|
}
|
|
209
192
|
}
|
|
210
193
|
if (bodyFont !== "sans-serif") {
|
|
211
|
-
const family = resolveFamily(bodyFont);
|
|
194
|
+
const family = resolveFamily(bodyFont) ?? fontCategoryStacks[bodyFont];
|
|
212
195
|
if (family) {
|
|
213
196
|
rules.push(buildScopeRule("body", bodyFont, family, resolveTables("body")));
|
|
214
197
|
}
|
package/src/theme/Tint.tsx
CHANGED
|
@@ -13,7 +13,8 @@ export interface TintProps extends PropsWithChildren {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Depth-based tint component. Each nesting level increments the depth
|
|
16
|
-
* and selects a tint from the preset's tints array via
|
|
16
|
+
* and selects a tint from the preset's tints array via
|
|
17
|
+
* `tints[(depth - 1) % length]` so the first Tint is `tints[0]`.
|
|
17
18
|
*
|
|
18
19
|
* Applies a tint sub-theme based on nesting depth.
|
|
19
20
|
*/
|
|
@@ -21,7 +22,7 @@ export function Tint({ children, alt = 0, disable, ...props }: TintProps) {
|
|
|
21
22
|
const parentDepth = useContext(TintDepthContext);
|
|
22
23
|
const depth = parentDepth + 1 + alt;
|
|
23
24
|
const tints = usePresetTints();
|
|
24
|
-
const tint = tints.length > 0 ? tints[depth % tints.length] : undefined;
|
|
25
|
+
const tint = tints.length > 0 ? tints[(depth - 1) % tints.length] : undefined;
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
28
|
<TintDepthContext.Provider value={depth}>
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { createAnimations } from "@tamagui/animations-css";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The CSS driver's named durations.
|
|
5
|
+
*
|
|
6
|
+
* `bouncy`, `lazy`, `slow`, `medium` and `quick` are Tamagui's own names and
|
|
7
|
+
* carry Tamagui's own values — a shared name that means something different
|
|
8
|
+
* here is worse than no name, because every consumer reading `animation="medium"`
|
|
9
|
+
* against the upstream docs gets a different answer than the one it renders.
|
|
10
|
+
* MPO-19 X10: `medium` was `ease-in-out 250ms` against stock `ease-in 300ms`,
|
|
11
|
+
* with no improvement argument written down anywhere.
|
|
12
|
+
*
|
|
13
|
+
* `tooltip`, `snappy` and `gentle` are additive — names Tamagui does not use,
|
|
14
|
+
* so they are ours to set and are not a contradiction.
|
|
15
|
+
*/
|
|
3
16
|
export const animationConfig = {
|
|
4
17
|
bouncy: "ease-in 200ms",
|
|
5
18
|
lazy: "ease-in 600ms",
|
|
6
19
|
slow: "ease-in 500ms",
|
|
7
|
-
medium: "ease-in
|
|
20
|
+
medium: "ease-in 300ms",
|
|
8
21
|
quick: "ease-in 100ms",
|
|
9
22
|
tooltip: "ease-in 400ms",
|
|
10
23
|
snappy: "ease-out 80ms",
|