diff --git a/src/components/RadioGroup.js b/src/components/RadioGroup.js index f9b42c63..6bd3337a 100644 --- a/src/components/RadioGroup.js +++ b/src/components/RadioGroup.js @@ -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()}`); @@ -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") { diff --git a/src/components/internal/InternalRadioGroup.js b/src/components/internal/InternalRadioGroup.js index b73ebe82..813e4ba4 100644 --- a/src/components/internal/InternalRadioGroup.js +++ b/src/components/internal/InternalRadioGroup.js @@ -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, @@ -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, diff --git a/src/hooks/internal/useField.js b/src/hooks/internal/useField.js index c65502da..a5490f7f 100644 --- a/src/hooks/internal/useField.js +++ b/src/hooks/internal/useField.js @@ -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`); } diff --git a/src/themes/default/radioGroup.js b/src/themes/default/radioGroup.js index 3a1af129..ff77d5ff 100644 --- a/src/themes/default/radioGroup.js +++ b/src/themes/default/radioGroup.js @@ -6,6 +6,7 @@ export default (theme, { getColor, getTextStyle }) => { return { display: "flex", flexDirection: "column", + height: "100%", }; } @@ -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), diff --git a/src/utils/component.js b/src/utils/component.js index 9385bb5a..7ef4633a 100644 --- a/src/utils/component.js +++ b/src/utils/component.js @@ -1,4 +1,4 @@ -import { notStringOrEmpty } from "./string"; +import React from "react"; import { DEFAULT_BREAKPOINT } from "./css"; import { hasOwnProperty } from "./core"; @@ -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; } } diff --git a/src/utils/string.js b/src/utils/string.js index 7690f6c2..49a77ba0 100644 --- a/src/utils/string.js +++ b/src/utils/string.js @@ -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() === ""; -} diff --git a/src/utils/string.test.js b/src/utils/string.test.js index 723317fd..f9963c9f 100644 --- a/src/utils/string.test.js +++ b/src/utils/string.test.js @@ -1,4 +1,4 @@ -import { pluralize, notStringOrEmpty } from "./string"; +import { pluralize } from "./string"; describe("pluralize", () => { it("count = 1", () => { @@ -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); - }); -}); diff --git a/website/src/pages/kitchen-sink/components/radio-group.js b/website/src/pages/kitchen-sink/components/radio-group.js index 58aa7219..4cb578ba 100644 --- a/website/src/pages/kitchen-sink/components/radio-group.js +++ b/website/src/pages/kitchen-sink/components/radio-group.js @@ -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"; @@ -134,6 +134,54 @@ function KitchenSinkRadioGroup() { /> + + + + + + Option 1 + + ), + value: "value1", + }, + { + label: ( + + + Option 2 + + ), + value: "value2", + }, + { + label: ( + + + Option 3 + + ), + value: "value3", + }, + { + label: ( + + + Option 4 + + ), + value: "value4", + }, + ]} + /> + +