@simplybusiness/mobius 5.1.2 → 5.3.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/cjs/components/Accordion/Accordion.js +6 -5
  3. package/dist/cjs/components/Accordion/Accordion.js.map +1 -1
  4. package/dist/cjs/components/Button/Button.js.map +1 -1
  5. package/dist/cjs/components/Drawer/Drawer.js.map +1 -1
  6. package/dist/cjs/components/Grid/Item.js.map +1 -1
  7. package/dist/cjs/components/Icon/Icon.js.map +1 -1
  8. package/dist/cjs/components/List/List.js.map +1 -1
  9. package/dist/cjs/components/PasswordField/ShowHideButton.js.map +1 -1
  10. package/dist/cjs/components/Progress/Progress.js.map +1 -1
  11. package/dist/cjs/components/Radio/RadioGroup.js.map +1 -1
  12. package/dist/cjs/components/Segment/SegmentGroup.js.map +1 -1
  13. package/dist/cjs/components/Stack/Stack.js.map +1 -1
  14. package/dist/cjs/components/Text/Text.js.map +1 -1
  15. package/dist/cjs/components/Trust/Trust.js.map +1 -1
  16. package/dist/cjs/hooks/useButton/useButton.js +3 -1
  17. package/dist/cjs/hooks/useButton/useButton.js.map +1 -1
  18. package/dist/cjs/hooks/useLabel/useLabel.js.map +1 -1
  19. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  20. package/dist/cjs/utils/getSpacingValue.js.map +1 -1
  21. package/dist/esm/components/Accordion/Accordion.js +6 -5
  22. package/dist/esm/components/Accordion/Accordion.js.map +1 -1
  23. package/dist/esm/components/Button/Button.js.map +1 -1
  24. package/dist/esm/components/Drawer/Drawer.js.map +1 -1
  25. package/dist/esm/components/Grid/Item.js.map +1 -1
  26. package/dist/esm/components/Icon/Icon.js.map +1 -1
  27. package/dist/esm/components/List/List.js.map +1 -1
  28. package/dist/esm/components/PasswordField/ShowHideButton.js.map +1 -1
  29. package/dist/esm/components/Progress/Progress.js.map +1 -1
  30. package/dist/esm/components/Radio/RadioGroup.js.map +1 -1
  31. package/dist/esm/components/Segment/SegmentGroup.js.map +1 -1
  32. package/dist/esm/components/Stack/Stack.js.map +1 -1
  33. package/dist/esm/components/Text/Text.js.map +1 -1
  34. package/dist/esm/components/Trust/Trust.js.map +1 -1
  35. package/dist/esm/hooks/useButton/useButton.js +3 -1
  36. package/dist/esm/hooks/useButton/useButton.js.map +1 -1
  37. package/dist/esm/hooks/useLabel/useLabel.js.map +1 -1
  38. package/dist/esm/utils/getSpacingValue.js.map +1 -1
  39. package/dist/types/components/Accordion/Accordion.d.ts +4 -0
  40. package/dist/types/components/Button/Button.d.ts +4 -0
  41. package/dist/types/hooks/useButton/useButton.d.ts +7 -1
  42. package/package.json +24 -25
  43. package/src/components/Accordion/Accordion.css +9 -0
  44. package/src/components/Accordion/Accordion.stories.tsx +1 -0
  45. package/src/components/Accordion/Accordion.test.tsx +36 -1
  46. package/src/components/Accordion/Accordion.tsx +19 -4
  47. package/src/components/Button/Button.tsx +4 -0
  48. package/src/components/Segment/Segment.css +1 -1
  49. package/src/components/Text/Text.css +5 -0
  50. package/src/hooks/useButton/useButton.tsx +8 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@simplybusiness/mobius",
3
3
  "license": "UNLICENSED",
4
- "version": "5.1.2",
4
+ "version": "5.3.0",
5
5
  "description": "Core library of Mobius react components",
6
6
  "repository": {
7
7
  "type": "git",
@@ -23,7 +23,8 @@
23
23
  "require": "./dist/cjs/index.js",
24
24
  "import": "./dist/esm/index.js",
25
25
  "default": "./dist/esm/index.js"
26
- }
26
+ },
27
+ "./src/**/*.css": "./src/**/*.css"
27
28
  },
28
29
  "scripts": {
29
30
  "clean": "rm -rf dist",
@@ -41,36 +42,34 @@
41
42
  },
42
43
  "sideEffects": false,
