Skip to content

Commit

Permalink
Allow RadioGroup option label to be JSX (#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
moroshko committed Apr 21, 2021
1 parent c102e81 commit a0b68b4
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 40 deletions.
26 changes: 16 additions & 10 deletions src/components/RadioGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ function RadioGroup(props) {
} = mergedProps;

if (!options) {
throw new Error(
`RadioGroup options should have the following format: [{ label: "option-label", value: "option-value" }, ...]`
);
throw new Error("RadioGroup options are invalid");
}

const [labelId] = useState(() => `radio-group-label-${nanoid()}`);
Expand Down Expand Up @@ -141,13 +139,21 @@ function RadioGroup(props) {
RadioGroup.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
description: PropTypes.node,
value: PropTypes.string.isRequired,
})
).isRequired,
options: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
description: PropTypes.node,
value: PropTypes.string.isRequired,
})
),
PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.node.isRequired,
value: PropTypes.string.isRequired,
})
),
]).isRequired,
columns: (props) => {
if (props.columns !== undefined) {
if (typeof props.columns !== "number") {
Expand Down
24 changes: 16 additions & 8 deletions src/components/internal/InternalRadioGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Radio.propTypes = {
name: PropTypes.string.isRequired,
parentName: PropTypes.string,
color: PropTypes.oneOf(COLORS),
label: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
isLabelBold: PropTypes.bool.isRequired,
description: PropTypes.node,
isChecked: PropTypes.bool.isRequired,
Expand Down Expand Up @@ -204,13 +204,21 @@ InternalRadioGroup.propTypes = {
name: PropTypes.string.isRequired,
parentName: PropTypes.string,
labelId: PropTypes.string,
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
description: PropTypes.node,
value: PropTypes.string.isRequired,
})
).isRequired,
options: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
description: PropTypes.node,
value: PropTypes.string.isRequired,
})
),
PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.node.isRequired,
value: PropTypes.string.isRequired,
})
),
]).isRequired,
columns: PropTypes.number,
color: PropTypes.oneOf(COLORS),
disabled: PropTypes.bool,
Expand Down
3 changes: 1 addition & 2 deletions src/hooks/internal/useField.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useEffect } from "react";
import useForm from "./useForm";
import { getPath } from "../../utils/objectPath";
import { notStringOrEmpty } from "../../utils/string";

function useField(componentName, { name, disabled, optional, validate, data }) {
if (notStringOrEmpty(name)) {
if (typeof name !== "string" || name.trim() === "") {
throw new Error(`${componentName} component is missing a name prop`);
}

Expand Down
2 changes: 2 additions & 0 deletions src/themes/default/radioGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default (theme, { getColor, getTextStyle }) => {
return {
display: "flex",
flexDirection: "column",
height: "100%",
};
}

Expand All @@ -25,6 +26,7 @@ export default (theme, { getColor, getTextStyle }) => {
alignItems: "flex-start",
padding: `${theme.space[3]} ${theme.space[4]}`,
minHeight: "24px",
height: "100%",
...getTextStyle({ name: "body1", mode: "container" }),
color: theme.colors.black,
backgroundColor: getColor(color),
Expand Down
10 changes: 8 additions & 2 deletions src/utils/component.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { notStringOrEmpty } from "./string";
import React from "react";
import { DEFAULT_BREAKPOINT } from "./css";
import { hasOwnProperty } from "./core";

Expand Down Expand Up @@ -34,7 +34,13 @@ export function areOptionsValid(options) {
}

for (const option of options) {
if (notStringOrEmpty(option.label) || typeof option.value !== "string") {
if (
!(
typeof option.value === "string" &&
((typeof option.label === "string" && option.label.trim() !== "") ||
React.isValidElement(option.label))
)
) {
return false;
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/utils/string.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
export function pluralize(count, word) {
return count === 1 ? `1 ${word}` : `${count} ${word}s`;
}

export function notStringOrEmpty(string) {
return typeof string !== "string" || string.trim() === "";
}
14 changes: 1 addition & 13 deletions src/utils/string.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pluralize, notStringOrEmpty } from "./string";
import { pluralize } from "./string";

describe("pluralize", () => {
it("count = 1", () => {
Expand All @@ -9,15 +9,3 @@ describe("pluralize", () => {
expect(pluralize(5, "day")).toBe("5 days");
});
});

describe("notStringOrEmpty", () => {
it("returns true", () => {
expect(notStringOrEmpty(123)).toBe(true);
expect(notStringOrEmpty("")).toBe(true);
expect(notStringOrEmpty(" ")).toBe(true);
});

it("returns false", () => {
expect(notStringOrEmpty("valid")).toBe(false);
});
});
50 changes: 49 additions & 1 deletion website/src/pages/kitchen-sink/components/radio-group.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import PropTypes from "prop-types";
import { Container, Grid, RadioGroup, Link } from "basis";
import { Container, Flex, Grid, Link, Placeholder, RadioGroup } from "basis";
import KitchenSinkLayout from "../../../components/kitchen-sink/KitchenSinkLayout";
import KitchenSinkForm from "../../../components/kitchen-sink/KitchenSinkForm";

Expand Down Expand Up @@ -134,6 +134,54 @@ function KitchenSinkRadioGroup() {
/>
</Grid>
</Container>

<Container padding="4">
<Grid rowsGap="8">
<FormWithRadioGroup
label="With JSX labels"
columns={2}
initialValue="value1"
options={[
{
label: (
<Flex>
<Placeholder label="Image 1" width="120" height="60" />
<Container margin="0 0 0 6">Option 1</Container>
</Flex>
),
value: "value1",
},
{
label: (
<Flex>
<Placeholder label="Image 2" width="120" height="120" />
<Container margin="0 0 0 6">Option 2</Container>
</Flex>
),
value: "value2",
},
{
label: (
<Flex>
<Placeholder label="Image 3" width="120" height="80" />
<Container margin="0 0 0 6">Option 3</Container>
</Flex>
),
value: "value3",
},
{
label: (
<Flex>
<Placeholder label="Image 4" width="120" height="100" />
<Container margin="0 0 0 6">Option 4</Container>
</Flex>
),
value: "value4",
},
]}
/>
</Grid>
</Container>
</Grid>
</Container>
</KitchenSinkLayout>
Expand Down

1 comment on commit a0b68b4

@vercel
Copy link

@vercel vercel bot commented on a0b68b4 Apr 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.