@multiplatform.one/theme 7.34.3 → 7.35.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/package.json +20 -5
- package/src/audit/constraintAudit.spec.ts +274 -87
- package/src/audit/constraintAudit.ts +135 -120
- package/src/audit/constraintScope.spec.ts +1 -1
- package/src/audit/designTokens.ts +42 -0
- package/src/audit/themeMatrix.spec.ts +83 -2
- package/src/audit/themeMatrix.ts +33 -1
- package/src/figma/figmaTokens.spec.ts +26 -34
- package/src/figma/figmaTokens.ts +26 -50
- package/src/fonts/createFontLoader.ts +4 -1
- package/src/menuRow.ts +4 -1
- package/src/theme/FontKnobStyles.tsx +2 -1
- package/src/theme/Preset.stories.tsx +0 -1
- package/src/theme/Preset.tsx +6 -1
- package/src/theme/PresetContext.ts +4 -0
- package/src/theme/Surface.spec.tsx +114 -67
- package/src/theme/Surface.stories.tsx +8 -25
- package/src/theme/Surface.tsx +87 -43
- package/src/theme/accentFloor.spec.ts +37 -11
- package/src/theme/activateThemeConfig.ts +22 -6
- package/src/theme/animations/animations.spec.ts +62 -0
- package/src/theme/animations/css.ts +9 -35
- package/src/theme/animations/reactNative.ts +98 -25
- package/src/theme/boundaryFloor.spec.ts +57 -0
- package/src/theme/chartPalette.spec.ts +56 -27
- package/src/theme/chartPalette.ts +33 -28
- package/src/theme/colorRules.spec.ts +32 -72
- package/src/theme/cookies.spec.ts +49 -18
- package/src/theme/cookies.ts +36 -7
- package/src/theme/cookiesPersistence.spec.ts +5 -5
- package/src/theme/createDefaultThemeConfig.spec.ts +182 -20
- package/src/theme/createDefaultThemeConfig.ts +34 -28
- package/src/theme/createThemes.ts +169 -218
- package/src/theme/defaults/accent.ts +3 -35
- package/src/theme/defaults/base.ts +14 -53
- package/src/theme/defaults/builderOptions.ts +68 -85
- package/src/theme/defaults/categoryFonts.ts +10 -0
- package/src/theme/defaults/fonts.spec.ts +84 -4
- package/src/theme/defaults/fonts.ts +166 -124
- package/src/theme/defaults/house.ts +48 -0
- package/src/theme/defaults/index.ts +1 -0
- package/src/theme/defaults/neutralRamp.spec.ts +52 -47
- package/src/theme/devtools/ColorLineVisualizer.tsx +6 -6
- package/src/theme/devtools/ThemeDevtoolsPanel.setMarkers.spec.tsx +13 -6
- package/src/theme/devtools/ThemeDevtoolsPanel.tsx +14 -77
- package/src/theme/devtools/animationOptions.spec.ts +23 -37
- package/src/theme/devtools/animationOptions.ts +4 -6
- package/src/theme/devtools/buildSnapshot.ts +0 -3
- package/src/theme/devtools/knobIcons.tsx +4 -24
- package/src/theme/focusState.spec.ts +9 -30
- package/src/theme/index.ts +17 -0
- package/src/theme/intentFill.spec.ts +42 -0
- package/src/theme/knobs.ts +14 -42
- package/src/theme/layoutTokens.ts +15 -1
- package/src/theme/layoutTokensHooks.spec.tsx +8 -4
- package/src/theme/mergedTokens.ts +20 -0
- package/src/theme/motion.spec.ts +84 -0
- package/src/theme/motion.ts +53 -0
- package/src/theme/motionStops.ts +17 -0
- package/src/theme/motionTiming.ts +59 -0
- package/src/theme/mpo13Proof.spec.ts +43 -46
- package/src/theme/mpo19Proof.spec.ts +13 -14
- package/src/theme/namedInkFloor.spec.ts +60 -0
- package/src/theme/overlaySurfaces.tsx +330 -0
- package/src/theme/preset.types.ts +16 -0
- package/src/theme/presetPreview.ts +32 -0
- package/src/theme/presetRoot.spec.tsx +89 -0
- package/src/theme/presetStore.persistence.spec.ts +141 -0
- package/src/theme/presetStore.spec.ts +205 -0
- package/src/theme/presetStore.ts +286 -0
- package/src/theme/presetUserSync.spec.tsx +168 -0
- package/src/theme/presetUserSync.ts +47 -0
- package/src/theme/presets.spec.ts +22 -15
- package/src/theme/presets.ts +22 -10
- package/src/theme/radiusClass.spec.ts +60 -41
- package/src/theme/radiusClass.ts +17 -4
- package/src/theme/radiusClassTable.generated.ts +3 -3
- package/src/theme/readableColor.spec.ts +59 -152
- package/src/theme/readableColor.ts +34 -174
- package/src/theme/recipeInputs.ts +153 -295
- package/src/theme/recipes.ts +58 -18
- package/src/theme/resolveKnobs.spec.ts +528 -588
- package/src/theme/resolveKnobs.ts +250 -325
- package/src/theme/scale/ScaleStyles.native.tsx +19 -0
- package/src/theme/scale/ScaleStyles.tsx +48 -0
- package/src/theme/scale/activeScale.ts +30 -0
- package/src/theme/scale/deriveRecipeInputs.ts +110 -0
- package/src/theme/scale/generateScale.spec.ts +260 -0
- package/src/theme/scale/generateScale.ts +147 -0
- package/src/theme/scale/index.ts +54 -0
- package/src/theme/scale/installScaleConfig.native.spec.ts +77 -0
- package/src/theme/scale/installScaleConfig.native.ts +57 -0
- package/src/theme/scale/installScaleConfig.ts +7 -0
- package/src/theme/scale/scaleAttribute.ts +21 -0
- package/src/theme/scale/scaleCss.probe.spec.tsx +64 -0
- package/src/theme/scale/scaleCss.spec.ts +132 -0
- package/src/theme/scale/scaleCss.ts +95 -0
- package/src/theme/scale/scaleFonts.ts +106 -0
- package/src/theme/scale/scaleInputs.ts +322 -0
- package/src/theme/scale/themeScales.ts +181 -0
- package/src/theme/scale/useActiveScale.spec.tsx +129 -0
- package/src/theme/scale/useActiveScale.ts +95 -0
- package/src/theme/schemeStore.spec.ts +81 -0
- package/src/theme/schemeStore.ts +67 -0
- package/src/theme/shared.spec.ts +7 -6
- package/src/theme/shared.tsx +37 -3
- package/src/theme/sizeLadder.spec.ts +37 -36
- package/src/theme/sizeRecipes.spec.ts +179 -85
- package/src/theme/sizeRecipes.ts +48 -25
- package/src/theme/subsetThemes.spec.ts +9 -3
- package/src/theme/switchThumb.spec.ts +69 -0
- package/src/theme/syntaxFloor.spec.ts +11 -8
- package/src/theme/theme.hydration.native.spec.tsx +51 -0
- package/src/theme/theme.native.tsx +59 -21
- package/src/theme/theme.palette.spec.tsx +76 -0
- package/src/theme/theme.preset.native.spec.tsx +73 -0
- package/src/theme/theme.provider.spec.ts +143 -1
- package/src/theme/theme.tsx +61 -25
- package/src/theme/tileSizes.ts +6 -7
- package/src/theme/transitionProps.native.ts +25 -2
- package/src/theme/transitionProps.spec.ts +34 -0
- package/src/theme/transitionProps.ts +26 -2
- package/src/theme/usePresetSwitch.native.spec.tsx +68 -0
- package/src/theme/usePresetSwitch.native.ts +32 -0
- package/src/theme/usePresetSwitch.spec.tsx +103 -0
- package/src/theme/usePresetSwitch.ts +54 -0
- package/src/theme/useResolvedKnobs.hydration.spec.tsx +2 -2
- package/src/theme/useResolvedKnobs.ts +23 -90
- package/src/theme/useResolvedKnobsBehavior.spec.tsx +25 -30
- package/src/theme/useSchemePreference.native.ts +33 -0
- package/src/theme/useSchemePreference.spec.tsx +51 -0
- package/src/theme/useSchemePreference.ts +32 -0
- package/src/theme/useSchemePreference.web.spec.tsx +32 -0
- package/src/theme/useTheme.native.spec.tsx +68 -0
- package/src/theme/useTheme.native.ts +49 -24
- package/src/theme/useTheme.ts +7 -4
- package/types/audit/constraintAudit.d.ts +6 -5
- package/types/audit/constraintAudit.d.ts.map +1 -1
- package/types/audit/designTokens.d.ts +13 -0
- package/types/audit/designTokens.d.ts.map +1 -0
- package/types/audit/themeMatrix.d.ts +10 -0
- package/types/audit/themeMatrix.d.ts.map +1 -1
- package/types/figma/figmaTokens.d.ts +11 -28
- package/types/figma/figmaTokens.d.ts.map +1 -1
- package/types/fonts/createFontLoader.d.ts.map +1 -1
- package/types/menuRow.d.ts +4 -1
- package/types/menuRow.d.ts.map +1 -1
- package/types/theme/FontKnobStyles.d.ts.map +1 -1
- package/types/theme/Preset.d.ts.map +1 -1
- package/types/theme/PresetContext.d.ts +4 -0
- package/types/theme/PresetContext.d.ts.map +1 -1
- package/types/theme/Surface.d.ts +57 -26
- package/types/theme/Surface.d.ts.map +1 -1
- package/types/theme/activateThemeConfig.d.ts +5 -3
- package/types/theme/activateThemeConfig.d.ts.map +1 -1
- package/types/theme/animations/css.d.ts +27 -34
- package/types/theme/animations/css.d.ts.map +1 -1
- package/types/theme/animations/reactNative.d.ts +196 -45
- package/types/theme/animations/reactNative.d.ts.map +1 -1
- package/types/theme/chartPalette.d.ts +11 -3
- package/types/theme/chartPalette.d.ts.map +1 -1
- package/types/theme/colorRules.d.ts +1 -1
- package/types/theme/cookies.d.ts +12 -1
- package/types/theme/cookies.d.ts.map +1 -1
- package/types/theme/createDefaultThemeConfig.d.ts +13 -13
- package/types/theme/createDefaultThemeConfig.d.ts.map +1 -1
- package/types/theme/createThemes.d.ts +58 -2
- package/types/theme/createThemes.d.ts.map +1 -1
- package/types/theme/defaults/accent.d.ts.map +1 -1
- package/types/theme/defaults/base.d.ts.map +1 -1
- package/types/theme/defaults/builderOptions.d.ts.map +1 -1
- package/types/theme/defaults/categoryFonts.d.ts +10 -0
- package/types/theme/defaults/categoryFonts.d.ts.map +1 -1
- package/types/theme/defaults/fonts.d.ts +330 -30
- package/types/theme/defaults/fonts.d.ts.map +1 -1
- package/types/theme/defaults/house.d.ts +8 -0
- package/types/theme/defaults/house.d.ts.map +1 -0
- 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 +3 -3
- package/types/theme/devtools/ThemeDevtoolsPanel.d.ts.map +1 -1
- package/types/theme/devtools/animationOptions.d.ts.map +1 -1
- package/types/theme/devtools/buildSnapshot.d.ts.map +1 -1
- package/types/theme/devtools/knobIcons.d.ts +0 -3
- package/types/theme/devtools/knobIcons.d.ts.map +1 -1
- package/types/theme/index.d.ts +11 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/knobs.d.ts +8 -36
- package/types/theme/knobs.d.ts.map +1 -1
- package/types/theme/layoutTokens.d.ts +13 -1
- package/types/theme/layoutTokens.d.ts.map +1 -1
- package/types/theme/mergedTokens.d.ts +11 -0
- package/types/theme/mergedTokens.d.ts.map +1 -0
- package/types/theme/motion.d.ts +17 -0
- package/types/theme/motion.d.ts.map +1 -0
- package/types/theme/motionStops.d.ts +3 -0
- package/types/theme/motionStops.d.ts.map +1 -0
- package/types/theme/motionTiming.d.ts +36 -0
- package/types/theme/motionTiming.d.ts.map +1 -0
- package/types/theme/overlaySurfaces.d.ts +70 -0
- package/types/theme/overlaySurfaces.d.ts.map +1 -0
- package/types/theme/preset.types.d.ts +16 -0
- package/types/theme/preset.types.d.ts.map +1 -1
- package/types/theme/presetPreview.d.ts +14 -0
- package/types/theme/presetPreview.d.ts.map +1 -0
- package/types/theme/presetStore.d.ts +40 -0
- package/types/theme/presetStore.d.ts.map +1 -0
- package/types/theme/presetUserSync.d.ts +7 -0
- package/types/theme/presetUserSync.d.ts.map +1 -0
- package/types/theme/presets.d.ts +12 -4
- package/types/theme/presets.d.ts.map +1 -1
- package/types/theme/radiusClass.d.ts +5 -2
- package/types/theme/radiusClass.d.ts.map +1 -1
- package/types/theme/radiusClassTable.generated.d.ts +3 -3
- package/types/theme/readableColor.d.ts +11 -49
- package/types/theme/readableColor.d.ts.map +1 -1
- package/types/theme/recipeInputs.d.ts +39 -70
- package/types/theme/recipeInputs.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +79 -18
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +64 -32
- package/types/theme/resolveKnobs.d.ts.map +1 -1
- package/types/theme/scale/ScaleStyles.d.ts +18 -0
- package/types/theme/scale/ScaleStyles.d.ts.map +1 -0
- package/types/theme/scale/ScaleStyles.native.d.ts +10 -0
- package/types/theme/scale/ScaleStyles.native.d.ts.map +1 -0
- package/types/theme/scale/activeScale.d.ts +13 -0
- package/types/theme/scale/activeScale.d.ts.map +1 -0
- package/types/theme/scale/deriveRecipeInputs.d.ts +10 -0
- package/types/theme/scale/deriveRecipeInputs.d.ts.map +1 -0
- package/types/theme/scale/generateScale.d.ts +38 -0
- package/types/theme/scale/generateScale.d.ts.map +1 -0
- package/types/theme/scale/index.d.ts +17 -0
- package/types/theme/scale/index.d.ts.map +1 -0
- package/types/theme/scale/installScaleConfig.d.ts +4 -0
- package/types/theme/scale/installScaleConfig.d.ts.map +1 -0
- package/types/theme/scale/installScaleConfig.native.d.ts +13 -0
- package/types/theme/scale/installScaleConfig.native.d.ts.map +1 -0
- package/types/theme/scale/scaleAttribute.d.ts +14 -0
- package/types/theme/scale/scaleAttribute.d.ts.map +1 -0
- package/types/theme/scale/scaleCss.d.ts +25 -0
- package/types/theme/scale/scaleCss.d.ts.map +1 -0
- package/types/theme/scale/scaleFonts.d.ts +16 -0
- package/types/theme/scale/scaleFonts.d.ts.map +1 -0
- package/types/theme/scale/scaleInputs.d.ts +66 -0
- package/types/theme/scale/scaleInputs.d.ts.map +1 -0
- package/types/theme/scale/themeScales.d.ts +52 -0
- package/types/theme/scale/themeScales.d.ts.map +1 -0
- package/types/theme/scale/useActiveScale.d.ts +31 -0
- package/types/theme/scale/useActiveScale.d.ts.map +1 -0
- package/types/theme/schemeStore.d.ts +6 -0
- package/types/theme/schemeStore.d.ts.map +1 -0
- package/types/theme/shared.d.ts +18 -0
- package/types/theme/shared.d.ts.map +1 -1
- package/types/theme/sizeRecipes.d.ts +20 -15
- package/types/theme/sizeRecipes.d.ts.map +1 -1
- package/types/theme/theme.d.ts +2 -1
- package/types/theme/theme.d.ts.map +1 -1
- package/types/theme/theme.native.d.ts +10 -1
- package/types/theme/theme.native.d.ts.map +1 -1
- package/types/theme/tileSizes.d.ts +6 -7
- package/types/theme/tileSizes.d.ts.map +1 -1
- package/types/theme/transitionProps.d.ts +3 -1
- package/types/theme/transitionProps.d.ts.map +1 -1
- package/types/theme/transitionProps.native.d.ts +3 -1
- package/types/theme/transitionProps.native.d.ts.map +1 -1
- package/types/theme/usePresetSwitch.d.ts +10 -0
- package/types/theme/usePresetSwitch.d.ts.map +1 -0
- package/types/theme/usePresetSwitch.native.d.ts +10 -0
- package/types/theme/usePresetSwitch.native.d.ts.map +1 -0
- package/types/theme/useResolvedKnobs.d.ts +13 -13
- package/types/theme/useResolvedKnobs.d.ts.map +1 -1
- package/types/theme/useSchemePreference.d.ts +8 -0
- package/types/theme/useSchemePreference.d.ts.map +1 -0
- package/types/theme/useSchemePreference.native.d.ts +8 -0
- package/types/theme/useSchemePreference.native.d.ts.map +1 -0
- package/types/theme/useTheme.d.ts +4 -2
- package/types/theme/useTheme.d.ts.map +1 -1
- package/types/theme/useTheme.native.d.ts +10 -1
- package/types/theme/useTheme.native.d.ts.map +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Colors from "@tamagui/colors";
|
|
2
|
-
import {
|
|
2
|
+
import { generateScale } from "../theme/scale/generateScale";
|
|
3
|
+
import { defaultScaleInputs } from "../theme/scale/scaleInputs";
|
|
3
4
|
import { describe, expect, it } from "vitest";
|
|
4
5
|
import { normalizeToHex } from "../theme/colorRules";
|
|
5
6
|
import { defaultAccentTheme } from "../theme/defaults/accent";
|
|
@@ -57,8 +58,12 @@ describe("buildFigmaTokens", () => {
|
|
|
57
58
|
expect(sameColor(built[i], source[i])).toBe(true);
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
|
-
expect(
|
|
61
|
-
|
|
61
|
+
expect(
|
|
62
|
+
sameColor(defaultAccentTheme.lightPalette[0], result.palette.themes.accent.light[0]),
|
|
63
|
+
).toBe(true);
|
|
64
|
+
expect(
|
|
65
|
+
sameColor(defaultAccentTheme.darkPalette[0], result.palette.themes.accent.dark[0]),
|
|
66
|
+
).toBe(true);
|
|
62
67
|
});
|
|
63
68
|
|
|
64
69
|
it("derives intent ramps from @tamagui/colors (error=red, success=green, warning=yellow)", () => {
|
|
@@ -96,7 +101,7 @@ describe("buildFigmaTokens", () => {
|
|
|
96
101
|
// borderColor back off color5, the background states no longer forced.
|
|
97
102
|
expect(result.semantic.borderColor?.alias).toBe("color4");
|
|
98
103
|
expect(result.semantic.textMuted?.alias).toBe("color11");
|
|
99
|
-
expect(result.semantic.placeholderColor?.alias).toBe("
|
|
104
|
+
expect(result.semantic.placeholderColor?.alias).toBe("color9");
|
|
100
105
|
expect(result.semantic.surfaceMuted?.alias).toBe("color10");
|
|
101
106
|
expect(result.semantic.borderStrong?.alias).toBe("color7");
|
|
102
107
|
});
|
|
@@ -135,17 +140,12 @@ describe("buildFigmaTokens", () => {
|
|
|
135
140
|
});
|
|
136
141
|
|
|
137
142
|
describe("sizing", () => {
|
|
138
|
-
it("mirrors the
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const size = defaultConfig.tokens.size as Record<string, number>;
|
|
143
|
+
it("mirrors the generated default tokens with figma-safe names", () => {
|
|
144
|
+
const tokens = generateScale(defaultScaleInputs).tokens;
|
|
145
|
+
const size = tokens.size as Record<string, number>;
|
|
142
146
|
expect(result.sizing["size-true"]).toBe(size.$true);
|
|
143
|
-
expect(result.sizing["radius-4"]).toBe(
|
|
144
|
-
|
|
145
|
-
);
|
|
146
|
-
expect(result.sizing["space-1-5"]).toBe(
|
|
147
|
-
(defaultConfig.tokens.space as Record<string, number>)["$1.5"],
|
|
148
|
-
);
|
|
147
|
+
expect(result.sizing["radius-4"]).toBe((tokens.radius as Record<string, number>)["4"]);
|
|
148
|
+
expect(result.sizing["space-1-5"]).toBe((tokens.space as Record<string, number>)["$1.5"]);
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
it("exports knob-shaped borderWidth values including the 0.5 hairline", () => {
|
|
@@ -188,31 +188,23 @@ describe("buildFigmaTokens", () => {
|
|
|
188
188
|
expect(modes.large.sizeToken).toBe("$4");
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
-
it("exports fontWeight
|
|
191
|
+
it("exports fontWeight and cornerSmoothing modes", () => {
|
|
192
192
|
expect(result.knobs.fontWeight.modes).toEqual({ regular: "400", bold: "700" });
|
|
193
|
-
expect(result.knobs.space.modes.medium.paddingFigmaName).toBe("space-4");
|
|
194
|
-
expect(result.knobs.space.modes.medium.gapFigmaName).toBe("space-4");
|
|
195
|
-
expect(result.knobs.space.modes.medium.gapLgFigmaName).toBe("space-5");
|
|
196
|
-
expect(result.knobs.size.modes).toEqual({
|
|
197
|
-
small: { token: "$3", figmaName: "size-3" },
|
|
198
|
-
medium: { token: "$4", figmaName: "size-4" },
|
|
199
|
-
large: { token: "$5", figmaName: "size-5" },
|
|
200
|
-
});
|
|
201
193
|
expect(result.knobs.cornerSmoothing.modes).toEqual({ round: 0, smooth: 0.6 });
|
|
202
194
|
});
|
|
203
195
|
|
|
204
|
-
it("exports
|
|
205
|
-
expect(result.knobs.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
expect(result.knobs.density.compact.space).toEqual({
|
|
212
|
-
small: "small",
|
|
213
|
-
medium: "small",
|
|
214
|
-
large: "medium",
|
|
196
|
+
it("exports the spacing roles and the default size token, not size/space/density modes", () => {
|
|
197
|
+
expect(result.knobs.spacing).toEqual({
|
|
198
|
+
gapSm: { token: "$2", figmaName: "space-2" },
|
|
199
|
+
gap: { token: "$3", figmaName: "space-3" },
|
|
200
|
+
gapLg: { token: "$5", figmaName: "space-5" },
|
|
201
|
+
panelPadding: { token: "$4", figmaName: "space-4" },
|
|
202
|
+
featurePadding: { token: "$6", figmaName: "space-6" },
|
|
215
203
|
});
|
|
204
|
+
expect(result.knobs.sizeToken).toEqual({ token: "$true", figmaName: "size-true" });
|
|
205
|
+
expect(result.knobs).not.toHaveProperty("space");
|
|
206
|
+
expect(result.knobs).not.toHaveProperty("size");
|
|
207
|
+
expect(result.knobs).not.toHaveProperty("density");
|
|
216
208
|
});
|
|
217
209
|
});
|
|
218
210
|
|
package/src/figma/figmaTokens.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* the built base themes (a key only becomes a `colorN` alias when light
|
|
14
14
|
* AND dark agree on the step index; otherwise raw per-scheme values are
|
|
15
15
|
* exported).
|
|
16
|
-
* - Sizing:
|
|
17
|
-
* `createDefaultThemeConfig` installs
|
|
16
|
+
* - Sizing: the default generated scale (`generateScale`), the tokens
|
|
17
|
+
* `createDefaultThemeConfig` installs.
|
|
18
18
|
* - Knob outputs: `resolveKnobs()` is executed per knob mode — the export
|
|
19
19
|
* shows exactly what the runtime resolver produces.
|
|
20
20
|
* - Typography: the built `defaultHeadingFont` / `defaultBodyFont` tables
|
|
@@ -25,14 +25,18 @@
|
|
|
25
25
|
* stamps `generatedAt` when writing to disk.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import { createTokens } from "@tamagui/web";
|
|
29
29
|
import { createThemesBuilder, tintHueNames } from "../theme/createThemes";
|
|
30
30
|
import { defaultAccentTheme } from "../theme/defaults/accent";
|
|
31
31
|
import { defaultBaseTheme } from "../theme/defaults/base";
|
|
32
32
|
import { defaultBuilderOptions } from "../theme/defaults/builderOptions";
|
|
33
33
|
import { defaultBodyFont, defaultHeadingFont } from "../theme/defaults/fonts";
|
|
34
34
|
import { type Knobs, defaultKnobs } from "../theme/knobs";
|
|
35
|
-
import {
|
|
35
|
+
import { resolveKnobs, spacingRoles } from "../theme/resolveKnobs";
|
|
36
|
+
import { generateScale } from "../theme/scale/generateScale";
|
|
37
|
+
import { defaultScaleInputs } from "../theme/scale/scaleInputs";
|
|
38
|
+
|
|
39
|
+
const tokens = createTokens(generateScale(defaultScaleInputs).tokens);
|
|
36
40
|
|
|
37
41
|
// ── Names / constants ─────────────────────────────────────────
|
|
38
42
|
|
|
@@ -105,13 +109,10 @@ export interface FigmaElevationMode {
|
|
|
105
109
|
px: number | null;
|
|
106
110
|
}
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
gapFigmaName: string;
|
|
113
|
-
gapLgToken: string;
|
|
114
|
-
gapLgFigmaName: string;
|
|
112
|
+
/** One spacing role: a fixed `$space` key whose px the scale supplies. */
|
|
113
|
+
export interface FigmaSpacingRole {
|
|
114
|
+
token: string;
|
|
115
|
+
figmaName: string;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export interface FigmaKnobsExport {
|
|
@@ -119,14 +120,11 @@ export interface FigmaKnobsExport {
|
|
|
119
120
|
borderWidth: { default: Knobs["borderWidth"]; modes: Record<string, number> };
|
|
120
121
|
elevation: { default: Knobs["elevation"]; modes: Record<string, FigmaElevationMode> };
|
|
121
122
|
fontWeight: { default: Knobs["fontWeight"]; modes: Record<string, string> };
|
|
122
|
-
space: { default: Knobs["space"]; modes: Record<string, FigmaSpaceMode> };
|
|
123
|
-
size: { default: Knobs["size"]; modes: Record<string, { token: string; figmaName: string }> };
|
|
124
123
|
cornerSmoothing: { default: string; modes: Record<string, number> };
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
};
|
|
124
|
+
/** SP-GAP roles: fixed `$space` keys, not knob modes. */
|
|
125
|
+
spacing: Record<keyof typeof spacingRoles, FigmaSpacingRole>;
|
|
126
|
+
/** The control size token at the default (`$true`); a use site picks another with `size`. */
|
|
127
|
+
sizeToken: FigmaSpacingRole;
|
|
130
128
|
}
|
|
131
129
|
|
|
132
130
|
export interface FigmaFontExport {
|
|
@@ -288,7 +286,7 @@ function buildSizing(borderWidthModes: Record<string, number>): Record<string, n
|
|
|
288
286
|
];
|
|
289
287
|
for (const [prefix, group] of groups) {
|
|
290
288
|
if (prefix !== "zIndex" && Object.keys(group).length === 0) {
|
|
291
|
-
throw new Error(`figmaTokens:
|
|
289
|
+
throw new Error(`figmaTokens: generated tokens.${prefix} is empty`);
|
|
292
290
|
}
|
|
293
291
|
for (const [key, val] of Object.entries(group)) {
|
|
294
292
|
sizing[figmaTokenName(prefix, key)] = val;
|
|
@@ -306,8 +304,6 @@ const RADIUS_KNOB_MODES: Knobs["borderRadius"][] = ["none", "small", "medium", "
|
|
|
306
304
|
const BORDER_WIDTH_KNOB_MODES: Knobs["borderWidth"][] = ["none", "small", "medium", "large"];
|
|
307
305
|
const ELEVATION_KNOB_MODES: Knobs["elevation"][] = ["none", "small", "medium", "large"];
|
|
308
306
|
const FONT_WEIGHT_KNOB_MODES: Knobs["fontWeight"][] = ["regular", "bold"];
|
|
309
|
-
const SPACE_KNOB_MODES: Knobs["space"][] = ["small", "medium", "large"];
|
|
310
|
-
const SIZE_KNOB_MODES: Knobs["size"][] = ["small", "medium", "large"];
|
|
311
307
|
|
|
312
308
|
function radiusPx(token: string): number {
|
|
313
309
|
const radius = unwrapTokenGroup(tokens.radius);
|
|
@@ -373,47 +369,27 @@ function buildKnobs(): FigmaKnobsExport {
|
|
|
373
369
|
fontWeight[mode] = String(knobProps.textWeight.fontWeight);
|
|
374
370
|
}
|
|
375
371
|
|
|
376
|
-
const
|
|
377
|
-
for (const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
space[mode] = {
|
|
383
|
-
paddingToken,
|
|
384
|
-
paddingFigmaName: tokenToFigma(paddingToken, "space"),
|
|
385
|
-
gapToken,
|
|
386
|
-
gapFigmaName: tokenToFigma(gapToken, "space"),
|
|
387
|
-
gapLgToken,
|
|
388
|
-
gapLgFigmaName: tokenToFigma(gapLgToken, "space"),
|
|
389
|
-
};
|
|
372
|
+
const spacing = {} as Record<keyof typeof spacingRoles, FigmaSpacingRole>;
|
|
373
|
+
for (const [role, token] of Object.entries(spacingRoles) as [
|
|
374
|
+
keyof typeof spacingRoles,
|
|
375
|
+
string,
|
|
376
|
+
][]) {
|
|
377
|
+
spacing[role] = { token, figmaName: tokenToFigma(token, "space") };
|
|
390
378
|
}
|
|
391
379
|
|
|
392
|
-
const
|
|
393
|
-
for (const mode of SIZE_KNOB_MODES) {
|
|
394
|
-
const { knobProps } = resolveKnobs({ ...defaultKnobs, size: mode });
|
|
395
|
-
const token = String(knobProps.sizeToken);
|
|
396
|
-
size[mode] = { token, figmaName: tokenToFigma(token, "size") };
|
|
397
|
-
}
|
|
380
|
+
const sizeToken = String(resolveKnobs(defaultKnobs).knobProps.sizeToken);
|
|
398
381
|
|
|
399
382
|
return {
|
|
400
383
|
borderRadius: { default: defaultKnobs.borderRadius, modes: borderRadius },
|
|
401
384
|
borderWidth: { default: defaultKnobs.borderWidth, modes: borderWidth },
|
|
402
385
|
elevation: { default: defaultKnobs.elevation, modes: elevation },
|
|
403
386
|
fontWeight: { default: defaultKnobs.fontWeight, modes: fontWeight },
|
|
404
|
-
space: { default: defaultKnobs.space, modes: space },
|
|
405
|
-
size: { default: defaultKnobs.size, modes: size },
|
|
406
387
|
cornerSmoothing: {
|
|
407
388
|
default: defaultKnobs.cornerSmoothing ?? "round",
|
|
408
389
|
modes: { ...FIGMA_CORNER_SMOOTHING },
|
|
409
390
|
},
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
compact: {
|
|
413
|
-
size: { small: "small", medium: "medium", large: "large" },
|
|
414
|
-
space: { ...compactSpaceMap },
|
|
415
|
-
},
|
|
416
|
-
},
|
|
391
|
+
spacing,
|
|
392
|
+
sizeToken: { token: sizeToken, figmaName: tokenToFigma(sizeToken, "size") },
|
|
417
393
|
};
|
|
418
394
|
}
|
|
419
395
|
|
|
@@ -3,7 +3,10 @@ import type { FontLoader, FontLoaderConfig } from "./types";
|
|
|
3
3
|
export function createFontLoader(config: FontLoaderConfig): FontLoader {
|
|
4
4
|
const fontMap: Record<string, number> = {};
|
|
5
5
|
if (config.inter) {
|
|
6
|
-
fontMap.Inter = require("@tamagui/font-inter/otf/Inter-
|
|
6
|
+
fontMap.Inter = require("@tamagui/font-inter/otf/Inter-Regular.otf");
|
|
7
|
+
fontMap.InterMedium = require("@tamagui/font-inter/otf/Inter-Medium.otf");
|
|
8
|
+
fontMap.InterSemiBold = require("@tamagui/font-inter/otf/Inter-SemiBold.otf");
|
|
9
|
+
fontMap.InterExtraBold = require("@tamagui/font-inter/otf/Inter-ExtraBold.otf");
|
|
7
10
|
fontMap.InterBold = require("@tamagui/font-inter/otf/Inter-Bold.otf");
|
|
8
11
|
}
|
|
9
12
|
for (const font of config.fonts) {
|
package/src/menuRow.ts
CHANGED
|
@@ -18,7 +18,10 @@
|
|
|
18
18
|
* - color ramps: menus highlight with `componentColors.interactive.*`,
|
|
19
19
|
* form fields with `formInputColors.background.*` (package-boundary rule);
|
|
20
20
|
* - cursor: `pointer` for menu items, `default` for listbox options;
|
|
21
|
-
* - vertical sizing:
|
|
21
|
+
* - vertical sizing: spread `knobProps.menuRow` (the `menuRow` recipe
|
|
22
|
+
* family — one size key below the control token, 36 at default, 44 on
|
|
23
|
+
* touch, padX `$3`); Select reads `knobProps.menuRow.minHeight` as its row
|
|
24
|
+
* pitch. MentionInput keeps its own suggestion pitch;
|
|
22
25
|
* - in-row gap and the state-variant model (selected/active/disabled).
|
|
23
26
|
*/
|
|
24
27
|
export const menuRowFrame = {
|
|
@@ -209,6 +209,7 @@ export function FontKnobStyles() {
|
|
|
209
209
|
const knobs = presetCtx ? { ...presetCtx.preset.knobs, ...presetCtx.overrides } : defaultKnobs;
|
|
210
210
|
const headingFont = knobs.headingFont ?? defaultKnobs.headingFont;
|
|
211
211
|
const bodyFont = knobs.bodyFont ?? defaultKnobs.bodyFont;
|
|
212
|
+
const scaleId = presetCtx?.scaleId;
|
|
212
213
|
|
|
213
214
|
useEffect(() => {
|
|
214
215
|
if (typeof document === "undefined") return;
|
|
@@ -224,7 +225,7 @@ export function FontKnobStyles() {
|
|
|
224
225
|
document.head.appendChild(tag);
|
|
225
226
|
}
|
|
226
227
|
if (tag.textContent !== css) tag.textContent = css;
|
|
227
|
-
}, [headingFont, bodyFont]);
|
|
228
|
+
}, [headingFont, bodyFont, scaleId]);
|
|
228
229
|
|
|
229
230
|
useEffect(
|
|
230
231
|
() => () => {
|
|
@@ -22,7 +22,6 @@ function Probe({ label }: { label: string }) {
|
|
|
22
22
|
"data-border-radius": String(knobProps.borderRadius.borderRadius),
|
|
23
23
|
"data-border-width": String(knobProps.surface.borderWidth),
|
|
24
24
|
"data-fill-style": knobProps.outlined ? "outlined" : "filled",
|
|
25
|
-
"data-space": String(knobProps.space),
|
|
26
25
|
} as Record<string, unknown>;
|
|
27
26
|
return (
|
|
28
27
|
<YStack
|
package/src/theme/Preset.tsx
CHANGED
|
@@ -51,6 +51,8 @@ export function Preset({
|
|
|
51
51
|
knobs: { ...base.knobs, ...parentCtx.overrides, ...overrides },
|
|
52
52
|
},
|
|
53
53
|
overrides: Object.keys(mergedOverrides).length > 0 ? mergedOverrides : undefined,
|
|
54
|
+
presetName: parentCtx.presetName,
|
|
55
|
+
scaleId: parentCtx.scaleId,
|
|
54
56
|
};
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -72,14 +74,17 @@ export function Preset({
|
|
|
72
74
|
base = freshDefault;
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
const scope = { presetName: parentCtx?.presetName, scaleId: parentCtx?.scaleId };
|
|
78
|
+
|
|
75
79
|
if (overrides) {
|
|
76
80
|
return {
|
|
77
81
|
preset: { ...base, knobs: { ...base.knobs, ...overrides } },
|
|
78
82
|
overrides,
|
|
83
|
+
...scope,
|
|
79
84
|
};
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
return { preset: base };
|
|
87
|
+
return { preset: base, ...scope };
|
|
83
88
|
}, [cascade, parentCtx, presetName, overrides]);
|
|
84
89
|
|
|
85
90
|
let element = <PresetContext.Provider value={ctxValue}>{children}</PresetContext.Provider>;
|
|
@@ -6,6 +6,10 @@ import type { ThemeName } from "@tamagui/web";
|
|
|
6
6
|
export interface PresetContextValue {
|
|
7
7
|
preset: Preset;
|
|
8
8
|
overrides?: Partial<Knobs>;
|
|
9
|
+
/** Name of the provider's active preset, whose scale is installed. */
|
|
10
|
+
presetName?: string;
|
|
11
|
+
/** Id of the installed token scale; changes after a switch re-render every knob reader. */
|
|
12
|
+
scaleId?: string;
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
export const PresetContext = createContext<PresetContextValue | null>(null);
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { TestProviders } from "@multiplatform.one/test-utils";
|
|
2
2
|
/**
|
|
3
|
-
* Surface context
|
|
3
|
+
* Surface context: a forwarded size token with a step-down ceiling (LC-78).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { render, renderHook } from "@testing-library/react";
|
|
7
7
|
import { createElement, type ReactNode } from "react";
|
|
8
8
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
9
|
+
import type { SizeTokens } from "tamagui";
|
|
10
|
+
import { generateScale } from "./scale/generateScale";
|
|
11
|
+
import { defaultScaleInputs } from "./scale/scaleInputs";
|
|
9
12
|
import {
|
|
10
13
|
Surface,
|
|
11
14
|
SurfaceContext,
|
|
12
|
-
clampSurfaceDensity,
|
|
13
15
|
clampSurfaceSize,
|
|
16
|
+
compareSizeTokens,
|
|
17
|
+
sizeTokenStep,
|
|
18
|
+
sizeTokenBelow,
|
|
19
|
+
sizeTokenStop,
|
|
20
|
+
surfaceSizeRank,
|
|
14
21
|
type SurfaceIntent,
|
|
15
22
|
} from "./Surface";
|
|
16
23
|
import { useResolvedKnobs } from "./useResolvedKnobs";
|
|
@@ -44,114 +51,154 @@ function Probe({ onRead }: { onRead: (intent: SurfaceIntent) => void }) {
|
|
|
44
51
|
return null;
|
|
45
52
|
}
|
|
46
53
|
|
|
47
|
-
function renderNested(
|
|
48
|
-
outer: { size?: "small" | "medium" | "large"; density?: "compact" | "comfortable" },
|
|
49
|
-
inner: { size?: "small" | "medium" | "large"; density?: "compact" | "comfortable" },
|
|
50
|
-
): SurfaceIntent {
|
|
54
|
+
function renderNested(outer: SizeTokens | undefined, inner: SizeTokens | undefined): SurfaceIntent {
|
|
51
55
|
let intent: SurfaceIntent | undefined;
|
|
52
56
|
render(
|
|
53
57
|
createElement(
|
|
54
58
|
Surface,
|
|
55
|
-
outer,
|
|
56
|
-
createElement(
|
|
59
|
+
{ size: outer },
|
|
60
|
+
createElement(
|
|
61
|
+
Surface,
|
|
62
|
+
{ size: inner },
|
|
63
|
+
createElement(Probe, { onRead: (value) => (intent = value) }),
|
|
64
|
+
),
|
|
57
65
|
),
|
|
58
66
|
);
|
|
59
67
|
if (!intent) throw new Error("Surface probe did not render");
|
|
60
68
|
return intent;
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
const scale = generateScale(defaultScaleInputs).tokens;
|
|
72
|
+
|
|
73
|
+
describe("surfaceSizeRank", () => {
|
|
74
|
+
it("ranks size keys by the scale's sorted $size ladder; $true ranks with $4", () => {
|
|
75
|
+
expect(surfaceSizeRank("$2")!).toBeLessThan(surfaceSizeRank("$3")!);
|
|
76
|
+
expect(surfaceSizeRank("$3")!).toBeLessThan(surfaceSizeRank("$3.5")!);
|
|
77
|
+
expect(surfaceSizeRank("$3.5")!).toBeLessThan(surfaceSizeRank("$4")!);
|
|
78
|
+
expect(surfaceSizeRank("$true")).toBe(surfaceSizeRank("$4"));
|
|
79
|
+
expect(surfaceSizeRank("$5")!).toBeGreaterThan(surfaceSizeRank("$4")!);
|
|
67
80
|
});
|
|
68
81
|
|
|
69
|
-
it("
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
it("does not rank anything that is not a size key (no sm/md/lg aliases)", () => {
|
|
83
|
+
for (const alias of ["sm", "small", "md", "medium", "lg", "large"]) {
|
|
84
|
+
expect(surfaceSizeRank(alias as SizeTokens), alias).toBeUndefined();
|
|
85
|
+
}
|
|
72
86
|
});
|
|
87
|
+
});
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
expect(
|
|
77
|
-
expect(
|
|
89
|
+
describe("compareSizeTokens", () => {
|
|
90
|
+
it("orders size keys on the ladder and treats anything else as equal", () => {
|
|
91
|
+
expect(compareSizeTokens("$3", "$true")).toBeLessThan(0);
|
|
92
|
+
expect(compareSizeTokens("$5", "$4")).toBeGreaterThan(0);
|
|
93
|
+
expect(compareSizeTokens("$4", "$true")).toBe(0);
|
|
94
|
+
expect(compareSizeTokens("small", "$true")).toBe(0);
|
|
78
95
|
});
|
|
79
96
|
|
|
80
|
-
it("
|
|
81
|
-
expect(
|
|
82
|
-
expect(
|
|
83
|
-
expect(
|
|
97
|
+
it("sizeTokenStep says which side of the default control size a token sits", () => {
|
|
98
|
+
expect(sizeTokenStep("$3")).toBe(-1);
|
|
99
|
+
expect(sizeTokenStep("$true")).toBe(0);
|
|
100
|
+
expect(sizeTokenStep("$4")).toBe(0);
|
|
101
|
+
expect(sizeTokenStep("$6")).toBe(1);
|
|
102
|
+
expect([sizeTokenStop("$3"), sizeTokenStop("$true"), sizeTokenStop("$5")]).toEqual([
|
|
103
|
+
"small",
|
|
104
|
+
"medium",
|
|
105
|
+
"large",
|
|
106
|
+
]);
|
|
84
107
|
});
|
|
85
108
|
});
|
|
86
109
|
|
|
87
|
-
describe("
|
|
110
|
+
describe("clampSurfaceSize", () => {
|
|
88
111
|
it("unset parent is no ceiling", () => {
|
|
89
|
-
expect(
|
|
112
|
+
expect(clampSurfaceSize("$5", "unset")).toBe("$5");
|
|
113
|
+
expect(clampSurfaceSize("unset", "unset")).toBe("unset");
|
|
90
114
|
});
|
|
91
115
|
|
|
92
116
|
it("unset requested inherits parent", () => {
|
|
93
|
-
expect(
|
|
117
|
+
expect(clampSurfaceSize("unset", "$3")).toBe("$3");
|
|
118
|
+
expect(clampSurfaceSize("unset", "$5")).toBe("$5");
|
|
94
119
|
});
|
|
95
120
|
|
|
96
|
-
it("never exceeds parent
|
|
97
|
-
expect(
|
|
98
|
-
expect(
|
|
121
|
+
it("never exceeds parent", () => {
|
|
122
|
+
expect(clampSurfaceSize("$5", "$3")).toBe("$3");
|
|
123
|
+
expect(clampSurfaceSize("$4", "$3")).toBe("$3");
|
|
124
|
+
expect(clampSurfaceSize("$true", "$3")).toBe("$3");
|
|
125
|
+
expect(clampSurfaceSize("$5", "$true")).toBe("$true");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("smaller than parent is allowed", () => {
|
|
129
|
+
expect(clampSurfaceSize("$3", "$5")).toBe("$3");
|
|
130
|
+
expect(clampSurfaceSize("$2", "$true")).toBe("$2");
|
|
131
|
+
expect(clampSurfaceSize("$true", "$4")).toBe("$true");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("an unranked request under a ceiling takes the ceiling", () => {
|
|
135
|
+
expect(clampSurfaceSize(40 as SizeTokens, "$3")).toBe("$3");
|
|
99
136
|
});
|
|
100
137
|
});
|
|
101
138
|
|
|
102
|
-
describe("Surface nesting (LC-
|
|
103
|
-
it("nested
|
|
104
|
-
expect(renderNested(
|
|
139
|
+
describe("Surface nesting (LC-78)", () => {
|
|
140
|
+
it("nested $5 inside $3 resolves $3", () => {
|
|
141
|
+
expect(renderNested("$3", "$5").size).toBe("$3");
|
|
105
142
|
});
|
|
106
143
|
|
|
107
|
-
it("nested
|
|
108
|
-
expect(renderNested(
|
|
109
|
-
"compact",
|
|
110
|
-
);
|
|
144
|
+
it("nested $3 inside $5 resolves $3 (smaller allowed)", () => {
|
|
145
|
+
expect(renderNested("$5", "$3").size).toBe("$3");
|
|
111
146
|
});
|
|
112
147
|
|
|
113
|
-
it("
|
|
114
|
-
expect(renderNested(
|
|
148
|
+
it("an unset inner Surface inherits the outer token", () => {
|
|
149
|
+
expect(renderNested("$3", undefined).size).toBe("$3");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("the context carries only a size: no density", () => {
|
|
153
|
+
expect(renderNested("$3", undefined)).not.toHaveProperty("density");
|
|
115
154
|
});
|
|
116
155
|
});
|
|
117
156
|
|
|
118
157
|
describe("useResolvedKnobs inside Surface", () => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const { result } = renderHook(() => useResolvedKnobs(), { wrapper });
|
|
127
|
-
expect(result.current.knobProps.size).toBe("small");
|
|
158
|
+
const inSurface =
|
|
159
|
+
(size: SizeTokens) =>
|
|
160
|
+
({ children }: { children: ReactNode }) =>
|
|
161
|
+
createElement(TestProviders, null, createElement(Surface, { size }, children));
|
|
162
|
+
|
|
163
|
+
it('<Surface size="$3"> renders controls at the scale\'s $3 height', () => {
|
|
164
|
+
const { result } = renderHook(() => useResolvedKnobs(), { wrapper: inSurface("$3") });
|
|
128
165
|
expect(result.current.knobProps.sizeToken).toBe("$3");
|
|
129
|
-
expect(result.current.knobProps.
|
|
130
|
-
expect(result.current.knobProps.
|
|
131
|
-
expect(result.current.knobProps.control.height).toBe(36);
|
|
166
|
+
expect(result.current.knobProps.control.height).toBe(scale.size.$3);
|
|
167
|
+
expect(result.current.knobProps.label.fontSize).toBe("$3");
|
|
132
168
|
});
|
|
133
169
|
|
|
134
|
-
it(
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
expect(result.current.knobProps.
|
|
139
|
-
expect(result.current.knobProps.
|
|
170
|
+
it('a size="$5" request inside <Surface size="$3"> clamps to $3', () => {
|
|
171
|
+
const { result } = renderHook(() => useResolvedKnobs({ size: "$5" }), {
|
|
172
|
+
wrapper: inSurface("$3"),
|
|
173
|
+
});
|
|
174
|
+
expect(result.current.knobProps.sizeToken).toBe("$3");
|
|
175
|
+
expect(result.current.knobProps.control.height).toBe(scale.size.$3);
|
|
140
176
|
});
|
|
141
177
|
|
|
142
|
-
it("
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
expect(result.current.knobProps.
|
|
178
|
+
it("a smaller request inside the Surface keeps its own token", () => {
|
|
179
|
+
const { result } = renderHook(() => useResolvedKnobs({ size: "$2" }), {
|
|
180
|
+
wrapper: inSurface("$3"),
|
|
181
|
+
});
|
|
182
|
+
expect(result.current.knobProps.sizeToken).toBe("$2");
|
|
183
|
+
expect(result.current.knobProps.control.height).toBe(scale.size.$2);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("the Surface token is the subtree default, and the spacing roles do not move", () => {
|
|
187
|
+
const { result } = renderHook(() => useResolvedKnobs(), { wrapper: inSurface("$5") });
|
|
147
188
|
expect(result.current.knobProps.sizeToken).toBe("$5");
|
|
189
|
+
expect(result.current.knobProps.control.height).toBe(scale.size.$5);
|
|
190
|
+
expect(result.current.knobProps.gap).toEqual({ gap: "$3" });
|
|
191
|
+
expect(result.current.knobProps.panelPadding).toEqual({ padding: "$4" });
|
|
148
192
|
});
|
|
193
|
+
});
|
|
149
194
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
expect(
|
|
155
|
-
expect(
|
|
195
|
+
describe("sizeTokenBelow", () => {
|
|
196
|
+
it("steps one whole key down, $true reading as $4, floored at $1", () => {
|
|
197
|
+
expect(sizeTokenBelow("$true")).toBe("$3");
|
|
198
|
+
expect(sizeTokenBelow("$4")).toBe("$3");
|
|
199
|
+
expect(sizeTokenBelow("$3")).toBe("$2");
|
|
200
|
+
expect(sizeTokenBelow("$5")).toBe("$4");
|
|
201
|
+
expect(sizeTokenBelow("$1")).toBe("$1");
|
|
202
|
+
expect(sizeTokenBelow("$3.5")).toBe("$3");
|
|
156
203
|
});
|
|
157
204
|
});
|