@multiplatform.one/theme 7.69.1 → 7.69.2
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 +5 -5
- package/src/menuRow.spec.ts +44 -4
- package/src/menuRow.ts +52 -7
- package/src/theme/theme.tsx +5 -0
- package/types/menuRow.d.ts +34 -6
- package/types/menuRow.d.ts.map +1 -1
- package/types/theme/theme.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/theme",
|
|
3
|
-
"version": "7.69.
|
|
3
|
+
"version": "7.69.2",
|
|
4
4
|
"description": "Tamagui theme system for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multiplatform",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"access": "public"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@multiplatform.one/platform": "^7.69.
|
|
76
|
-
"@multiplatform.one/store": "^7.69.
|
|
75
|
+
"@multiplatform.one/platform": "^7.69.2",
|
|
76
|
+
"@multiplatform.one/store": "^7.69.2",
|
|
77
77
|
"@tamagui/animations-react-native": "2.7.6",
|
|
78
78
|
"@tamagui/colors": "2.7.6",
|
|
79
79
|
"@tamagui/config": "2.7.6",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@expo/prebuild-config": "55.0.18",
|
|
92
|
-
"@multiplatform.one/config": "7.69.
|
|
93
|
-
"@multiplatform.one/test-utils": "7.69.
|
|
92
|
+
"@multiplatform.one/config": "7.69.2",
|
|
93
|
+
"@multiplatform.one/test-utils": "7.69.2",
|
|
94
94
|
"@tamagui/animations-css": "2.7.6",
|
|
95
95
|
"@tamagui/animations-reanimated": "2.7.6",
|
|
96
96
|
"@tamagui/font-inter": "2.7.6",
|
package/src/menuRow.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { menuRowChecked, menuRowFrame } from "./menuRow";
|
|
2
|
+
import { menuRowCheckInk, menuRowChecked, menuRowFrame, resolveMenuRowCheckInk } from "./menuRow";
|
|
3
3
|
|
|
4
4
|
describe("menuRowFrame (LC-16 shared menu-row geometry)", () => {
|
|
5
5
|
it("spans the overlay edge-to-edge with its own horizontal padding (SP-EDGE)", () => {
|
|
@@ -31,8 +31,48 @@ describe("menuRowFrame (LC-16 shared menu-row geometry)", () => {
|
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
describe("menuRowChecked (LC-262
|
|
35
|
-
it("
|
|
36
|
-
expect(menuRowChecked).
|
|
34
|
+
describe("menuRowChecked (LC-262 checked row, FZ-8355 r6)", () => {
|
|
35
|
+
it("rests light rows on the $color4 selection surface, one step past the $color3 hover", () => {
|
|
36
|
+
expect(menuRowChecked("light").backgroundColor).toBe("$color4");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("recesses dark rows to $color2, off the $color4 dark overlay", () => {
|
|
40
|
+
expect(menuRowChecked("dark").backgroundColor).toBe("$color2");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("keeps the fill through hover and press, and leaves focus rings to the consumer", () => {
|
|
44
|
+
for (const scheme of ["light", "dark"] as const) {
|
|
45
|
+
const checked = menuRowChecked(scheme);
|
|
46
|
+
expect(checked.hoverStyle).toEqual({ backgroundColor: checked.backgroundColor });
|
|
47
|
+
expect(checked.pressStyle).toEqual({ backgroundColor: checked.backgroundColor });
|
|
48
|
+
expect(checked).not.toHaveProperty("focusVisibleStyle");
|
|
49
|
+
expect(checked.backgroundColor).not.toBe(menuRowFrame.backgroundColor);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("marks the check in the theme's selected ink", () => {
|
|
54
|
+
expect(menuRowCheckInk).toBe("$selectedColor");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("resolveMenuRowCheckInk (LC-176 bold mono check on hue-less themes)", () => {
|
|
59
|
+
it("keeps a colour theme's selected ink", () => {
|
|
60
|
+
expect(
|
|
61
|
+
resolveMenuRowCheckInk({ selectedColor: { val: "#113264" }, color: { val: "#050505" } }),
|
|
62
|
+
).toBe("#113264");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("paints the primary ink when the selected ink is grey", () => {
|
|
66
|
+
expect(
|
|
67
|
+
resolveMenuRowCheckInk({
|
|
68
|
+
selectedColor: { val: "hsla(0, 0%, 27%, 1)" },
|
|
69
|
+
color: { val: "hsla(0, 0%, 2%, 1)" },
|
|
70
|
+
}),
|
|
71
|
+
).toBe("hsla(0, 0%, 2%, 1)");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("falls back to the primary ink, then currentColor, when a key is missing", () => {
|
|
75
|
+
expect(resolveMenuRowCheckInk({ color: { val: "#fff" } })).toBe("#fff");
|
|
76
|
+
expect(resolveMenuRowCheckInk({})).toBe("currentColor");
|
|
37
77
|
});
|
|
38
78
|
});
|
package/src/menuRow.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { useTheme } from "tamagui";
|
|
2
|
+
import { normalizeToHex } from "./theme/colorRules";
|
|
3
|
+
import type { ColorScheme } from "./theme/resolveKnobs";
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* LC-16 ONE-IMPLEMENTATION — the shared menu-row frame geometry.
|
|
3
7
|
*
|
|
@@ -35,11 +39,52 @@ export const menuRowFrame = {
|
|
|
35
39
|
} as const;
|
|
36
40
|
|
|
37
41
|
/**
|
|
38
|
-
* LC-262
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
+
* LC-262: a checked or selected menu or picker row is highlighted, so it reads
|
|
43
|
+
* as chosen without hunting for the check (FZ-8355 r6, rv_9244d1b063a3a4de).
|
|
44
|
+
* Light rests on the LC-05 selection surface `$color4`, one step past the
|
|
45
|
+
* `$color3` hover. A dark overlay is itself `$color4` (`surface2`), so dark
|
|
46
|
+
* recesses to `$color2`, the band Clay rated good. In a colour theme both
|
|
47
|
+
* steps carry its hue. Hover and press keep the fill, so a checked row never
|
|
48
|
+
* drops to the transient hover fill. Spread it last on the row so it wins
|
|
49
|
+
* over the consumer's hover and keyboard-cursor fills; a consumer that paints
|
|
50
|
+
* focus as a fill paints `backgroundColor` there too. Focus rings stay the
|
|
51
|
+
* consumer's.
|
|
42
52
|
*/
|
|
43
|
-
export
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
export function menuRowChecked(scheme: ColorScheme) {
|
|
54
|
+
const fill = scheme === "dark" ? "$color2" : "$color4";
|
|
55
|
+
return {
|
|
56
|
+
backgroundColor: fill,
|
|
57
|
+
hoverStyle: { backgroundColor: fill },
|
|
58
|
+
pressStyle: { backgroundColor: fill },
|
|
59
|
+
} as const;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The check mark on a `menuRowChecked` row: the theme's selected ink. */
|
|
63
|
+
export const menuRowCheckInk = "$selectedColor" as const;
|
|
64
|
+
|
|
65
|
+
type ThemeValues = Record<string, { val?: unknown } | undefined>;
|
|
66
|
+
|
|
67
|
+
function isHueless(paint: string): boolean {
|
|
68
|
+
const hex = normalizeToHex(paint);
|
|
69
|
+
if (!hex) return false;
|
|
70
|
+
const rgb = [1, 3, 5].map((i) => Number.parseInt(hex.slice(i, i + 2), 16));
|
|
71
|
+
return Math.max(...rgb) - Math.min(...rgb) <= 8;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The paint for a checked row's check (LC-176, FZ-8355 r6). A colour theme
|
|
76
|
+
* marks it in its selected ink; a hue-less theme's selected ink is a muted
|
|
77
|
+
* grey that reads as a thin grey tick on the fill, so it takes the primary
|
|
78
|
+
* ink instead, the bold mono glyph. Never undefined.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveMenuRowCheckInk(theme: ThemeValues): string {
|
|
81
|
+
const tint = theme[menuRowCheckInk.slice(1)]?.val;
|
|
82
|
+
const ink = theme.color?.val;
|
|
83
|
+
if (typeof tint === "string" && !(isHueless(tint) && typeof ink === "string")) return tint;
|
|
84
|
+
return typeof ink === "string" ? ink : "currentColor";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Live `resolveMenuRowCheckInk` for the theme in scope. */
|
|
88
|
+
export function useMenuRowCheckInk(): string {
|
|
89
|
+
return resolveMenuRowCheckInk(useTheme() as unknown as ThemeValues);
|
|
90
|
+
}
|
package/src/theme/theme.tsx
CHANGED
|
@@ -144,6 +144,11 @@ export function ThemeProvider<T extends CreateTamaguiProps>({
|
|
|
144
144
|
":root { --mp-transition: 200ms; }",
|
|
145
145
|
// Reserve space for scrollbar to prevent gap when modal Sheet hides it
|
|
146
146
|
"html { scrollbar-gutter: stable; }",
|
|
147
|
+
// A scroll lock (Tamagui's sheet lock writes an inline stable gutter plus
|
|
148
|
+
// overflow hidden) must not keep the gutter: it shrinks the initial
|
|
149
|
+
// containing block, so a fixed scrim and sheet stop a scrollbar's width
|
|
150
|
+
// short of the right edge with a page-coloured strip beside them (FZ-8355).
|
|
151
|
+
'html[style*="overflow: hidden"] { scrollbar-gutter: auto !important; }',
|
|
147
152
|
// Disable browser-native focus ring on form controls;
|
|
148
153
|
// components provide their own focus-visible affordance.
|
|
149
154
|
"input:focus, input:focus-visible,",
|
package/types/menuRow.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ColorScheme } from "./theme/resolveKnobs";
|
|
1
2
|
/**
|
|
2
3
|
* LC-16 ONE-IMPLEMENTATION — the shared menu-row frame geometry.
|
|
3
4
|
*
|
|
@@ -34,12 +35,39 @@ export declare const menuRowFrame: {
|
|
|
34
35
|
readonly backgroundColor: "transparent";
|
|
35
36
|
};
|
|
36
37
|
/**
|
|
37
|
-
* LC-262
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* LC-262: a checked or selected menu or picker row is highlighted, so it reads
|
|
39
|
+
* as chosen without hunting for the check (FZ-8355 r6, rv_9244d1b063a3a4de).
|
|
40
|
+
* Light rests on the LC-05 selection surface `$color4`, one step past the
|
|
41
|
+
* `$color3` hover. A dark overlay is itself `$color4` (`surface2`), so dark
|
|
42
|
+
* recesses to `$color2`, the band Clay rated good. In a colour theme both
|
|
43
|
+
* steps carry its hue. Hover and press keep the fill, so a checked row never
|
|
44
|
+
* drops to the transient hover fill. Spread it last on the row so it wins
|
|
45
|
+
* over the consumer's hover and keyboard-cursor fills; a consumer that paints
|
|
46
|
+
* focus as a fill paints `backgroundColor` there too. Focus rings stay the
|
|
47
|
+
* consumer's.
|
|
41
48
|
*/
|
|
42
|
-
export declare
|
|
43
|
-
readonly backgroundColor: "
|
|
49
|
+
export declare function menuRowChecked(scheme: ColorScheme): {
|
|
50
|
+
readonly backgroundColor: "$color2" | "$color4";
|
|
51
|
+
readonly hoverStyle: {
|
|
52
|
+
readonly backgroundColor: "$color2" | "$color4";
|
|
53
|
+
};
|
|
54
|
+
readonly pressStyle: {
|
|
55
|
+
readonly backgroundColor: "$color2" | "$color4";
|
|
56
|
+
};
|
|
44
57
|
};
|
|
58
|
+
/** The check mark on a `menuRowChecked` row: the theme's selected ink. */
|
|
59
|
+
export declare const menuRowCheckInk: "$selectedColor";
|
|
60
|
+
type ThemeValues = Record<string, {
|
|
61
|
+
val?: unknown;
|
|
62
|
+
} | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* The paint for a checked row's check (LC-176, FZ-8355 r6). A colour theme
|
|
65
|
+
* marks it in its selected ink; a hue-less theme's selected ink is a muted
|
|
66
|
+
* grey that reads as a thin grey tick on the fill, so it takes the primary
|
|
67
|
+
* ink instead, the bold mono glyph. Never undefined.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveMenuRowCheckInk(theme: ThemeValues): string;
|
|
70
|
+
/** Live `resolveMenuRowCheckInk` for the theme in scope. */
|
|
71
|
+
export declare function useMenuRowCheckInk(): string;
|
|
72
|
+
export {};
|
|
45
73
|
//# sourceMappingURL=menuRow.d.ts.map
|
package/types/menuRow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menuRow.d.ts","sourceRoot":"","sources":["../src/menuRow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"menuRow.d.ts","sourceRoot":"","sources":["../src/menuRow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC;AAEX;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW;;;;;;;;EAOjD;AAED,0EAA0E;AAC1E,eAAO,MAAM,eAAe,EAAG,gBAAyB,CAAC;AAEzD,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAAC,CAAC;AASjE;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAKjE;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/theme/theme.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAG1B,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAU/C,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,UAAU,CAAC;AAGvD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAkB5D;AAMD,MAAM,WAAW,kBAAkB,CACjC,CAAC,SAAS,kBAAkB,GAAG,kBAAkB,CACjD,SAAQ,iBAAiB,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,cAAc,CAAC,CAAC;IAChF,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,UAAU,CAAC,cAAc,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAChC;AAkBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,kBAAkB,EAAE,EAC1D,QAAQ,EACR,MAAM,EACN,WAAW,EACX,GAAG,YAAY,EAChB,EAAE,kBAAkB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/theme/theme.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAG1B,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAU/C,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,UAAU,CAAC;AAGvD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAkB5D;AAMD,MAAM,WAAW,kBAAkB,CACjC,CAAC,SAAS,kBAAkB,GAAG,kBAAkB,CACjD,SAAQ,iBAAiB,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,cAAc,CAAC,CAAC;IAChF,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,UAAU,CAAC,cAAc,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAChC;AAkBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,kBAAkB,EAAE,EAC1D,QAAQ,EACR,MAAM,EACN,WAAW,EACX,GAAG,YAAY,EAChB,EAAE,kBAAkB,CAAC,CAAC,CAAC,2CA2GvB"}
|