43
44
  "devDependencies": {
44
- "@react-types/button": "^3.9.6",
45
- "@react-types/dialog": "^3.5.12",
46
- "@react-types/progress": "^3.5.6",
47
- "@swc/cli": "^0.4.0",
48
- "@swc/core": "^1.7.1",
45
+ "@react-types/progress": "^3.5.7",
46
+ "@swc/cli": "^0.4.1-nightly.20240914",
47
+ "@swc/core": "^1.7.28",
49
48
  "@swc/jest": "^0.2.36",
50
49
  "@testing-library/dom": "^10.4.0",
51
- "@testing-library/jest-dom": "6.4.8",
52
- "@testing-library/react": "^16.0.0",
50
+ "@testing-library/jest-dom": "6.5.0",
51
+ "@testing-library/react": "^16.0.1",
53
52
  "@testing-library/user-event": "^14.5.2",
54
53
  "@total-typescript/shoehorn": "^0.1.2",
55
- "@types/jest": "^29.5.12",
54
+ "@types/jest": "^29.5.13",
56
55
  "@types/lodash.debounce": "^4.0.9",
57
56
  "@types/node": "^20.14.12",
58
- "@types/react": "^18.3.3",
57
+ "@types/react": "^18.3.11",
59
58
  "@types/react-dom": "^18.3.0",
60
- "@typescript-eslint/eslint-plugin": "^7.17.0",
61
- "@typescript-eslint/parser": "^7.17.0",
59
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
60
+ "@typescript-eslint/parser": "^8.8.0",
62
61
  "csstype": "^3.1.3",
63
- "eslint": "^8.57.0",
62
+ "eslint": "^8.57.1",
64
63
  "eslint-config-airbnb": "^19.0.4",
65
64
  "eslint-config-prettier": "^9.1.0",
66
- "eslint-import-resolver-typescript": "^3.6.1",
67
- "eslint-plugin-import": "^2.29.1",
68
- "eslint-plugin-jsx-a11y": "^6.9.0",
69
- "eslint-plugin-no-only-tests": "^3.1.0",
65
+ "eslint-import-resolver-typescript": "^3.6.3",
66
+ "eslint-plugin-import": "^2.31.0",
67
+ "eslint-plugin-jsx-a11y": "^6.10.0",
68
+ "eslint-plugin-no-only-tests": "^3.3.0",
70
69
  "eslint-plugin-prettier": "^5.2.1",
71
- "eslint-plugin-react": "^7.35.0",
70
+ "eslint-plugin-react": "^7.37.1",
72
71
  "eslint-plugin-react-hooks": "^4.6.2",
73
- "eslint-plugin-storybook": "^0.8.0",
72
+ "eslint-plugin-storybook": "^0.9.0",
74
73
  "eslint-plugin-testing-library": "^6.3.0",
75
74
  "identity-obj-proxy": "^3.0.0",
76
75
  "jest": "^29.7.0",
@@ -78,17 +77,17 @@
78
77
  "prettier": "^3.3.3",
79
78
  "react": "^18.3.1",
80
79
  "react-dom": "^18.3.1",
81
- "ts-jest": "^29.2.3",
82
- "tslib": "^2.6.3",
83
- "typescript": "^5.5.4"
80
+ "ts-jest": "^29.2.5",
81
+ "tslib": "^2.7.0",
82
+ "typescript": "^5.6.2"
84
83
  },
85
84
  "peerDependencies": {
86
85
  "react": "^18.2.0",
87
86
  "react-dom": "^18.2.0"
88
87
  },
89
88
  "dependencies": {
90
- "@floating-ui/react": "^0.26.20",
91
- "@simplybusiness/icons": "^4.14.0",
89
+ "@floating-ui/react": "^0.26.24",
90
+ "@simplybusiness/icons": "^4.14.1",
92
91
  "classnames": "^2.5.1",
93
92
  "dialog-polyfill": "^0.5.6",
94
93
  "lodash.debounce": "^4.0.8",
@@ -58,9 +58,18 @@
58
58
  }
59
59
  }
60
60
 
61
+ h1.mobius-accordion__link-text,
62
+ h2.mobius-accordion__link-text,
63
+ h3.mobius-accordion__link-text,
64
+ h4.mobius-accordion__link-text,
65
+ h5.mobius-accordion__link-text,
66
+ h6.mobius-accordion__link-text,
61
67
  .mobius-accordion__link-text {
68
+ margin: 0;
62
69
  margin-right: var(--size-xs);
63
70
  line-height: var(--line-height-normal);
71
+ font-size: var(--font-size-regular);
72
+ font-weight: var(--font-weight-normal);
64
73
  }
65
74
 
