@thecb/components 10.4.7-beta.0 → 10.5.0-beta.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thecb/components",
3
- "version": "10.4.7-beta.0",
3
+ "version": "10.5.0-beta.0",
4
4
  "description": "Common lib for CityBase react components",
5
5
  "main": "dist/index.cjs.js",
6
6
  "typings": "dist/index.d.ts",
@@ -20,9 +20,9 @@ const HiddenToggleSwitchBox = styled.input`
20
20
  `;
21
21
 
22
22
  const VisibleSwitchComponent = styled.label`
23
- width: 44px;
23
+ width: 48px;
24
24
  height: 24px;
25
- border-radius: 12px;
25
+ border-radius: 48px;
26
26
  border: none;
27
27
  position: relative;
28
28
  box-sizing: border-box;
@@ -41,15 +41,27 @@ const VisibleSwitchComponent = styled.label`
41
41
  ${({ isMobile }) => (isMobile ? `transform: scale(0.75)` : ``)}
42
42
  `;
43
43
 
44
- const ToggleSwitchRingComponent = styled.div`
44
+ const ToggleSwitchMiddleRingComponent = styled.div`
45
45
  position: absolute;
46
- width: 16px;
47
- height: 16px;
46
+ width: 20px;
47
+ height: 20px;
48
48
  border: none;
49
49
  border-radius: 50%;
50
50
  box-sizing: border-box;
51
51
  `;
52
52
 
53
+ const ToggleSwitchInnerRingComponent = styled.div`
54
+ position: absolute;
55
+ width: 14px;
56
+ height: 14px;
57
+ top: 3px;
58
+ left: 3px;
59
+ right: 3px;
60
+ bottom: 3px;
61
+ border-radius: 50%;
62
+ box-sizing: border-box;
63
+ `;
64
+
53
65
  const ToggleSwitch = ({
54
66
  isOn = false,
55
67
  onToggle = noop,
@@ -61,32 +73,54 @@ const ToggleSwitch = ({
61
73
  isMobile,
62
74
  dataQa
63
75
  }) => {
64
- const ToggleSwitchRing = posed(ToggleSwitchRingComponent)({
76
+ const ToggleSwitchInnerRing = posed(ToggleSwitchInnerRingComponent)({
77
+ off: {
78
+ backgroundColor: themeValues.offBackground,
79
+ transition: {
80
+ ease: "easeOut"
81
+ }
82
+ },
83
+ on: {
84
+ backgroundColor: themeValues.onBackground,
85
+ transition: {
86
+ ease: "easeIn"
87
+ }
88
+ },
89
+ disabled: {
90
+ backgroundColor: themeValues.disabledBackground
91
+ }
92
+ });
93
+
94
+ const ToggleSwitchMiddleRing = posed(ToggleSwitchMiddleRingComponent)({
65
95
  off: {
66
- backgroundColor: disabled
67
- ? themeValues.disabledBackground
68
- : themeValues.onBackground,
69
- left: "4px",
70
- top: "3px",
71
- bottom: "3px",
72
- right: "20px",
96
+ backgroundColor: themeValues.white,
97
+ left: "2px",
98
+ top: "2px",
99
+ bottom: "2px",
100
+ right: "24px",
73
101
  transition: {
74
102
  ease: "backIn"
75
103
  }
76
104
  },
77
105
  on: {
78
106
  backgroundColor: themeValues.white,
79
- right: "8px",
80
- top: "3px",
81
- bottom: "4px",
82
- left: "23px",
107
+ right: "1px",
108
+ top: "2px",
109
+ bottom: "2px",
110
+ left: "25px",
83
111
  transition: {
84
112
  ease: "backIn"
85
113
  }
114
+ },
115
+ disabled: {
116
+ backgroundColor: themeValues.white,
117
+ left: "2px",
118
+ top: "2px",
119
+ bottom: "2px",
120
+ right: "24px"
86
121
  }
87
122
  });
88
123
 
89
- // to do: for disabled, background color should not be white (should be lighter disabled background)
90
124
  const VisibleSwitch = posed(VisibleSwitchComponent)({
91
125
  focusable: true,
92
126
  hoverable: true,
@@ -99,28 +133,19 @@ const ToggleSwitch = ({
99
133
  boxShadow: "0px 2px 5px 0px rgba(0,0,0,0.5)"
100
134
  },
101
135
  off: {
102
- border: "1px solid",
103
- backgroundColor: disabled
104
- ? themeValues.disabledBackgroundLight
105
- : themeValues.white,
106
- borderColor: disabled
107
- ? themeValues.disabledBackground
108
- : themeValues.onBackground,
136
+ backgroundColor: themeValues.offBackground,
109
137
  transition: {
110
138
  ease: "easeOut"
111
139
  }
112
140
  },
113
141
  on: {
114
- border: "1px solid",
115
- backgroundColor: disabled
116
- ? themeValues.disabledBackground
117
- : themeValues.onBackground,
118
- borderColor: disabled
119
- ? themeValues.disabledBackground
120
- : themeValues.onBackground,
142
+ backgroundColor: themeValues.onBackground,
121
143
  transition: {
122
144
  ease: "easeIn"
123
145
  }
146
+ },
147
+ disabled: {
148
+ backgroundColor: themeValues.disabledBackground
124
149
  }
125
150
  });
126
151
 
@@ -159,12 +184,14 @@ const ToggleSwitch = ({
159
184
  htmlFor={`#toggle-${name}`}
160
185
  onClick={disabled ? noop : onToggle}
161
186
  onKeyDown={disabled ? noop : handleKeyDown}
162
- pose={isOn ? "on" : "off"}
187
+ pose={disabled ? "disabled" : isOn ? "on" : "off"}
163
188
  tabIndex={disabled ? -1 : 0}
164
189
  disabled={disabled}
165
190
  isMobile={isMobile}
166
191
  >
167
- <ToggleSwitchRing />
192
+ <ToggleSwitchMiddleRing>
193
+ <ToggleSwitchInnerRing />
194
+ </ToggleSwitchMiddleRing>
168
195
  </VisibleSwitch>
169
196
  </Box>
170
197
  </Cover>
@@ -1,5 +1,5 @@
1
1
  import React, { useState, Fragment } from "react";
2
- import { boolean, text } from "@storybook/addon-knobs";
2
+ import { boolean } from "@storybook/addon-knobs";
3
3
  import ToggleSwitch from "./ToggleSwitch";
4
4
  import page from "../../../../.storybook/page";
5
5
 
@@ -7,12 +7,12 @@ export const toggleSwitchDefault = () => {
7
7
  const [isOn, onToggle] = useState(false);
8
8
 
9
9
  const disabled = boolean("disabled", false, "props");
10
- const label = text(label, "Toggle Switch Label", "props");
10
+
11
11
  return (
12
12
  <Fragment>
13
13
  <ToggleSwitch
14
14
  name="toggle-switch"
15
- label={label}
15
+ label="Toggle Switch Label"
16
16
  isOn={isOn}
17
17
  onToggle={() => onToggle(!isOn)}
18
18
  disabled={disabled}
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  WHITE,
3
- ATHENS_GREY,
4
- MANATEE_GREY,
3
+ REGENT_GREY,
4
+ IRON_GREY,
5
5
  MATISSE_BLUE
6
6
  } from "../../../constants/colors";
7
7
 
8
8
  const onBackground = `${MATISSE_BLUE}`;
9
- const disabledBackground = `${MANATEE_GREY}`;
10
- const disabledBackgroundLight = `${ATHENS_GREY}`;
9
+ const disabledBackground = `${IRON_GREY}`;
11
10
  const white = `${WHITE}`;
11
+ const offBackground = `${REGENT_GREY}`;
12
12
 
13
13
  const labelStyles = `
14
14
  display: flex;
@@ -29,8 +29,8 @@ const leftLabelStyles = `
29
29
  export const fallbackValues = {
30
30
  onBackground,
31
31
  disabledBackground,
32
- disabledBackgroundLight,
33
32
  white,
33
+ offBackground,
34
34
  rightLabelStyles,
35
35
  leftLabelStyles
36
36
  };
@@ -1,221 +1,10 @@
1
- import React, { Fragment, useContext, useRef } from "react";
2
- import { ThemeContext } from "styled-components";
3
- import AriaModal from "react-aria-modal";
4
- import { WHITE, ATHENS_GREY, SILVER_GREY } from "../../../constants/colors";
5
- import { FONT_WEIGHT_SEMIBOLD } from "../../../constants/style_constants";
6
- import Paragraph from "../../atoms/paragraph";
7
- import Title from "../../atoms/title";
8
- import ButtonWithAction from "../../atoms/button-with-action";
9
- import { Box, Stack, Cluster } from "../../atoms/layouts";
1
+ import React from "react";
2
+ import ModalControlV1 from "./ModalControlV1";
3
+ import ModalControlV2 from "./ModalControlV2";
10
4
 
11
- /*
12
- Default Modal molecule
13
- Uses react-aria-modal behind the scenes for a11y purposes
14
- Styling accomplished with our atoms / layout primitives
15
-
16
- Cancel button will (for now) always use hideModal as its action
17
- Continue button takes an action, if you want to navigate to
18
- a different route (as with a link) connect() and use "push" from @thecb/connected-react-router
19
- */
20
-
21
- const getApplicationNode = () => document.getElementById("root");
22
-
23
- const Modal = ({
24
- hideModal,
25
- onExit = hideModal,
26
- continueAction,
27
- isContinueActionDisabled = false,
28
- cancelAction,
29
- modalOpen,
30
- modalHeaderText,
31
- modalBodyText,
32
- cancelButtonText = "Cancel",
33
- continueButtonText = "Continue",
34
- closeButtonText = "Close",
35
- modalHeaderBg = WHITE,
36
- modalBodyBg = ATHENS_GREY,
37
- useDangerButton = false,
38
- defaultWrapper = true,
39
- onlyCloseButton = false,
40
- noButtons = false, // for instances where modal is closed automatically
41
- maxHeight,
42
- underlayClickExits = true,
43
- noBorder,
44
- customWidth,
45
- isLoading,
46
- buttonExtraStyles,
47
- children,
48
- dataQa = null,
49
- initialFocusSelector = "",
50
- blurUnderlay = true
51
- }) => {
52
- const { isMobile } = useContext(ThemeContext);
53
- const modalContainerRef = useRef(null);
54
-
55
- return (
56
- <div ref={modalContainerRef} data-qa={dataQa}>
57
- {modalOpen && (
58
- <AriaModal
59
- // fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
60
- focusTrapOptions={{
61
- fallbackFocus: modalContainerRef?.current
62
- }}
63
- onExit={onExit}
64
- getApplicationNode={getApplicationNode}
65
- titleText={modalHeaderText}
66
- underlayStyle={{
67
- display: "flex",
68
- flexDirection: "column",
69
- justifyContent: "center",
70
- alignItems: "center",
71
- background: "rgba(41, 42, 51, 0.45)",
72
- backdropFilter: blurUnderlay ? "blur(4px)" : "none",
73
- WebkitBackdropFilter: blurUnderlay ? "blur(4px)" : "none"
74
- }}
75
- dialogStyle={{
76
- width: customWidth || "615px",
77
- overflow: "auto"
78
- }}
79
- underlayClickExits={underlayClickExits}
80
- aria-modal={true}
81
- initialFocus={initialFocusSelector}
82
- focusDialog={!initialFocusSelector} // Focus the dialogue box itself if no selector for initial focus was provided
83
- >
84
- <Box
85
- padding="0"
86
- borderRadius="2px"
87
- boxShadow="inset 0px -2px 0px 0px rgb(0, 80, 149)"
88
- >
89
- <Box background={modalHeaderBg} padding="1.5rem">
90
- <Cluster justify="flex-start" align="center">
91
- <Title as="h2" weight={FONT_WEIGHT_SEMIBOLD} fontSize="1.25rem">
92
- {modalHeaderText}
93
- </Title>
94
- </Cluster>
95
- </Box>
96
- <Box background={modalBodyBg} padding="1.5rem">
97
- <Stack childGap="1.5rem">
98
- <Box
99
- borderWidthOverride={noBorder && "0 0 2px 0"}
100
- borderColor={!noBorder && SILVER_GREY}
101
- padding={!noBorder && "0 0 1.5rem 0"}
102
- extraStyles={
103
- maxHeight ? `max-height: ${maxHeight}; overflow: auto;` : ``
104
- }
105
- >
106
- {defaultWrapper ? (
107
- <Paragraph variant="p">{modalBodyText}</Paragraph>
108
- ) : (
109
- <Box padding={maxHeight ? "0 0 1rem 0" : "0"}>
110
- {modalBodyText}
111
- </Box>
112
- )}
113
- </Box>
114
- <Box padding="0">
115
- <Stack
116
- direction="row"
117
- justify="flex-end"
118
- align="center"
119
- childGap="0rem"
120
- >
121
- {!noButtons && (
122
- <>
123
- {!onlyCloseButton ? (
124
- <Fragment>
125
- {isMobile ? (
126
- <Stack childGap="1rem" direction="row">
127
- <Box width="100%" padding="0">
128
- <ButtonWithAction
129
- variant="secondary"
130
- action={
131
- cancelAction ? cancelAction : hideModal
132
- }
133
- text={cancelButtonText}
134
- dataQa={cancelButtonText}
135
- extraStyles={buttonExtraStyles}
136
- className="modal-cancel-button"
137
- role="button"
138
- name={cancelButtonText}
139
- />
140
- </Box>
141
- <Box width="100%" padding="0">
142
- <ButtonWithAction
143
- variant={
144
- useDangerButton ? "danger" : "primary"
145
- }
146
- action={continueAction}
147
- text={continueButtonText}
148
- dataQa={continueButtonText}
149
- isLoading={isLoading}
150
- disabled={isContinueActionDisabled}
151
- extraStyles={buttonExtraStyles}
152
- className="modal-continue-button"
153
- role="button"
154
- name={continueButtonText}
155
- />
156
- </Box>
157
- </Stack>
158
- ) : (
159
- <Stack
160
- childGap="1rem"
161
- direction="row"
162
- justify="flex-end"
163
- >
164
- <ButtonWithAction
165
- variant="secondary"
166
- action={
167
- cancelAction ? cancelAction : hideModal
168
- }
169
- text={cancelButtonText}
170
- dataQa={cancelButtonText}
171
- extraStyles={buttonExtraStyles}
172
- className="modal-cancel-button"
173
- role="button"
174
- name={cancelButtonText}
175
- />
176
- <ButtonWithAction
177
- variant={
178
- useDangerButton ? "danger" : "primary"
179
- }
180
- action={continueAction}
181
- text={continueButtonText}
182
- dataQa={continueButtonText}
183
- isLoading={isLoading}
184
- disabled={isContinueActionDisabled}
185
- extraStyles={buttonExtraStyles}
186
- className="modal-continue-button"
187
- role="button"
188
- name={continueButtonText}
189
- />
190
- </Stack>
191
- )}
192
- </Fragment>
193
- ) : (
194
- <Box padding="0.5rem">
195
- <ButtonWithAction
196
- action={hideModal}
197
- variant="primary"
198
- text={closeButtonText}
199
- dataQa={closeButtonText}
200
- extraStyles={buttonExtraStyles}
201
- className="modal-close-button"
202
- role="button"
203
- name={closeButtonText}
204
- />
205
- </Box>
206
- )}
207
- </>
208
- )}
209
- </Stack>
210
- </Box>
211
- </Stack>
212
- </Box>
213
- </Box>
214
- </AriaModal>
215
- )}
216
- {children}
217
- </div>
218
- );
5
+ const Modal = ({ version = "v1", ...rest }) => {
6
+ const ModalControl = version === "v1" ? ModalControlV1 : ModalControlV2;
7
+ return <ModalControl {...rest} />;
219
8
  };
220
9
 
221
10
  export default Modal;
@@ -1,16 +1,18 @@
1
1
  import React, { useEffect, useState } from "react";
2
2
  import { text, boolean } from "@storybook/addon-knobs";
3
3
  import Modal from "./Modal";
4
-
5
4
  import page from "../../../../.storybook/page";
6
5
 
7
6
  import Text from "../../atoms/text";
8
7
  import { noop } from "../../../util/general";
9
8
  import Spinner from "../../atoms/spinner/Spinner";
10
9
  import { Center } from "../../atoms/layouts";
10
+
11
11
  const groupId = "props";
12
- export const modal = () => (
12
+
13
+ export const modalV1 = () => (
13
14
  <Modal
15
+ version="v1"
14
16
  ModalLink={() => (
15
17
  <Text
16
18
  onClick={noop}
@@ -33,13 +35,50 @@ export const modal = () => (
33
35
  modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
34
36
  useDangerButton={boolean("useDangerButton", false, groupId)}
35
37
  defaultWrapper={boolean("defaultWrapper", true, groupId)}
38
+ noBorder={boolean("noBorder", true, groupId)}
36
39
  onlyCloseButton={boolean("onlyCloseButton", false, groupId)}
40
+ onlyContinueButton={boolean("onlyContinueButton", false, groupId)}
37
41
  maxHeight={text("maxHeight", null, groupId)}
38
42
  blurUnderlay={boolean("blurUnderlay", true, groupId)}
39
43
  />
40
44
  );
41
45
 
42
- modal.storyName = "Standard Modal";
46
+ modalV1.storyName = "Standard Modal (V1)";
47
+
48
+ export const modalV2 = () => (
49
+ <Modal
50
+ version="v2"
51
+ ModalLink={() => (
52
+ <Text
53
+ onClick={noop}
54
+ color={"#347BB2"}
55
+ fontSize="18px"
56
+ lineHeight="2rem"
57
+ extraStyles={`cursor: pointer;`}
58
+ >
59
+ Modal Link
60
+ </Text>
61
+ )}
62
+ blurUnderlay={boolean("blurUnderlay", true, groupId)}
63
+ cancelButtonText={text("cancelButtonText", "Cancel", groupId)}
64
+ continueAction={noop}
65
+ continueButtonText={text("continueButtonText", "Continue", groupId)}
66
+ defaultWrapper={boolean("defaultWrapper", true, groupId)}
67
+ hideModal={noop}
68
+ maxHeight={text("maxHeight", null, groupId)}
69
+ modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
70
+ modalBodyText={text("modalBodyText", "Modal Body Text", groupId)}
71
+ modalHeaderBg={text("modalHeaderBg", "white", groupId)}
72
+ modalHeaderText={text("modalHeaderText", "Modal Header Text", groupId)}
73
+ modalOpen={boolean("modalOpen", true, groupId)}
74
+ noButtons={boolean("noButtons", false, groupId)}
75
+ onlyCloseButton={boolean("onlyCloseButton", false, groupId)}
76
+ onlyContinueButton={boolean("onlyContinueButton", false, groupId)}
77
+ useDangerButton={boolean("useDangerButton", false, groupId)}
78
+ />
79
+ );
80
+
81
+ modalV2.storyName = "Standard Modal (V2)";
43
82
 
44
83
  export const modalWithoutButtons = () => {
45
84
  const [isModalOpen, setIsModalOpen] = useState(true);
@@ -51,6 +90,7 @@ export const modalWithoutButtons = () => {
51
90
  }, []);
52
91
  return (
53
92
  <Modal
93
+ version="v1"
54
94
  ModalLink={() => (
55
95
  <Text
56
96
  tabIndex={0}
@@ -86,10 +126,11 @@ export const modalWithoutButtons = () => {
86
126
  );
87
127
  };
88
128
 
89
- modalWithoutButtons.storyName = "Modal Without Buttons";
129
+ modalWithoutButtons.storyName = "Modal (V1) Without Buttons";
90
130
 
91
131
  const story = page({
92
132
  title: "Components|Molecules/Modal",
93
133
  Component: Modal
94
134
  });
135
+
95
136
  export default story;