diff --git a/gradle/changelog/added_radion_button.yaml b/gradle/changelog/added_radion_button.yaml new file mode 100644 index 0000000000..3da625d3b5 --- /dev/null +++ b/gradle/changelog/added_radion_button.yaml @@ -0,0 +1,2 @@ +- type: added + description: Radiobutton components are now available in the ui-forms module diff --git a/gradle/changelog/fixed_chip_input_ref.yaml b/gradle/changelog/fixed_chip_input_ref.yaml new file mode 100644 index 0000000000..b80788b585 --- /dev/null +++ b/gradle/changelog/fixed_chip_input_ref.yaml @@ -0,0 +1,2 @@ +- type: fixed + description: Some chip inputs not correctly passing the ref diff --git a/scm-ui/ui-forms/package.json b/scm-ui/ui-forms/package.json index c935308fae..78b9a79832 100644 --- a/scm-ui/ui-forms/package.json +++ b/scm-ui/ui-forms/package.json @@ -18,6 +18,7 @@ "@scm-manager/tsconfig": "^2.13.0", "@scm-manager/ui-styles": "2.47.1-SNAPSHOT", "@storybook/addon-actions": "^6.5.10", + "@storybook/addon-docs": "^6.5.14", "@storybook/addon-essentials": "^6.5.10", "@storybook/addon-interactions": "^6.5.10", "@storybook/addon-links": "^6.5.10", @@ -25,7 +26,6 @@ "@storybook/manager-webpack5": "^6.5.10", "@storybook/react": "^6.5.10", "@storybook/testing-library": "^0.0.13", - "@storybook/addon-docs": "^6.5.14", "babel-loader": "^8.2.5", "storybook-addon-mock": "^3.2.0", "storybook-addon-themes": "^6.1.0", @@ -41,12 +41,13 @@ "styled-components": "5" }, "dependencies": { - "@scm-manager/ui-buttons": "2.47.1-SNAPSHOT", - "@scm-manager/ui-overlays": "2.47.1-SNAPSHOT", - "@scm-manager/ui-api": "2.47.1-SNAPSHOT", "@headlessui/react": "^1.7.15", + "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-slot": "^1.0.1", - "@radix-ui/react-visually-hidden": "^1.0.3" + "@radix-ui/react-visually-hidden": "^1.0.3", + "@scm-manager/ui-api": "2.47.1-SNAPSHOT", + "@scm-manager/ui-buttons": "2.47.1-SNAPSHOT", + "@scm-manager/ui-overlays": "2.47.1-SNAPSHOT" }, "prettier": "@scm-manager/prettier-config", "eslintConfig": { @@ -55,4 +56,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/scm-ui/ui-forms/src/Form.stories.tsx b/scm-ui/ui-forms/src/Form.stories.tsx index 821b6dd8bb..2dca8480cb 100644 --- a/scm-ui/ui-forms/src/Form.stories.tsx +++ b/scm-ui/ui-forms/src/Form.stories.tsx @@ -40,6 +40,7 @@ import ControlledChipInputField from "./chip-input/ControlledChipInputField"; import Combobox from "./combobox/Combobox"; import ControlledComboboxField from "./combobox/ControlledComboboxField"; import { defaultOptionFactory } from "./helpers"; +import ChipInput from "./headless-chip-input/ChipInput"; export type SimpleWebHookConfiguration = { urlPattern: string; @@ -430,4 +431,23 @@ storiesOf("Forms", module) - )); + )) + .add("Controlled Chip Input with add", () => { + const ref = useRef(null); + return ( +
+ + + + + Add + +
+ ); + }); diff --git a/scm-ui/ui-forms/src/base/Control.tsx b/scm-ui/ui-forms/src/base/Control.tsx index 7db727ba0c..3e9aaf2178 100644 --- a/scm-ui/ui-forms/src/base/Control.tsx +++ b/scm-ui/ui-forms/src/base/Control.tsx @@ -22,13 +22,13 @@ * SOFTWARE. */ -import React, { FC, HTMLProps } from "react"; +import React, { HTMLProps } from "react"; import classNames from "classnames"; -const Control: FC> = ({ className, children, ...rest }) => ( -
+const Control = React.forwardRef>(({ className, children, ...rest }, ref) => ( +
{children}
-); +)); export default Control; diff --git a/scm-ui/ui-forms/src/base/Field.tsx b/scm-ui/ui-forms/src/base/Field.tsx index 16e180ae94..150aa4d8fb 100644 --- a/scm-ui/ui-forms/src/base/Field.tsx +++ b/scm-ui/ui-forms/src/base/Field.tsx @@ -25,9 +25,11 @@ import React, { FC, HTMLProps } from "react"; import classNames from "classnames"; -const Field: FC> = ({ className, children, ...rest }) => ( -
- {children} -
-); +const Field: FC | ({ as: keyof JSX.IntrinsicElements } & HTMLProps)> = ({ + as = "div", + className, + children, + ...rest +}) => React.createElement(as, { className: classNames("field", className), ...rest }, children); + export default Field; diff --git a/scm-ui/ui-forms/src/base/label/Label.tsx b/scm-ui/ui-forms/src/base/label/Label.tsx index 79d468fce2..ec7faa2444 100644 --- a/scm-ui/ui-forms/src/base/label/Label.tsx +++ b/scm-ui/ui-forms/src/base/label/Label.tsx @@ -25,9 +25,11 @@ import React, { FC, HTMLProps } from "react"; import classNames from "classnames"; -const Label: FC> = ({ className, children, ...rest }) => ( - -); +const Label: FC | ({ as: keyof JSX.IntrinsicElements } & HTMLProps)> = ({ + as = "label", + className, + children, + ...rest +}) => React.createElement(as, { className: classNames("label", className), ...rest }, children); + export default Label; diff --git a/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx b/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx index df01edf28a..54fe167643 100644 --- a/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx +++ b/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx @@ -26,7 +26,7 @@ import React, { ComponentProps } from "react"; import { Controller, ControllerRenderProps, Path } from "react-hook-form"; import { useScmFormContext } from "../ScmFormContext"; import { useScmFormPathContext } from "../FormPathContext"; -import { defaultOptionFactory, prefixWithoutIndices } from "../helpers"; +import { defaultOptionFactory, prefixWithoutIndices, withForwardRef } from "../helpers"; import classNames from "classnames"; import ChipInputField from "./ChipInputField"; import { Option } from "@scm-manager/ui-types"; @@ -41,27 +41,31 @@ type Props> = Omit< defaultValue?: string[]; createDeleteText?: (value: string) => string; optionFactory?: (val: any) => Option; + ref?: React.ForwardedRef; }; /** * @beta * @since 2.44.0 */ -function ControlledChipInputField>({ - name, - label, - helpText, - rules, - testId, - defaultValue, - readOnly, - placeholder, - className, - createDeleteText, - children, - optionFactory = defaultOptionFactory, - ...props -}: Props) { +function ControlledChipInputField>( + { + name, + label, + helpText, + rules, + testId, + defaultValue, + readOnly, + placeholder, + className, + createDeleteText, + children, + optionFactory = defaultOptionFactory, + ...props + }: Props, + ref: React.ForwardedRef +) { const { control, t, readOnly: formReadonly } = useScmFormContext(); const formPathPrefix = useScmFormPathContext(); @@ -95,6 +99,7 @@ function ControlledChipInputField>({ : undefined } testId={testId ?? `input-${nameWithPrefix}`} + ref={ref} > {children} @@ -103,4 +108,4 @@ function ControlledChipInputField>({ ); } -export default ControlledChipInputField; +export default withForwardRef(ControlledChipInputField); diff --git a/scm-ui/ui-forms/src/index.ts b/scm-ui/ui-forms/src/index.ts index 3a1a844dfc..d2f2248030 100644 --- a/scm-ui/ui-forms/src/index.ts +++ b/scm-ui/ui-forms/src/index.ts @@ -38,6 +38,10 @@ import { ScmNestedFormPathContextProvider } from "./FormPathContext"; import ControlledComboboxField from "./combobox/ControlledComboboxField"; import ChipInputFieldComponent from "./chip-input/ChipInputField"; import ChipInput from "./headless-chip-input/ChipInput"; +import ControlledRadioGroupField from "./radio-button/ControlledRadioGroupField"; +import RadioGroupComponent from "./radio-button/RadioGroup"; +import RadioButton from "./radio-button/RadioButton"; +import RadioGroupFieldComponent from "./radio-button/RadioGroupField"; export { default as Field } from "./base/Field"; export { default as Checkbox } from "./checkbox/Checkbox"; @@ -51,6 +55,13 @@ export { default as Select } from "./select/Select"; export * from "./resourceHooks"; export { default as Label } from "./base/label/Label"; +const RadioGroupExport = { + Option: RadioButton, +}; + +export const RadioGroup = Object.assign(RadioGroupComponent, RadioGroupExport); +export const RadioGroupField = Object.assign(RadioGroupFieldComponent, RadioGroupExport); + export const ChipInputField = Object.assign(ChipInputFieldComponent, { AddButton: ChipInput.AddButton, }); @@ -70,4 +81,5 @@ export const Form = Object.assign(FormCmp, { }), ChipInput: ControlledChipInputField, Combobox: ControlledComboboxField, + RadioGroup: Object.assign(ControlledRadioGroupField, RadioGroupExport), }); diff --git a/scm-ui/ui-forms/src/radio-button/ControlledRadioGroupField.tsx b/scm-ui/ui-forms/src/radio-button/ControlledRadioGroupField.tsx new file mode 100644 index 0000000000..0f9a777eea --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/ControlledRadioGroupField.tsx @@ -0,0 +1,90 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { ComponentProps } from "react"; +import RadioGroupField from "./RadioGroupField"; +import { Controller, ControllerRenderProps, Path } from "react-hook-form"; +import { useScmFormContext } from "../ScmFormContext"; +import { useScmFormPathContext } from "../FormPathContext"; +import { prefixWithoutIndices } from "../helpers"; +import classNames from "classnames"; +import { RadioButtonContextProvider } from "./RadioButtonContext"; + +type Props> = Omit< + ComponentProps, + "label" | keyof ControllerRenderProps +> & { + name: Path; + rules?: ComponentProps["rules"]; + label?: string; + readOnly?: boolean; +}; + +function ControlledRadioGroupField>({ + name, + label, + helpText, + rules, + defaultValue, + children, + fieldClassName, + readOnly, + ...props +}: Props) { + const { control, t, readOnly: formReadOnly, formId } = useScmFormContext(); + const formPathPrefix = useScmFormPathContext(); + const nameWithPrefix = formPathPrefix ? `${formPathPrefix}.${name}` : name; + const prefixedNameWithoutIndices = prefixWithoutIndices(nameWithPrefix); + const labelTranslation = label ?? t(`${prefixedNameWithoutIndices}.label`) ?? ""; + const helpTextTranslation = helpText ?? t(`${prefixedNameWithoutIndices}.helpText`); + + return ( + ( + + + {children} + + + )} + /> + ); +} + +export default ControlledRadioGroupField; diff --git a/scm-ui/ui-forms/src/radio-button/RadioButton.stories.tsx b/scm-ui/ui-forms/src/radio-button/RadioButton.stories.tsx new file mode 100644 index 0000000000..0fcceb9534 --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/RadioButton.stories.tsx @@ -0,0 +1,226 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { useState } from "react"; +import { storiesOf } from "@storybook/react"; +import RadioButton from "./RadioButton"; +import RadioGroup from "./RadioGroup"; +import RadioGroupField from "./RadioGroupField"; +import Form from "../Form"; +import ControlledRadioGroupField from "./ControlledRadioGroupField"; +import ControlledInputField from "../input/ControlledInputField"; +import FormRow from "../FormRow"; +import { ScmFormListContextProvider } from "../ScmFormListContext"; +import ControlledList from "../list/ControlledList"; +import ControlledTable from "../table/ControlledTable"; +import ControlledColumn from "../table/ControlledColumn"; +import AddListEntryForm from "../AddListEntryForm"; + +storiesOf("Radio Group", module) + .add("Uncontrolled State", () => { + return ( + + + + + + ); + }) + .add("Controlled State", () => { + const [value, setValue] = useState(undefined); + return ( + + + + + + ); + }) + .add("Radio Group Field", () => { + const [value, setValue] = useState(undefined); + return ( + + + + + + ); + }) + .add("Controlled Radio Group Field", () => ( +
+ + + + + + + + + + +
+ )) + .add("Readonly Controlled Radio Group Field", () => ( +
+ + + + + + + + + + +
+ )) + .add("With options", () => ( +
+ + + +
+ )) + .add("Without label prop", () => ( +
+ + + +
+ )) + .add("Nested", () => ( +
+ + + {({ value: trainers }) => ( + <> + + + +
+ Team +
+ + + + + + + + + + + + + + +
+
+ + )} +
+
+
+ )); diff --git a/scm-ui/ui-forms/src/radio-button/RadioButton.tsx b/scm-ui/ui-forms/src/radio-button/RadioButton.tsx new file mode 100644 index 0000000000..fd191da119 --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/RadioButton.tsx @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { ComponentProps } from "react"; +import classNames from "classnames"; +import Help from "../base/help/Help"; +import * as RadioGroup from "@radix-ui/react-radio-group"; +import { createAttributesForTesting, useGeneratedId } from "@scm-manager/ui-components"; +import styled from "styled-components"; +import { useRadioButtonContext } from "./RadioButtonContext"; + +const StyledRadioButton = styled(RadioGroup.Item)` + all: unset; + width: 1rem; + height: 1rem; + border: var(--scm-border); + border-radius: 100%; + + :hover { + border-color: var(--scm-hover-color); + } + + :hover *::after { + background-color: var(--scm-info-hover-color); + } + + :disabled { + background-color: var(--scm-dark-color-25); + border-color: var(--scm-hover-color); + } + + :disabled *::after { + background-color: var(--scm-info-color); + } +`; + +const StyledIndicator = styled(RadioGroup.Indicator)` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + position: relative; + + ::after { + content: ""; + display: block; + width: 0.5rem; + height: 0.5rem; + border-radius: 50%; + background-color: var(--scm-info-color); + } +`; + +type Props = { + value: string; + id?: string; + testId?: string; + indicatorClassName?: string; + label?: string; + labelClassName?: string; + helpText?: string; +} & ComponentProps; + +const RadioButton = React.forwardRef( + ({ id, testId, indicatorClassName, label, labelClassName, className, helpText, value, ...props }, ref) => { + const context = useRadioButtonContext(); + const inputId = useGeneratedId(id); + const labelKey = `${context?.prefix}.radio.${value}`; + + return ( + + ); + } +); + +export default RadioButton; diff --git a/scm-ui/ui-forms/src/radio-button/RadioButtonContext.tsx b/scm-ui/ui-forms/src/radio-button/RadioButtonContext.tsx new file mode 100644 index 0000000000..b43b6feac5 --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/RadioButtonContext.tsx @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { createContext, FC, useContext } from "react"; +import { TFunction } from "i18next"; + +type ContextType = { + t: TFunction; + prefix: string; + formId?: string; +}; + +const RadioButtonContext = createContext(null); + +export function useRadioButtonContext() { + return useContext(RadioButtonContext); +} + +export const RadioButtonContextProvider: FC = ({ children, ...props }) => ( + {children} +); diff --git a/scm-ui/ui-forms/src/radio-button/RadioGroup.tsx b/scm-ui/ui-forms/src/radio-button/RadioGroup.tsx new file mode 100644 index 0000000000..3009ad8055 --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/RadioGroup.tsx @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { ComponentProps } from "react"; +import Control from "../base/Control"; +import * as RadixRadio from "@radix-ui/react-radio-group"; +import RadioButton from "./RadioButton"; + +type Props = { + options?: { value: string; label?: string; helpText?: string }[]; +} & ComponentProps; + +const RadioGroup = React.forwardRef(({ options, children, className, ...props }, ref) => ( + + + {children ?? + options?.map((option) => ( + + ))} + + +)); + +export default RadioGroup; diff --git a/scm-ui/ui-forms/src/radio-button/RadioGroupField.tsx b/scm-ui/ui-forms/src/radio-button/RadioGroupField.tsx new file mode 100644 index 0000000000..9df91a753e --- /dev/null +++ b/scm-ui/ui-forms/src/radio-button/RadioGroupField.tsx @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { ComponentProps } from "react"; +import Field from "../base/Field"; +import Label from "../base/label/Label"; +import Help from "../base/help/Help"; +import RadioGroup from "./RadioGroup"; + +type Props = { + fieldClassName?: string; + labelClassName?: string; + label: string; + helpText?: string; +} & ComponentProps; + +const RadioGroupField = React.forwardRef( + ({ fieldClassName, labelClassName, label, helpText, children, ...props }, ref) => { + return ( + + + + {children} + + + ); + } +); + +export default RadioGroupField; diff --git a/scm-ui/ui-styles/src/components/_main.scss b/scm-ui/ui-styles/src/components/_main.scss index a62a03bdb2..4fe95f7351 100644 --- a/scm-ui/ui-styles/src/components/_main.scss +++ b/scm-ui/ui-styles/src/components/_main.scss @@ -26,9 +26,11 @@ --scm-white-color: #{$white}; --scm-light-color: #{$light}; --scm-dark-color: #{$dark}; + --scm-dark-color-25: #{$dark-25}; --scm-primary-color: #{$primary}; --scm-link-color: #{$link}; --scm-info-color: #{$info}; + --scm-info-hover-color: #{$info-75}; --scm-success-color: #{$success}; --scm-warning-color: #{$warning}; --scm-danger-color: #{$danger}; diff --git a/yarn.lock b/yarn.lock index 32efc26b82..5cce748e40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2944,6 +2944,23 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.2" +"@radix-ui/react-radio-group@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-radio-group/-/react-radio-group-1.1.3.tgz#3197f5dcce143bcbf961471bf89320735c0212d3" + integrity sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-roving-focus" "1.0.4" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-use-previous" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/react-roving-focus@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz#e90c4a6a5f6ac09d3b8c1f5b5e81aab2f0db1974" @@ -3070,6 +3087,13 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-previous@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz#b595c087b07317a4f143696c6a01de43b0d0ec66" + integrity sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-rect@1.0.0": version "1.0.0" resolved "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz"