@thecb/components 9.1.0-beta.2 → 9.1.0-beta.4
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/index.cjs.js +37 -12
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +37 -12
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/radio-section/RadioSection.js +24 -11
- package/src/components/molecules/radio-section/RadioSection.stories.js +40 -1
- package/src/components/molecules/radio-section/radio-button/RadioButton.js +12 -3
package/package.json
CHANGED
|
@@ -5,10 +5,9 @@ import { fallbackValues } from "./RadioSection.theme";
|
|
|
5
5
|
import { AnimatePresence } from "framer-motion";
|
|
6
6
|
import RadioButton from "./radio-button/RadioButton";
|
|
7
7
|
import { Box, Cluster, Stack, Motion } from "../../atoms/layouts";
|
|
8
|
-
import { noop } from "../../../util/general";
|
|
8
|
+
import { createIdFromString, noop } from "../../../util/general";
|
|
9
9
|
import Text from "../../atoms/text";
|
|
10
10
|
import { CHARADE_GREY } from "../../../constants/colors";
|
|
11
|
-
import { createIdFromString } from "../../../util/general";
|
|
12
11
|
/*
|
|
13
12
|
Takes an array of section objects, each object should look like:
|
|
14
13
|
{
|
|
@@ -32,6 +31,11 @@ import { createIdFromString } from "../../../util/general";
|
|
|
32
31
|
|
|
33
32
|
*/
|
|
34
33
|
|
|
34
|
+
const idString = section =>
|
|
35
|
+
typeof section.title === "string"
|
|
36
|
+
? createIdFromString(section.title)
|
|
37
|
+
: section.id;
|
|
38
|
+
|
|
35
39
|
const RadioSection = ({
|
|
36
40
|
themeValues,
|
|
37
41
|
isMobile,
|
|
@@ -46,7 +50,7 @@ const RadioSection = ({
|
|
|
46
50
|
ariaDescribedBy
|
|
47
51
|
}) => {
|
|
48
52
|
const handleKeyDown = (id, e) => {
|
|
49
|
-
if (e?.keyCode === 13) {
|
|
53
|
+
if (e?.keyCode === 13 || e?.keyCode === 32) {
|
|
50
54
|
toggleOpenSection(id);
|
|
51
55
|
}
|
|
52
56
|
};
|
|
@@ -101,7 +105,7 @@ const RadioSection = ({
|
|
|
101
105
|
borderRadius="4px"
|
|
102
106
|
extraStyles={containerStyles}
|
|
103
107
|
>
|
|
104
|
-
<Stack childGap="0">
|
|
108
|
+
<Stack childGap="0" role="radiogroup">
|
|
105
109
|
{sections
|
|
106
110
|
.filter(section => !section.hidden)
|
|
107
111
|
.map(section => (
|
|
@@ -117,6 +121,9 @@ const RadioSection = ({
|
|
|
117
121
|
initial={initiallyOpen ? "open" : "closed"}
|
|
118
122
|
key={`item-${section.id}`}
|
|
119
123
|
extraStyles={borderStyles}
|
|
124
|
+
role="radio"
|
|
125
|
+
aria-checked={openSection === section.id}
|
|
126
|
+
aria-disabled={section.disabled}
|
|
120
127
|
>
|
|
121
128
|
<Stack childGap="0">
|
|
122
129
|
<Box
|
|
@@ -159,11 +166,8 @@ const RadioSection = ({
|
|
|
159
166
|
{!section.hideRadioButton && (
|
|
160
167
|
<Box padding="0">
|
|
161
168
|
<RadioButton
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
? createIdFromString(section.title)
|
|
165
|
-
: section.id
|
|
166
|
-
}
|
|
169
|
+
id={`radio-input-${idString(section)}`}
|
|
170
|
+
name={idString(section)}
|
|
167
171
|
ariaDescribedBy={ariaDescribedBy}
|
|
168
172
|
radioOn={openSection === section.id}
|
|
169
173
|
radioFocused={focused === section.id}
|
|
@@ -180,13 +184,21 @@ const RadioSection = ({
|
|
|
180
184
|
<Cluster align="center">{section.titleIcon}</Cluster>
|
|
181
185
|
)}
|
|
182
186
|
<Box padding={section.titleIcon ? "0 0 0 8px" : "0"}>
|
|
183
|
-
<Text
|
|
187
|
+
<Text
|
|
188
|
+
as="label"
|
|
189
|
+
htmlFor={`radio-input-${idString(section)}`}
|
|
190
|
+
color={CHARADE_GREY}
|
|
191
|
+
>
|
|
184
192
|
{section.title}
|
|
185
193
|
</Text>
|
|
186
194
|
</Box>
|
|
187
195
|
</Cluster>
|
|
188
196
|
{section.rightIcons && (
|
|
189
|
-
<Cluster
|
|
197
|
+
<Cluster
|
|
198
|
+
childGap="0.5rem"
|
|
199
|
+
aria-label={section?.rightIconsLabel || null}
|
|
200
|
+
role={section?.rightIconsRole || null}
|
|
201
|
+
>
|
|
190
202
|
{section.rightIcons.map(icon => (
|
|
191
203
|
<RightIcon
|
|
192
204
|
src={icon.img}
|
|
@@ -194,6 +206,7 @@ const RadioSection = ({
|
|
|
194
206
|
fade={!icon.enabled}
|
|
195
207
|
isMobile={isMobile}
|
|
196
208
|
alt={icon.altText}
|
|
209
|
+
aria-disabled={!icon.enabled}
|
|
197
210
|
/>
|
|
198
211
|
))}
|
|
199
212
|
</Cluster>
|
|
@@ -10,8 +10,47 @@ const story = page({
|
|
|
10
10
|
});
|
|
11
11
|
export default story;
|
|
12
12
|
|
|
13
|
+
const cardIcons = [
|
|
14
|
+
{
|
|
15
|
+
img: "https://cityville-demos.uat.cityba.se/Visa.svg",
|
|
16
|
+
enabled: true,
|
|
17
|
+
altText: "visa",
|
|
18
|
+
name: "VISA"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
img: "https://cityville-demos.uat.cityba.se/MasterCardDark.svg",
|
|
22
|
+
enabled: false,
|
|
23
|
+
altText: "master card",
|
|
24
|
+
name: "MASTERCARD"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
img: "https://cityville-demos.uat.cityba.se/DiscoverDark.svg",
|
|
28
|
+
enabled: true,
|
|
29
|
+
altText: "discover",
|
|
30
|
+
name: "DISCOVER"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
img: "https://cityville-demos.uat.cityba.se/AmEx.svg",
|
|
34
|
+
enabled: true,
|
|
35
|
+
altText: "american express",
|
|
36
|
+
name: "AMEX"
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
const cardIconsLabel = `Accepting ${cardIcons
|
|
40
|
+
.filter(ci => ci.enabled)
|
|
41
|
+
?.map((cardIcon, index) =>
|
|
42
|
+
index === cardIcons.length - 1
|
|
43
|
+
? ` and ${cardIcon.altText}.`
|
|
44
|
+
: ` ` + cardIcon.altText
|
|
45
|
+
)}`;
|
|
13
46
|
const sections = [
|
|
14
|
-
{
|
|
47
|
+
{
|
|
48
|
+
id: "new-card-section",
|
|
49
|
+
title: "New Card",
|
|
50
|
+
content: <p>The form to add a credit card would go here.</p>,
|
|
51
|
+
rightIconsLabel: cardIconsLabel,
|
|
52
|
+
rightIcons: cardIcons
|
|
53
|
+
},
|
|
15
54
|
{ id: "bar", title: "Bar", content: <div>Content 1</div> },
|
|
16
55
|
{ id: "baz", title: "Baz", content: <div>Content 2</div> }
|
|
17
56
|
];
|
|
@@ -17,7 +17,9 @@ const RadioButton = ({
|
|
|
17
17
|
name,
|
|
18
18
|
disabled = false,
|
|
19
19
|
ariaDescribedBy = "",
|
|
20
|
-
themeValues
|
|
20
|
+
themeValues,
|
|
21
|
+
ariaLabelledBy = "",
|
|
22
|
+
ariaLabel = null
|
|
21
23
|
}) => {
|
|
22
24
|
const buttonBorder = {
|
|
23
25
|
onFocused: {
|
|
@@ -60,6 +62,12 @@ const RadioButton = ({
|
|
|
60
62
|
width: "0px"
|
|
61
63
|
}
|
|
62
64
|
};
|
|
65
|
+
const extraProps = {};
|
|
66
|
+
if (ariaLabelledBy && ariaLabelledBy.length) {
|
|
67
|
+
extraProps["aria-labelledby"] = ariaLabelledBy;
|
|
68
|
+
} else if (ariaLabel && ariaLabel !== null) {
|
|
69
|
+
extraProps["aria-label"] = ariaLabel;
|
|
70
|
+
}
|
|
63
71
|
|
|
64
72
|
return (
|
|
65
73
|
<Motion
|
|
@@ -77,12 +85,13 @@ const RadioButton = ({
|
|
|
77
85
|
}
|
|
78
86
|
>
|
|
79
87
|
<HiddenRadioButton
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
type="radio"
|
|
89
|
+
id={`radio-${name}`}
|
|
82
90
|
disabled={disabled}
|
|
83
91
|
onClick={toggleRadio}
|
|
84
92
|
aria-describedby={ariaDescribedBy}
|
|
85
93
|
tabIndex="-1"
|
|
94
|
+
{...extraProps}
|
|
86
95
|
/>
|
|
87
96
|
<Motion
|
|
88
97
|
borderWidth="1px"
|