66
75
  .mobius-accordion__link-icon {
@@ -31,6 +31,7 @@ export const Default: StoryType = {
31
31
  </Accordion>
32
32
  ),
33
33
  args: {
34
+ linkElementType: "h2",
34
35
  showText: "See more",
35
36
  hideText: "See less",
36
37
  headerPosition: "top",
@@ -1,6 +1,6 @@
1
1
  import { fireEvent, render, screen } from "@testing-library/react";
2
2
  import userEvent from "@testing-library/user-event";
3
- import { Accordion } from ".";
3
+ import { Accordion, AccordionLinkElementType } from ".";
4
4
  import { jestMockMatchMedia } from "../../utils/jestMockMatchMedia";
5
5
 
6
6
  const CONTAINER_CLASS_NAME = "mobius-accordion";
@@ -259,4 +259,39 @@ describe("Accordion", () => {
259
259
  expect(toggle).not.toHaveBeenCalled();
260
260
  });
261
261
  });
262
+
263
+ describe("semantic heading", () => {
264
+ it("uses span by default", async () => {
265
+ const toggle = jest.fn();
266
+ const { container } = render(
267
+ <Accordion onChange={toggle}>Sample text</Accordion>,
268
+ );
269
+
270
+ const linkContainer = container.getElementsByClassName(LINK_CLASS_NAME);
271
+ const link = linkContainer[0].firstChild;
272
+
273
+ expect(link instanceof HTMLSpanElement).toBe(true);
274
+ });
275
+
276
+ it.each(["h1", "h2", "h3", "h4", "h5", "h6"])(
277
+ "uses heading type %s",
278
+ headingType => {
279
+ const toggle = jest.fn();
280
+ const { container } = render(
281
+ <Accordion
282
+ onChange={toggle}
283
+ linkElementType={headingType as AccordionLinkElementType}
284
+ >
285
+ Sample text
286
+ </Accordion>,
287
+ );
288
+
289
+ const linkContainer = container.getElementsByClassName(LINK_CLASS_NAME);
290
+ const link = linkContainer[0].firstChild;
291
+
292
+ expect(link instanceof HTMLHeadingElement).toBe(true);
293
+ expect(link?.nodeName).toBe(headingType.toUpperCase());
294
+ },
295
+ );
296
+ });
262
297
  });
@@ -11,17 +11,26 @@ import {
11
11
  useEffect,
12
12
  useState,
13
13
  } from "react";
14
+ import { usePrefersReducedMotion } from "../../hooks/usePrefersReducedMotion";
14
15
  import { ForwardedRefComponent } from "../../types/components";
15
16
  import { DOMProps } from "../../types/dom";
16
17
  import { Flex } from "../Flex";
17
18
  import { Icon } from "../Icon";
18
- import { usePrefersReducedMotion } from "../../hooks/usePrefersReducedMotion";
19
19
 
20
+ export type AccordionLinkElementType =
21
+ | "h1"
22
+ | "h2"
23
+ | "h3"
24
+ | "h4"
25
+ | "h5"
26
+ | "h6"
27
+ | "span";
20
28
  export type AccordionElementType = HTMLDivElement;
21
29
  export type AccordionRef = Ref<AccordionElementType>;
