@thecb/components 11.11.0-beta.4 → 11.11.0-beta.7

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 (35) hide show
  1. package/README.md +8 -4
  2. package/dist/index.cjs.js +95 -67
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +95 -67
  5. package/dist/index.esm.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/components/atoms/card-type/CardType.js +10 -2
  8. package/src/components/atoms/dropdown/Dropdown.js +2 -3
  9. package/src/components/atoms/dropdown/DropdownIcon.js +1 -0
  10. package/src/components/atoms/dropdown/DropdownIconV2.js +1 -0
  11. package/src/components/atoms/form-layouts/FormInput.js +9 -16
  12. package/src/components/atoms/formatted-bank-account/FormattedBankAccount.js +2 -2
  13. package/src/components/atoms/formatted-bank-account/FormattedBankAccount.theme.js +2 -2
  14. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.js +12 -9
  15. package/src/components/atoms/formatted-credit-card/FormattedCreditCard.theme.js +2 -2
  16. package/src/components/atoms/icons/AmExSmallIcon.js +2 -0
  17. package/src/components/atoms/icons/DiscoverSmallIcon.js +2 -0
  18. package/src/components/atoms/icons/GenericCardLarge.js +1 -1
  19. package/src/components/atoms/icons/GenericSmallIcon.js +2 -0
  20. package/src/components/atoms/icons/MasterCardSmallIcon.js +2 -0
  21. package/src/components/atoms/icons/VisaSmallIcon.js +2 -0
  22. package/src/components/molecules/email-form/EmailForm.js +2 -1
  23. package/src/components/molecules/email-form/EmailForm.stories.js +210 -0
  24. package/src/components/molecules/forgot-password-form/ForgotPasswordForm.js +2 -1
  25. package/src/components/molecules/login-form/LoginForm.js +2 -1
  26. package/src/components/molecules/radio-section/InnerRadioSection.js +3 -3
  27. package/src/components/molecules/radio-section/RadioSection.stories.js +142 -0
  28. package/src/components/molecules/registration-form/RegistrationForm.js +2 -1
  29. package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.js +1 -1
  30. package/src/components/molecules/terms-and-conditions-modal/TermsAndConditionsModal.stories.js +110 -0
  31. package/src/components/molecules/tooltip/Tooltip.js +28 -15
  32. package/src/components/molecules/tooltip/Tooltip.stories.js +5 -5
  33. package/src/components/molecules/tooltip/Tooltip.theme.js +10 -11
  34. package/src/components/molecules/tooltip/index.d.ts +1 -1
  35. package/src/util/formats.js +6 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thecb/components",
3
- "version": "11.11.0-beta.4",
3
+ "version": "11.11.0-beta.7",
4
4
  "description": "Common lib for CityBase react components",
5
5
  "main": "dist/index.cjs.js",
6
6
  "typings": "dist/index.d.ts",
@@ -34,11 +34,19 @@ const cardBrands = {
34
34
  }
35
35
  };
36
36
 
