@jobber/components-native 0.115.4 → 0.115.5
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/docs/Elevations/Elevations.md +7 -0
- package/dist/package.json +4 -3
- package/dist/src/AtlantisThemeContext/AtlantisThemeContext.js +7 -2
- package/dist/src/AtlantisThemeContext/AtlantisThemeContext.test.js +26 -5
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/src/AtlantisThemeContext/AtlantisThemeContext.guide.md +13 -5
- package/src/AtlantisThemeContext/AtlantisThemeContext.test.tsx +61 -9
- package/src/AtlantisThemeContext/AtlantisThemeContext.tsx +13 -2
|
@@ -66,6 +66,13 @@ they map to our low/base/high pattern.
|
|
|
66
66
|
| `--shadow-base` | |
|
|
67
67
|
| `--shadow-high` | |
|
|
68
68
|
|
|
69
|
+
### Dark mode
|
|
70
|
+
|
|
71
|
+
On web and iOS, the dark theme keeps the same shadow offsets and blur and only
|
|
72
|
+
raises the opacity, so elevated elements stay distinguishable against dark
|
|
73
|
+
surfaces. On Android, the dark theme raises `elevation`, which makes the shadow
|
|
74
|
+
larger and softer, and uses a fully opaque shadow colour.
|
|
75
|
+
|
|
69
76
|
## Mobile
|
|
70
77
|
|
|
71
78
|
For mobile designs, the concept of elevation applies to both shadows and
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.115.
|
|
3
|
+
"version": "0.115.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -73,11 +73,12 @@
|
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@babel/runtime": "^7.29.2",
|
|
75
75
|
"@gorhom/bottom-sheet": "^5.2.8",
|
|
76
|
-
"@jobber/design": "0.121.
|
|
76
|
+
"@jobber/design": "0.121.1",
|
|
77
77
|
"@jobber/hooks": "2.21.1",
|
|
78
78
|
"@react-native-community/datetimepicker": "^8.4.5",
|
|
79
79
|
"@react-native/babel-preset": "^0.82.1",
|
|
80
80
|
"@storybook/addon-a11y": "10.3.5",
|
|
81
|
+
"@storybook/addon-docs": "10.3.5",
|
|
81
82
|
"@storybook/addon-mcp": "^0.4.2",
|
|
82
83
|
"@storybook/react-native-web-vite": "10.3.5",
|
|
83
84
|
"@testing-library/react-native": "^13.3.3",
|
|
@@ -123,5 +124,5 @@
|
|
|
123
124
|
"react-native-screens": ">=4.18.0",
|
|
124
125
|
"react-native-svg": ">=12.0.0"
|
|
125
126
|
},
|
|
126
|
-
"gitHead": "
|
|
127
|
+
"gitHead": "9b27100be34c36aa1d4717f298cea4388ab9277d"
|
|
127
128
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { androidTokens,
|
|
1
|
+
import { androidTokens, darkAndroidTokens, darkIosTokens, iosTokens, } from "@jobber/design";
|
|
2
2
|
import React, { createContext, useCallback, useContext, useState } from "react";
|
|
3
3
|
import mergeWith from "lodash/mergeWith";
|
|
4
4
|
import { Platform, useColorScheme } from "react-native";
|
|
@@ -7,7 +7,12 @@ const lightTokens = Platform.select({
|
|
|
7
7
|
android: () => androidTokens,
|
|
8
8
|
default: () => androidTokens,
|
|
9
9
|
})();
|
|
10
|
-
const
|
|
10
|
+
const darkPlatformTokens = Platform.select({
|
|
11
|
+
ios: () => darkIosTokens,
|
|
12
|
+
android: () => darkAndroidTokens,
|
|
13
|
+
default: () => darkAndroidTokens,
|
|
14
|
+
})();
|
|
15
|
+
const completeDarkTokens = mergeWith({}, lightTokens, darkPlatformTokens, (platformValue, darkValue) => {
|
|
11
16
|
const platformValueIsObject = typeof platformValue === "object" && platformValue !== null;
|
|
12
17
|
const darkValueIsObject = typeof darkValue === "object" && darkValue !== null;
|
|
13
18
|
if (platformValueIsObject && !darkValueIsObject)
|
|
@@ -9,9 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import React from "react";
|
|
11
11
|
import { act, renderHook } from "@testing-library/react-native";
|
|
12
|
-
import {
|
|
12
|
+
import { androidTokens, darkAndroidTokens, darkIosTokens, iosTokens, } from "@jobber/design";
|
|
13
13
|
import merge from "lodash/merge";
|
|
14
|
-
import { useColorScheme } from "react-native";
|
|
14
|
+
import { useColorScheme, } from "react-native";
|
|
15
15
|
import { AtlantisThemeContextProvider, useAtlantisTheme, } from "./AtlantisThemeContext";
|
|
16
16
|
jest.mock("react-native", () => {
|
|
17
17
|
const actual = jest.requireActual("react-native");
|
|
@@ -21,7 +21,7 @@ jest.mock("react-native", () => {
|
|
|
21
21
|
});
|
|
22
22
|
return actual;
|
|
23
23
|
});
|
|
24
|
-
const expectedDarkTokens =
|
|
24
|
+
const expectedDarkTokens = merge({}, iosTokens, darkIosTokens);
|
|
25
25
|
const expectedLightTokens = iosTokens;
|
|
26
26
|
const mockUseColorScheme = useColorScheme;
|
|
27
27
|
function Wrapper({ children, theme, onThemeChange, dangerouslyOverrideTheme, }) {
|
|
@@ -56,14 +56,35 @@ describe("ThemeContext", () => {
|
|
|
56
56
|
expect(result.current.effectiveTheme).toBe("light");
|
|
57
57
|
expect(result.current.tokens).toEqual(expectedLightTokens);
|
|
58
58
|
}));
|
|
59
|
-
it.each(["shadow-low", "shadow-base", "shadow-high"])("
|
|
59
|
+
it.each(["shadow-low", "shadow-base", "shadow-high"])("uses the dark platform-native %s token in dark mode", (shadowToken) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
60
|
const { result } = renderHook(useAtlantisTheme, {
|
|
61
61
|
wrapper: (props) => (React.createElement(Wrapper, Object.assign({}, props))),
|
|
62
62
|
});
|
|
63
63
|
yield act(() => __awaiter(void 0, void 0, void 0, function* () { return result.current.setTheme("dark"); }));
|
|
64
|
-
expect(result.current.tokens[shadowToken]).toEqual(
|
|
64
|
+
expect(result.current.tokens[shadowToken]).toEqual(darkIosTokens[shadowToken]);
|
|
65
|
+
expect(result.current.tokens[shadowToken]).not.toEqual(iosTokens[shadowToken]);
|
|
65
66
|
expect(typeof result.current.tokens[shadowToken]).toBe("object");
|
|
66
67
|
}));
|
|
68
|
+
describe("on android", () => {
|
|
69
|
+
let android;
|
|
70
|
+
// The provider picks platform tokens at import time, so it is loaded in an
|
|
71
|
+
// isolated registry after Platform is switched to android. This runs while
|
|
72
|
+
// collecting tests because the testing library registers cleanup hooks.
|
|
73
|
+
jest.isolateModules(() => {
|
|
74
|
+
const { Platform, } = require("react-native");
|
|
75
|
+
jest.replaceProperty(Platform, "OS", "android");
|
|
76
|
+
jest.spyOn(Platform, "select").mockImplementation(spec => spec.android);
|
|
77
|
+
android = Object.assign(Object.assign({}, require("@testing-library/react-native")), require("./AtlantisThemeContext"));
|
|
78
|
+
});
|
|
79
|
+
it.each(["shadow-low", "shadow-base", "shadow-high"])("uses the android %s token in light and dark mode", (shadowToken) => __awaiter(void 0, void 0, void 0, function* () {
|
|
80
|
+
const { result } = android.renderHook(android.useAtlantisTheme, {
|
|
81
|
+
wrapper: ({ children }) => (React.createElement(android.AtlantisThemeContextProvider, null, children)),
|
|
82
|
+
});
|
|
83
|
+
expect(result.current.tokens[shadowToken]).toEqual(androidTokens[shadowToken]);
|
|
84
|
+
yield android.act(() => __awaiter(void 0, void 0, void 0, function* () { return result.current.setTheme("dark"); }));
|
|
85
|
+
expect(result.current.tokens[shadowToken]).toEqual(darkAndroidTokens[shadowToken]);
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
67
88
|
it("resolves the system theme from the OS color scheme", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
89
|
mockUseColorScheme.mockReturnValue("dark");
|
|
69
90
|
const { result, rerender } = renderHook(useAtlantisTheme, {
|