22
30
  export interface AccordionLinkProps extends DOMProps {
23
31
  /** Link text to show accordion content */
24
32
  text?: string;
33
+ elementType?: AccordionLinkElementType;
25
34
  onClick?: () => void;
26
35
  toggle: () => void;
27
36
  headerChildren?: ReactNode;
@@ -30,6 +39,7 @@ export interface AccordionLinkProps extends DOMProps {
30
39
 
31
40
  const AccordionLink = ({
32
41
  text,
42
+ elementType: LinkElement = "span",
33
43
  toggle,
34
44
  onClick,
35
45
  headerChildren,
@@ -41,7 +51,6 @@ const AccordionLink = ({
41
51
  const iconClasses = classNames("mobius-accordion__link-icon", {
42
52
  "--is-open": ariaExpanded,
43
53
  });
44
-
45
54
  const handleOnClick = (): void => {
46
55
  if (onClick) {
47
56
  onClick();
@@ -70,7 +79,9 @@ const AccordionLink = ({
70
79
  tabIndex={0}
71
80
  aria-expanded={!!ariaExpanded}
72
81
  >
73
- <span className="mobius-accordion__link-text">{text}</span>
82
+ <LinkElement className="mobius-accordion__link-text">
83
+ {text}
84
+ </LinkElement>
74
85
  <Icon icon={chevronDown} className={iconClasses} />
75
86
  </div>
76
87
  {headerChildren}
@@ -87,7 +98,7 @@ const AccordionLink = ({
87
98
  tabIndex={0}
88
99
  aria-expanded={!!ariaExpanded}
89
100
  >
90
- <span className="mobius-accordion__link-text">{text}</span>
101
+ <LinkElement className="mobius-accordion__link-text">{text}</LinkElement>
91
102
  <Icon icon={chevronDown} className={iconClasses} />
92
103
  </div>
93
104
  );
@@ -106,6 +117,8 @@ export interface AccordionProps
106
117
  headerPosition?: "top" | "bottom";
107
118
  /** Whether to expand the accordion initially */
108
119
  startOpen?: boolean | undefined;
120
+ /** Semantic heading for title link (default is span) */
121
+ linkElementType?: AccordionLinkElementType;
109
122
  /** Callback that fires each time the accordion is opened */
110
123
  onOpen?: () => void;
111
124
  /** Callback that fires each time the accordion is closed */
@@ -125,6 +138,7 @@ export const Accordion: ForwardedRefComponent<
125
138
  hideText = "See less",
126
139
  headerPosition = "top",
127
140
  startOpen = false,
141
+ linkElementType,
128
142
  onOpen,
129
143
  onClose,
130
144
  onChange = () => {},
@@ -186,6 +200,7 @@ export const Accordion: ForwardedRefComponent<
186
200
  {headerPosition === "top" && (
187
201
  <AccordionLink
188
202
  text={linkText}
203
+ elementType={linkElementType}
189
204
  toggle={handleChange}
190
205
  ariaExpanded={accordionState.open}
191
206
  headerChildren={headerChildren}
@@ -26,6 +26,10 @@ export interface ButtonProps
26
26
  extends UseButtonProps,
27
27
  DOMProps,
28
28
  RefAttributes<ButtonElementType> {
29
+ /** The name of the button when submitted in a form */
30
+ name?: string | undefined;
31
+ /** The value of the button when submitted in a form */
32
+ value?: string | undefined;
29
33
  /** Custom class name for setting specific CSS */
30
34
  className?: string;
31
35
  /** Shortlist of styles */
@@ -159,7 +159,7 @@
159
159
 
160
160
  /* Colours */
161
161
  &.subtle {
162
- background-color: var(--color-background-highlight);
162
+ background-color: var(--color-border-light);
163
163
  }
164
164
 
165
165
  &.grey {
@@ -11,6 +11,7 @@
11
11
  font-size: var(--font-size-regular);
12
12
  font-weight: var(--font-weight-normal);
13
13
  line-height: var(--line-height-normal);
14
+ text-wrap: pretty;
14
15
  }
15
16
 
16
17
  &:where(.--is-h1) {
@@ -20,6 +21,7 @@
20
21
  font-weight: var(--font-weight-bold);
21
22
  line-height: 1.25; /* 40px */
22
23
  margin: 0.35em 0;
24
+ text-wrap: balance;
23
25
  }
24
26
 
25
27
  &:where(.--is-h2) {
@@ -29,6 +31,7 @@
29
31
  font-weight: var(--font-weight-bold);
30
32
  line-height: var(--line-height-tight); /* 1.333, 32px */
31
33
  margin: 0.45em 0;
34
+ text-wrap: balance;
32
35
  }
33
36
 
34
37
  &:where(.--is-h3) {
@@ -38,6 +41,7 @@
38
41
  font-weight: var(--font-weight-bold);
39
42
  line-height: 1.2; /* 24px */
40
43
  margin: 0.5em 0;
44
+ text-wrap: balance;
41
45
  }
42
46
 
43
47
  &:where(.--is-h4) {
@@ -47,6 +51,7 @@
47
51
  font-weight: var(--font-weight-bold);
48
52
  line-height: var(--line-height-normal); /* 1.5, 24px */
49
53
  margin: 0.55em 0;
54
+ text-wrap: balance;
50
55
  }
51
56
 
52
57
  &:where(.--is-span) {
@@ -16,6 +16,8 @@ export interface UseButtonProps {
16
16
  target?: string;
17
17
  rel?: string;
18
18
  role?: string;
19
+ name?: string | undefined;
20
+ value?: string | undefined;
19
21
  }
20
22
 
21
23
  export function useButton({
@@ -26,6 +28,8 @@ export function useButton({
26
28
  target,
27
29
  rel,
28
30
  role,
31
+ name,
32
+ value,
29
33
  onClick,
30
34
  onPress,
31
35
  }: UseButtonProps) {
@@ -68,6 +72,10 @@ export function useButton({
68
72
  tabIndex: isDisabled ? -1 : 0,
69
73
  disabled: isDisabled || undefined,
70
74
  "aria-disabled": isDisabled || undefined,
75
+ name:
76
+ elementType === "input" || elementType === "button" ? name : undefined,
77
+ value:
78
+ elementType === "input" || elementType === "button" ? value : undefined,
71
79
  ...extraProps,
72
80
  onClick: realOnClick,
73
81
  },