aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/molecules/forms/labelled-boolean-field.tsx
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-06-01 22:37:56 +0200
committerGitHub <noreply@github.com>2022-06-01 22:37:56 +0200
commit0a33a4658d848fe056715c6da053763407845b2a (patch)
tree7c679e54ba4bbadaf0a59bbde780f5742e3b875d /src/components/molecules/forms/labelled-boolean-field.tsx
parent97031a86ca38890e60ecec79828498b7bb13cbfa (diff)
parent6be20422494e3806fba3d1c5ad5c3e98bd6e67e5 (diff)
chore(a11y): improve website settings accessibility (#17)
The previous switch buttons (using checkbox) was not a11y compliant. So I change my approach to use radio buttons and to clearly separate the two different states. I also convert the Ackee select setting to improve consistency between settings.
Diffstat (limited to 'src/components/molecules/forms/labelled-boolean-field.tsx')
-rw-r--r--src/components/molecules/forms/labelled-boolean-field.tsx92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/components/molecules/forms/labelled-boolean-field.tsx b/src/components/molecules/forms/labelled-boolean-field.tsx
new file mode 100644
index 0000000..46eb080
--- /dev/null
+++ b/src/components/molecules/forms/labelled-boolean-field.tsx
@@ -0,0 +1,92 @@
+import BooleanField, {
+ type BooleanFieldProps,
+} from '@components/atoms/forms/boolean-field';
+import Label, { type LabelProps } from '@components/atoms/forms/label';
+import { FC } from 'react';
+import styles from './labelled-boolean-field.module.scss';
+
+export type LabelledBooleanFieldProps = Omit<
+ BooleanFieldProps,
+ 'aria-labelledby' | 'className'
+> & {
+ /**
+ * Set additional classnames to the labelled field wrapper.
+ */
+ className?: string;
+ /**
+ * Set additional classnames to the field.
+ */
+ fieldClassName?: LabelledBooleanFieldProps['className'];
+ /**
+ * The field label.
+ */
+ label: LabelProps['children'];
+ /**
+ * Set additional classnames to the label.
+ */
+ labelClassName?: LabelProps['className'];
+ /**
+ * The label position. Default: left.
+ */
+ labelPosition?: 'left' | 'right';
+ /**
+ * The label size.
+ */
+ labelSize?: LabelProps['size'];
+};
+
+/**
+ * LabelledBooleanField component
+ *
+ * Render a checkbox or radio button with a label.
+ */
+const LabelledBooleanField: FC<LabelledBooleanFieldProps> = ({
+ className = '',
+ fieldClassName,
+ hidden,
+ id,
+ label,
+ labelClassName,
+ labelPosition = 'left',
+ labelSize,
+ ...props
+}) => {
+ const labelHiddenModifier = hidden ? 'label--hidden' : 'label--visible';
+ const labelPositionModifier = `label--${labelPosition}`;
+
+ return labelPosition === 'left' ? (
+ <span className={`${styles.wrapper} ${className}`}>
+ <Label
+ className={`${styles[labelPositionModifier]} ${styles[labelHiddenModifier]} ${labelClassName}`}
+ htmlFor={id}
+ size={labelSize}
+ >
+ {label}
+ </Label>
+ <BooleanField
+ className={fieldClassName}
+ hidden={hidden}
+ id={id}
+ {...props}
+ />
+ </span>
+ ) : (
+ <span className={`${styles.wrapper} ${className}`}>
+ <BooleanField
+ className={fieldClassName}
+ hidden={hidden}
+ id={id}
+ {...props}
+ />
+ <Label
+ className={`${styles[labelPositionModifier]} ${styles[labelHiddenModifier]} ${labelClassName}`}
+ htmlFor={id}
+ size={labelSize}
+ >
+ {label}
+ </Label>
+ </span>
+ );
+};
+
+export default LabelledBooleanField;