From a6ff5eee45215effb3344cb5d631a27a7c0369aa Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Fri, 22 Sep 2023 19:34:01 +0200
Subject: refactor(components): rewrite form components

---
 .../molecules/forms/radio-group/radio-group.tsx    | 110 +++++++++++++++++++++
 1 file changed, 110 insertions(+)
 create mode 100644 src/components/molecules/forms/radio-group/radio-group.tsx

(limited to 'src/components/molecules/forms/radio-group/radio-group.tsx')

diff --git a/src/components/molecules/forms/radio-group/radio-group.tsx b/src/components/molecules/forms/radio-group/radio-group.tsx
new file mode 100644
index 0000000..0ca4dac
--- /dev/null
+++ b/src/components/molecules/forms/radio-group/radio-group.tsx
@@ -0,0 +1,110 @@
+import { ForwardRefRenderFunction, forwardRef } from 'react';
+import {
+  Fieldset,
+  FieldsetProps,
+  Label,
+  LabelProps,
+  Radio,
+  RadioProps,
+} from '../../../atoms';
+import { LabelledField } from '../labelled-field';
+import styles from './radio-group.module.scss';
+
+export type RadioGroupItem = {
+  /**
+   * The item id.
+   */
+  id: string;
+  /**
+   * Should the item be disabled?
+   */
+  isDisabled?: boolean;
+  /**
+   * The item label.
+   */
+  label: LabelProps['children'];
+  /**
+   * The item value.
+   */
+  value: string;
+};
+
+export type RadioGroupProps = Omit<FieldsetProps, 'children' | 'role'> & {
+  /**
+   * Should we display the radio buttons inlined?
+   *
+   * @default false
+   */
+  isInline?: boolean;
+  /**
+   * The radio group name.
+   */
+  name: string;
+  /**
+   * A function to handle selection change.
+   */
+  onSwitch?: RadioProps['onChange'];
+  /**
+   * The options.
+   */
+  options: RadioGroupItem[];
+  /**
+   * The selected value. It should match a RadioGroupItem value or be undefined.
+   */
+  value?: RadioGroupItem['value'];
+};
+
+const RadioGroupWithRef: ForwardRefRenderFunction<
+  HTMLFieldSetElement,
+  RadioGroupProps
+> = (
+  {
+    className = '',
+    isInline = false,
+    name,
+    onSwitch,
+    options,
+    value,
+    ...props
+  },
+  ref
+) => {
+  const layoutModifier = isInline ? styles['group--inline'] : '';
+  const groupClass = `${layoutModifier} ${className}`;
+
+  return (
+    <Fieldset
+      {...props}
+      className={groupClass}
+      isInline={isInline}
+      ref={ref}
+      role="radiogroup"
+    >
+      {options.map((option) => (
+        <LabelledField
+          className={styles.option}
+          field={
+            <Radio
+              id={option.id}
+              isChecked={value === option.value}
+              name={name}
+              onChange={onSwitch}
+              value={option.value}
+            />
+          }
+          isInline
+          isReversedOrder
+          key={option.id}
+          label={<Label htmlFor={option.id}>{option.label}</Label>}
+        />
+      ))}
+    </Fieldset>
+  );
+};
+
+/**
+ * RadioGroup component
+ *
+ * Render a group of labelled radio buttons.
+ */
+export const RadioGroup = forwardRef(RadioGroupWithRef);
-- 
cgit v1.2.3