37
+ const normalizeType = type => {
38
+ if (!type) return undefined;
39
+ const lower = type.toLowerCase();
40
+ if (lower === "mastercard") return "master_card";
41
+ return lower;
42
+ };
43
+
37
44
  const CardType = ({ type, size = "small" }) => {
45
+ const normalizedType = normalizeType(type);
38
46
  const { label, [size]: IconComponent } =
39
- cardBrands[type] || cardBrands.default;
47
+ cardBrands[normalizedType] || cardBrands.default;
40
48
  return (
41
- <span role="img" aria-label={label}>
49
+ <span>
42
50
  <IconComponent />
43
51
  </span>
44
52
  );
@@ -13,7 +13,6 @@ import "core-js/proposals/relative-indexing-method";
13
13
 
14
14
  import {
15
15
  ERROR_COLOR,
16
- GREY_CHATEAU,
17
16
  MINESHAFT_GREY,
18
17
  STORM_GREY,
19
18
  WHITE
@@ -35,7 +34,7 @@ const IconWrapper = styled.div`
35
34
 
36
35
  const DropdownContentWrapper = styled.div`
37
36
  transform-origin: 0 0;
38
- border: 1px solid ${GREY_CHATEAU};
37
+ border: 1px solid ${STORM_GREY};
39
38
  border-radius: 2px;
40
39
  background-color: ${WHITE};
41
40
  padding: 8px 0 8px;
@@ -349,7 +348,7 @@ const Dropdown = ({
349
348
  ? ERROR_COLOR
350
349
  : isOpen
351
350
  ? themeValues.selectedColor
352
- : GREY_CHATEAU
351
+ : STORM_GREY
353
352
  }
354
353
  dataQa={placeholder}
355
354
  extraStyles={
@@ -2,6 +2,7 @@ import React from "react";
2
2
 
3
3
  const DropdownIcon = () => (
4
4
  <svg
5
+ aria-hidden="true"
5
6
  version="1.2"
6
7
  xmlns="http://www.w3.org/2000/svg"
7
8
  overflow="visible"
@@ -7,6 +7,7 @@ const DropdownIconV2 = ({
7
7
  ...props
8
8
  }) => (
9
9
  <svg
10
+ aria-hidden="true"
10
11
  width={width}
11
12
  height={height}
12
13
  viewBox={`0 0 ${width} ${height}`}
@@ -5,6 +5,7 @@ import { fallbackValues } from "./FormLayouts.theme.js";
5
5
  import { themeComponent } from "../../../util/themeUtils";
6
6
  import { createIdFromString } from "../../../util/general.js";
7
7
  import Text from "../text";
8
+ import ButtonWithAction from "../button-with-action";
8
9
  import { Box, Cluster, Stack } from "../layouts";
9
10
  import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
10
11
  import { ERROR_COLOR, ROYAL_BLUE } from "../../../constants/colors";
@@ -171,7 +172,7 @@ const FormInput = ({
171
172
  </Cluster>
172
173
  ) : (
173
174
  <Box padding="0" minWidth="100%">
174
- <Cluster justify="space-between" align="center">
175
+ <Cluster justify="space-between" align="center" overflow>
175
176
  {labelDisplayOverride ? (
176
177
  labelDisplayOverride
177
178
  ) : (
@@ -191,22 +192,14 @@ const FormInput = ({
191
192
  </Text>
192
193
  )}
193
194
  {type === "password" && (
194
- <Text
195
- variant={labelTextVariant}
196
- color={themeValues.linkColor}
197
- weight={themeValues.fontWeight}
198
- hoverStyles={themeValues.hoverFocusStyles}
199
- extraStyles={`text-decoration: underline; cursor: pointer; &:focus { outline-offset: -2px; }`}
200
- onClick={() => setShowPassword(!showPassword)}
201
- tabIndex="0"
195
+ <ButtonWithAction
196
+ variant="smallGhost"
197
+ text={showPassword ? "Hide" : "Show"}
198
+ action={() => setShowPassword(!showPassword)}
202
199
  aria-label={showPassword ? "Hide Password" : "Show password"}
203
- aria-live="polite"
204
- onKeyPress={e =>
205
- e.key === "Enter" && setShowPassword(!showPassword)
206
- }
207
- >
208
- {showPassword ? "Hide" : "Show"}
209
- </Text>
200
+ extraStyles={`margin: 0; min-width: auto;`}
201
+ textExtraStyles={`color: ${themeValues.linkColor};`}
202
+ />
210
203
  )}
211
204
  {isMobile && decorator && (
212
205
  <Box padding="0 0 0 auto">{decorator}</Box>
@@ -50,8 +50,8 @@ const FormattedBankAccount = ({
50
50
  <Text
51
51
  variant="p"
52
52
  color={themeValues.autopayTextColor}
53
- extraStyles={`font-style: italic;`}
54
- >{`Autopay Enabled`}</Text>
53
+ extraStyles={`font-style: italic; font-size: .75rem;`}
54
+ >{`Autopay On`}</Text>
55
55
  )}
56
56
  </Stack>
57
57
  </BankItemWrapper>
@@ -1,7 +1,7 @@
1
- import { CHARADE_GREY, REGENT_GREY } from "../../../constants/colors";
1
+ import { CHARADE_GREY, SEA_GREEN } from "../../../constants/colors";
2
2
 
3
3
  const textColor = `${CHARADE_GREY}`;
4
- const autopayTextColor = `${REGENT_GREY}`;
4
+ const autopayTextColor = `${SEA_GREEN}`;
5
5
 
6
6
  export const fallbackValues = {
7
7
  textColor,
@@ -1,5 +1,5 @@
1
- import React, { Fragment } from "react";
2
- import styled from "styled-components";
1
+ import React, { Fragment, useContext } from "react";
2
+ import styled, { ThemeContext } from "styled-components";
3
3
  import CardType from "../card-type";
4
4
  import Text from "../text";
5
5
  import { Box, Stack } from "../layouts";
@@ -15,7 +15,7 @@ export const CreditCardWrapper = styled.div`
15
15
 
16
16
  export const CCIconWrapper = styled.div`
17
17
  margin-right: 16px;
18
- width: 30px;
18
+ width: 36px;
19
19
  height: auto;
20
20
  display: flex;
21
21
  `;
@@ -27,16 +27,18 @@ const FormattedCreditCard = ({
27
27
  expireDate,
28
28
  expirationStatus,
29
29
  themeValues
30
- }) => (
30
+ }) => {
31
+ const { isMobile } = useContext(ThemeContext);
32
+ return (
31
33
  <CreditCardWrapper>
32
34
  <CCIconWrapper>
33
- <CardType type={type} />
35
+ <CardType type={type} size={isMobile ? "small" : "large"} />
34
36
  </CCIconWrapper>
35
37
  <Stack childGap="0">
36
38
  <Box padding="0">
37
39
  <Text
38
40
  variant="p"
39
- padding="0 0 0 8px"
41
+ padding="0"
40
42
  color={themeValues.textColor}
41
43
  textAlign="left"
42
44
  extraStyles={`display: inline-block;`}
@@ -53,12 +55,13 @@ const FormattedCreditCard = ({
53
55
  <Text
54
56
  variant="p"
55
57
  color={themeValues.autopayTextColor}
56
- extraStyles={`font-style: italic;`}
57
- >{`Autopay Enabled`}</Text>
58
+ extraStyles={`font-style: italic; font-size: .75rem;`}
59
+ >{`Autopay On`}</Text>
58
60
  )}
59
61
  </Stack>
60
62
  </CreditCardWrapper>
61
- );
63
+ );
64
+ };
62
65
  export default themeComponent(
63
66
  FormattedCreditCard,
64
67
  "FormattedCreditCard",
@@ -1,7 +1,7 @@
1
- import { CHARADE_GREY, REGENT_GREY } from "../../../constants/colors";
1
+ import { CHARADE_GREY, SEA_GREEN } from "../../../constants/colors";
2
2
 
3
3
  const textColor = `${CHARADE_GREY}`;
4
- const autopayTextColor = `${REGENT_GREY}`;
4
+ const autopayTextColor = `${SEA_GREEN}`;
5
5
 
6
6
  export const fallbackValues = {
7
7
  textColor,
@@ -8,6 +8,8 @@ const AmExSmallIcon = () => {
8
8
  viewBox="0 0 24 16"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
+ role="img"
12
+ aria-label="American Express"
11
13
  >
12
14
  <g clipPath="url(#clip0_3693_1095)">
13
15
  <g clipPath="url(#clip1_3693_1095)">
@@ -8,6 +8,8 @@ const DiscoverSmallIcon = () => {
8
8
  viewBox="0 0 24 16"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
+ role="img"
12
+ aria-label="Discover"
11
13
  >
12
14
  <g clipPath="url(#clip0_3818_267)">
13
15
  <path
@@ -9,7 +9,7 @@ const GenericCardLarge = () => {
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
11
  role="img"
12
- aria-label="Card Payment"
12
+ aria-label="Credit card"
13
13
  >
14
14
  <rect width="36" height="24" rx="2" fill="#15749D" />
15
15
  <path
@@ -8,6 +8,8 @@ const GenericSmallIcon = () => {
8
8
  viewBox="0 0 24 16"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
+ role="img"
12
+ aria-label="Credit card"
11
13
  >
12
14
  <rect width="24" height="16" rx="2" fill="#15749D" />
13
15
  <path
@@ -8,6 +8,8 @@ const MasterCardSmallIcon = () => {
8
8
  viewBox="0 0 24 16"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
+ role="img"
12
+ aria-label="Mastercard"
11
13
  >
12
14
  <rect width="24" height="16" rx="1" fill="#F6F6F9" />
13
15
  <path
@@ -8,6 +8,8 @@ const VisaSmallIcon = () => {
8
8
  viewBox="0 0 24 16"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
+ role="img"
12
+ aria-label="Visa"
11
13
  >
12
14
  <path
13
15
  fillRule="evenodd"
@@ -34,7 +34,8 @@ const EmailForm = ({
34
34
  );
35
35
  const emailFieldErrorMessages = {
36
36
  [required.error]: "Email address is required",
37
- [isProbablyEmail.error]: "Invalid email address"
37
+ [isProbablyEmail.error]:
38
+ "Please enter a valid email address in the format user@example.com"
38
39
  };
39
40
 
40
41
  return (
@@ -0,0 +1,210 @@
1
+ import React from "react";
2
+ import EmailForm from "./EmailForm";
3
+ import { connect, Provider } from "react-redux";
4
+ import { createStore } from "redux";
5
+ import { createFormState, isProbablyEmail } from "redux-freeform";
6
+ import { noop } from "../../../util/general";
7
+ import { fn } from "@storybook/test";
8
+
9
+ const formConfig = {
10
+ email: {
11
+ validators: [isProbablyEmail()]
12
+ }
13
+ };
14
+
15
+ const { mapStateToProps, mapDispatchToProps, reducer } = createFormState(
16
+ formConfig
17
+ );
18
+
19
+ const store = createStore(
20
+ reducer,
21
+ window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
22
+ );
23
+
24
+ const FormWrapper = props => <EmailForm {...props} />;
25
+
26
+ const ConnectedEmailForm = connect(
27
+ mapStateToProps,
28
+ mapDispatchToProps
29
+ )(FormWrapper);
30
+
31
+ export default {
32
+ title: "Molecules/EmailForm",
33
+ component: ConnectedEmailForm,
34
+ tags: ["!autodocs"],
35
+ parameters: {
36
+ layout: "centered"
37
+ },
38
+ args: {
39
+ variant: "default",
40
+ clearOnDismount: undefined,
41
+ fields: undefined,
42
+ actions: undefined,
43
+ showErrors: false,
44
+ guestCheckout: false,
45
+ handleSubmit: noop,
46
+ showWalletCheckbox: false,
47
+ saveToWallet: noop,
48
+ walletCheckboxMarked: false,
49
+ isRequired: false
50
+ },
51
+ argTypes: {
52
+ variant: {
53
+ description: "Form container variant.",
54
+ control: { type: "text" },
55
+ table: {
56
+ type: { summary: "string" },
57
+ defaultValue: { summary: "default" }
58
+ }
59
+ },
60
+ fields: {
61
+ description:
62
+ "Field data, usually generated with [redux-freeform](https://github.com/CityBaseInc/redux-freeform).",
63
+ control: { type: "object" },
64
+ table: {
65
+ type: { summary: "object" },
66
+ defaultValue: { summary: undefined }
67
+ }
68
+ },
69
+ actions: {
70
+ description:
71
+ "Field actions, usually generated with [redux-freeform](https://github.com/CityBaseInc/redux-freeform).",
72
+ control: { type: "object" },
73
+ table: {
74
+ type: { summary: "object" },
75
+ defaultValue: { summary: undefined }
76
+ }
77
+ },
78
+ clearOnDismount: {
79
+ description:
80
+ "If `true`, `actions.form.clear()` will be called when the component unmounts.",
81
+ control: { type: "boolean" },
82
+ table: {
83
+ type: { summary: "boolean" },
84
+ defaultValue: { summary: undefined }
85
+ }
86
+ },
87
+ showErrors: {
88
+ description: "Show form field errors.",
89
+ control: { type: "boolean" },
90
+ table: {
91
+ type: { summary: "boolean" },
92
+ defaultValue: { summary: false }
93
+ }
94
+ },
95
+ guestCheckout: {
96
+ description:
97
+ "If `true`, displays a message about creating a wallet later for faster checkout.",
98
+ control: { type: "boolean" },
99
+ table: {
100
+ type: { summary: "boolean" },
101
+ defaultValue: { summary: false }
102
+ }
103
+ },
104
+ handleSubmit: {
105
+ description:
106
+ "Function called when the `Enter` key is pressed on the email input (via `onKeyDown` prop passed to `FormInput` component).",
107
+ control: { type: "object" },
108
+ table: {
109
+ type: { summary: "function" },
110
+ defaultValue: { summary: undefined }
111
+ }
112
+ },
113
+ showWalletCheckbox: {
114
+ description:
115
+ "If `true`, displays a checkbox to save the email address to wallet.",
116
+ control: { type: "boolean" },
117
+ table: {
118
+ type: { summary: "boolean" },
119
+ defaultValue: { summary: false }
120
+ }
121
+ },
122
+ saveToWallet: {
123
+ description: "Function called when the wallet checkbox is toggled.",
124
+ control: { type: "object" },
125
+ table: {
126
+ type: { summary: "function" },
127
+ defaultValue: { summary: undefined }
128
+ }
129
+ },
130
+ walletCheckboxMarked: {
131
+ description: "Whether the wallet checkbox is checked.",
132
+ control: { type: "boolean" },
133
+ table: {
134
+ type: { summary: "boolean" },
135
+ defaultValue: { summary: false }
136
+ }
137
+ },
138
+ isRequired: {
139
+ description: "If `true`, the email field becomes required.",
140
+ control: { type: "boolean" },
141
+ table: {
142
+ type: { summary: "boolean" },
143
+ defaultValue: { summary: false }
144
+ }
145
+ }
146
+ },
147
+ decorators: [
148
+ Story => (
149
+ <Provider store={store}>
150
+ <Story />
151
+ </Provider>
152
+ )
153
+ ]
154
+ };
155
+
156
+ export const Basic = args => <ConnectedEmailForm {...args} />;
157
+
158
+ export const ShowErrors = {
159
+ args: {
160
+ showErrors: true
161
+ },
162
+ render: args => <ConnectedEmailForm {...args} />
163
+ };
164
+
165
+ export const GuestCheckout = {
166
+ args: {
167
+ guestCheckout: true
168
+ },
169
+ render: args => <ConnectedEmailForm {...args} />
170
+ };
171
+
172
+ export const WithWalletCheckbox = {
173
+ args: {
174
+ showWalletCheckbox: true,
175
+ saveToWallet: fn()
176
+ },
177
+ render: args => <ConnectedEmailForm {...args} />
178
+ };
179
+
180
+ export const Required = {
181
+ args: {
182
+ isRequired: true
183
+ },
184
+ render: args => <ConnectedEmailForm {...args} />
185
+ };
186
+
187
+ export const RequiredWithErrors = {
188
+ args: {
189
+ isRequired: true,
190
+ showErrors: true
191
+ },
192
+ render: args => <ConnectedEmailForm {...args} />
193
+ };
194
+
195
+ export const GuestCheckoutWithWallet = {
196
+ args: {
197
+ guestCheckout: true,
198
+ showWalletCheckbox: true,
199
+ saveToWallet: fn(),
200
+ walletCheckboxMarked: true
201
+ },
202
+ render: args => <ConnectedEmailForm {...args} />
203
+ };
204
+
205
+ export const HandleSubmit = {
206
+ args: {
207
+ handleSubmit: fn()
208
+ },
209
+ render: args => <ConnectedEmailForm {...args} />
210
+ };
@@ -15,7 +15,8 @@ const ForgotPasswordForm = ({
15
15
  }
16
16
  const EmailErrorMessages = {
17
17
  [required.error]: "Email address is required",
18
- [isProbablyEmail.error]: "Email address is not valid"
18
+ [isProbablyEmail.error]:
19
+ "Please enter a valid email address in the format user@example.com"
19
20
  };
20
21
 
21
22
  return (
@@ -15,7 +15,8 @@ const LoginForm = ({
15
15
  }
16
16
  const emailErrorMessages = {
17
17
  [required.error]: "Email address is required",
18
- [isProbablyEmail.error]: "Invalid email address"
18
+ [isProbablyEmail.error]:
19
+ "Please enter a valid email address in the format user@example.com"
19
20
  };
20
21
  const passwordErrorMessages = {
21
22
  [required.error]: "Password is required"
@@ -69,8 +69,8 @@ const InnerRadioSection = ({
69
69
  `;
70
70
 
71
71
  const RightIcon = styled.img`
72
- height: ${({ isMobile }) => (isMobile ? "14px" : "18px")};
73
- width: ${({ isMobile }) => (isMobile ? "22px" : "28px")};
72
+ height: ${({ isMobile }) => (isMobile ? "16px" : "24px")};
73
+ width: ${({ isMobile }) => (isMobile ? "24px" : "36px")};
74
74
  ${({ fade }) => fade && "opacity: 0.4;"}
75
75
  transition: opacity 0.3s ease;
76
76
  `;
@@ -159,7 +159,7 @@ const InnerRadioSection = ({
159
159
  <Box padding={section.titleIcon ? "0 0 0 8px" : "0"}>
160
160
  <Text
161
161
  as="label"
162
- htmlFor={`radio-input-${idString(section)}`}
162
+ htmlFor={`radio-${idString(section)}`}
163
163
  color={CHARADE_GREY}
164
164
  >
165
165
  {section.title}
@@ -0,0 +1,142 @@
1
+ import React, { useState } from "react";
2
+ import RadioSection from "./RadioSection";
3
+ import { Box } from "../../atoms/layouts";
4
+
5
+ const PaymentMethodSections = () => {
6
+ const [openSection, setOpenSection] = useState("");
7
+ return (
8
+ <RadioSection
9
+ toggleOpenSection={setOpenSection}
10
+ openSection={openSection}
11
+ isSectionRequired={true}
12
+ sections={[
13
+ {
14
+ id: "checking-1234",
15
+ title: "Checking Account ending in 1234",
16
+ content: (
17
+ <Box padding="1rem">
18
+ <p>Checking account payment details would appear here.</p>
19
+ </Box>
20
+ ),
21
+ required: true,
22
+ dataQa: "Checking Account"
23
+ },
24
+ {
25
+ id: "savings-5678",
26
+ title: "Savings Account ending in 5678",
27
+ content: (
28
+ <Box padding="1rem">
29
+ <p>Savings account payment details would appear here.</p>
30
+ </Box>
31
+ ),
32
+ required: true,
33
+ dataQa: "Savings Account"
34
+ },
35
+ {
36
+ id: "card-4321",
37
+ title: "Card ending in 4321",
38
+ content: (
39
+ <Box padding="1rem">
40
+ <p>Credit card payment details would appear here.</p>
41
+ </Box>
42
+ ),
43
+ required: true,
44
+ dataQa: "Credit Card"
45
+ }
46
+ ]}
47
+ />
48
+ );
49
+ };
50
+
51
+ const BasicSections = () => {
52
+ const [openSection, setOpenSection] = useState("");
53
+ return (
54
+ <RadioSection
55
+ toggleOpenSection={setOpenSection}
56
+ openSection={openSection}
57
+ sections={[
58
+ {
59
+ id: "section-a",
60
+ title: "Section A",
61
+ content: (
62
+ <Box padding="1rem">
63
+ <p>Content for section A</p>
64
+ </Box>
65
+ )
66
+ },
67
+ {
68
+ id: "section-b",
69
+ title: "Section B",
70
+ content: (
71
+ <Box padding="1rem">
72
+ <p>Content for section B</p>
73
+ </Box>
74
+ )
75
+ },
76
+ {
77
+ id: "section-c",
78
+ title: "Section C",
79
+ content: (
80
+ <Box padding="1rem">
81
+ <p>Content for section C</p>
82
+ </Box>
83
+ )
84
+ }
85
+ ]}
86
+ />
87
+ );
88
+ };
89
+
90
+ const WithDisabledSection = () => {
91
+ const [openSection, setOpenSection] = useState("");
92
+ return (
93
+ <RadioSection
94
+ toggleOpenSection={setOpenSection}
95
+ openSection={openSection}
96
+ sections={[
97
+ {
98
+ id: "enabled-section",
99
+ title: "Enabled Option",
100
+ content: (
101
+ <Box padding="1rem">
102
+ <p>This option is selectable.</p>
103
+ </Box>
104
+ )
105
+ },
106
+ {
107
+ id: "disabled-section",
108
+ title: "Disabled Option",
109
+ disabled: true,
110
+ content: (
111
+ <Box padding="1rem">
112
+ <p>This option is disabled.</p>
113
+ </Box>
114
+ )
115
+ }
116
+ ]}
117
+ />
118
+ );
119
+ };
120
+
121
+ const meta = {
122
+ title: "Molecules/RadioSection",
123
+ component: RadioSection,
124
+ parameters: {
125
+ layout: "centered"
126
+ },
127
+ tags: ["!autodocs"]
128
+ };
129
+
130
+ export default meta;
131
+
132
+ export const PaymentMethods = {
133
+ render: () => <PaymentMethodSections />
134
+ };
135
+
136
+ export const Basic = {
137
+ render: () => <BasicSections />
138
+ };
139
+
140
+ export const Disabled = {
141
+ render: () => <WithDisabledSection />
142
+ };