@jobber/components-native 0.103.1 → 0.104.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/dist/package.json +2 -2
- package/dist/src/primitives/HelperText/HelperText.js +13 -0
- package/dist/src/primitives/HelperText/HelperText.style.js +19 -0
- package/dist/src/primitives/HelperText/HelperText.test.js +55 -0
- package/dist/src/primitives/HelperText/index.js +1 -0
- package/dist/src/primitives/index.js +4 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/src/primitives/HelperText/HelperText.d.ts +15 -0
- package/dist/types/src/primitives/HelperText/HelperText.style.d.ts +16 -0
- package/dist/types/src/primitives/HelperText/HelperText.test.d.ts +1 -0
- package/dist/types/src/primitives/HelperText/index.d.ts +2 -0
- package/dist/types/src/primitives/index.d.ts +1 -1
- package/package.json +2 -2
- package/src/primitives/HelperText/HelperText.stories.tsx +36 -0
- package/src/primitives/HelperText/HelperText.style.ts +21 -0
- package/src/primitives/HelperText/HelperText.test.tsx +80 -0
- package/src/primitives/HelperText/HelperText.tsx +43 -0
- package/src/primitives/HelperText/docs/HelperTextCriticalExample.tsx +9 -0
- package/src/primitives/HelperText/docs/HelperTextNeutralExample.tsx +9 -0
- package/src/primitives/HelperText/docs/index.ts +2 -0
- package/src/primitives/HelperText/index.ts +2 -0
- package/src/primitives/index.ts +1 -1
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.104.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -122,5 +122,5 @@
|
|
|
122
122
|
"react-native-screens": ">=4.18.0",
|
|
123
123
|
"react-native-svg": ">=12.0.0"
|
|
124
124
|
},
|
|
125
|
-
"gitHead": "
|
|
125
|
+
"gitHead": "53e34a184129137a1ea6e2dea8a287ad8a468cfb"
|
|
126
126
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { useStyles } from "./HelperText.style";
|
|
4
|
+
import { Text } from "../../Text";
|
|
5
|
+
import { Icon } from "../../Icon";
|
|
6
|
+
export function HelperText({ message, status = "neutral" }) {
|
|
7
|
+
const styles = useStyles();
|
|
8
|
+
const isCritical = status === "critical";
|
|
9
|
+
return (React.createElement(View, { style: [styles.row, isCritical ? styles.rowCritical : styles.rowNeutral], accessible: isCritical || undefined, accessibilityRole: isCritical ? "alert" : undefined, accessibilityLiveRegion: isCritical ? "assertive" : undefined },
|
|
10
|
+
isCritical && (React.createElement(View, { style: styles.iconContainer },
|
|
11
|
+
React.createElement(Icon, { name: "alert", size: "small", color: "critical" }))),
|
|
12
|
+
React.createElement(Text, { level: "textSupporting", variation: isCritical ? "error" : "subdued" }, message)));
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { tokens as staticTokens } from "../../utils/design";
|
|
2
|
+
import { buildThemedStyles } from "../../AtlantisThemeContext";
|
|
3
|
+
const tightLineHeight = staticTokens["typography--lineHeight-tight"];
|
|
4
|
+
export const useStyles = buildThemedStyles(tokens => ({
|
|
5
|
+
row: {
|
|
6
|
+
flexDirection: "row",
|
|
7
|
+
alignItems: "flex-start",
|
|
8
|
+
},
|
|
9
|
+
rowNeutral: {
|
|
10
|
+
gap: 0,
|
|
11
|
+
},
|
|
12
|
+
rowCritical: {
|
|
13
|
+
gap: tokens["space-smaller"],
|
|
14
|
+
},
|
|
15
|
+
iconContainer: {
|
|
16
|
+
height: tightLineHeight,
|
|
17
|
+
justifyContent: "center",
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
|
+
import { AccessibilityInfo } from "react-native";
|
|
4
|
+
import { HelperText } from ".";
|
|
5
|
+
import { Icon } from "../../Icon";
|
|
6
|
+
describe("HelperText", () => {
|
|
7
|
+
describe("neutral status (default)", () => {
|
|
8
|
+
it("renders the message as subdued supporting text without an alert icon or role", () => {
|
|
9
|
+
const { getByText, queryByRole } = render(React.createElement(HelperText, { message: "Pick a status" }));
|
|
10
|
+
expect(getByText("Pick a status")).toBeDefined();
|
|
11
|
+
expect(queryByRole("alert")).toBeNull();
|
|
12
|
+
});
|
|
13
|
+
it("renders identically when status is explicitly neutral", () => {
|
|
14
|
+
const { getByText, queryByRole } = render(React.createElement(HelperText, { status: "neutral", message: "Pick a status" }));
|
|
15
|
+
expect(getByText("Pick a status")).toBeDefined();
|
|
16
|
+
expect(queryByRole("alert")).toBeNull();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("critical status", () => {
|
|
20
|
+
it("renders the alert icon, error text, alert role, and assertive live region", () => {
|
|
21
|
+
const { getByText, getByRole, UNSAFE_getByType } = render(React.createElement(HelperText, { status: "critical", message: "Pick a status before continuing" }));
|
|
22
|
+
expect(getByText("Pick a status before continuing")).toBeDefined();
|
|
23
|
+
const alertWrapper = getByRole("alert");
|
|
24
|
+
expect(alertWrapper.props.accessibilityLiveRegion).toBe("assertive");
|
|
25
|
+
// Confirms the alert icon is present alongside the message.
|
|
26
|
+
const icon = UNSAFE_getByType(Icon);
|
|
27
|
+
expect(icon.props.name).toBe("alert");
|
|
28
|
+
expect(icon.props.size).toBe("small");
|
|
29
|
+
expect(icon.props.color).toBe("critical");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("leaf invariants", () => {
|
|
33
|
+
it("does not fire imperative accessibility announcements", () => {
|
|
34
|
+
jest.spyOn(AccessibilityInfo, "announceForAccessibility");
|
|
35
|
+
render(React.createElement(HelperText, { status: "neutral", message: "Neutral" }));
|
|
36
|
+
render(React.createElement(HelperText, { status: "critical", message: "Critical" }));
|
|
37
|
+
expect(AccessibilityInfo.announceForAccessibility).not.toHaveBeenCalled();
|
|
38
|
+
jest.mocked(AccessibilityInfo.announceForAccessibility).mockRestore();
|
|
39
|
+
});
|
|
40
|
+
it("renders successfully outside of any Atlantis context", () => {
|
|
41
|
+
// Renders bare (no providers) and asserts no warning or throw.
|
|
42
|
+
const warn = jest.spyOn(console, "warn").mockImplementation(() => {
|
|
43
|
+
// swallow warnings; we'll inspect the spy below
|
|
44
|
+
});
|
|
45
|
+
const error = jest.spyOn(console, "error").mockImplementation(() => {
|
|
46
|
+
// swallow errors; we'll inspect the spy below
|
|
47
|
+
});
|
|
48
|
+
expect(() => render(React.createElement(HelperText, { message: "Bare render" }))).not.toThrow();
|
|
49
|
+
expect(warn).not.toHaveBeenCalled();
|
|
50
|
+
expect(error).not.toHaveBeenCalled();
|
|
51
|
+
warn.mockRestore();
|
|
52
|
+
error.mockRestore();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HelperText } from "./HelperText";
|