aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/atoms/forms/fields/boolean-field
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/atoms/forms/fields/boolean-field')
-rw-r--r--src/components/atoms/forms/fields/boolean-field/boolean-field.module.scss7
-rw-r--r--src/components/atoms/forms/fields/boolean-field/boolean-field.stories.tsx175
-rw-r--r--src/components/atoms/forms/fields/boolean-field/boolean-field.test.tsx36
-rw-r--r--src/components/atoms/forms/fields/boolean-field/boolean-field.tsx86
-rw-r--r--src/components/atoms/forms/fields/boolean-field/index.ts1
5 files changed, 305 insertions, 0 deletions
diff --git a/src/components/atoms/forms/fields/boolean-field/boolean-field.module.scss b/src/components/atoms/forms/fields/boolean-field/boolean-field.module.scss
new file mode 100644
index 0000000..7e13e43
--- /dev/null
+++ b/src/components/atoms/forms/fields/boolean-field/boolean-field.module.scss
@@ -0,0 +1,7 @@
+@use "../../../../../styles/abstracts/mixins" as mix;
+
+.field {
+ &--hidden {
+ @include mix.visually-hidden;
+ }
+}
diff --git a/src/components/atoms/forms/fields/boolean-field/boolean-field.stories.tsx b/src/components/atoms/forms/fields/boolean-field/boolean-field.stories.tsx
new file mode 100644
index 0000000..cb017da
--- /dev/null
+++ b/src/components/atoms/forms/fields/boolean-field/boolean-field.stories.tsx
@@ -0,0 +1,175 @@
+import { ComponentMeta, ComponentStory } from '@storybook/react';
+import { useState } from 'react';
+import { BooleanField } from './boolean-field';
+
+/**
+ * BooleanField - Storybook Meta
+ */
+export default {
+ title: 'Atoms/Forms/Fields',
+ component: BooleanField,
+ args: {
+ isHidden: false,
+ },
+ argTypes: {
+ 'aria-labelledby': {
+ control: {
+ type: 'text',
+ },
+ description: 'One or more ids that refers to the field name.',
+ table: {
+ category: 'Accessibility',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
+ className: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the field.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
+ id: {
+ control: {
+ type: 'text',
+ },
+ description: 'The field id.',
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ isChecked: {
+ control: {
+ type: null,
+ },
+ description: 'The field state: true if checked.',
+ type: {
+ name: 'boolean',
+ required: true,
+ },
+ },
+ isHidden: {
+ control: {
+ type: 'boolean',
+ },
+ description: 'Define if the field should be visually hidden.',
+ table: {
+ category: 'Options',
+ defaultValue: { summary: false },
+ },
+ type: {
+ name: 'boolean',
+ required: false,
+ },
+ },
+ name: {
+ control: {
+ type: 'text',
+ },
+ description: 'The field name.',
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ onChange: {
+ control: {
+ type: null,
+ },
+ description: 'A callback function to handle field state change.',
+ table: {
+ category: 'Events',
+ },
+ type: {
+ name: 'function',
+ required: true,
+ },
+ },
+ onClick: {
+ control: {
+ type: null,
+ },
+ description: 'A callback function to handle click on field.',
+ table: {
+ category: 'Events',
+ },
+ type: {
+ name: 'function',
+ required: false,
+ },
+ },
+ type: {
+ control: {
+ type: 'select',
+ },
+ description: 'The field type. Either checkbox or radio.',
+ options: ['checkbox', 'radio'],
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ value: {
+ control: {
+ type: 'text',
+ },
+ description: 'The field value.',
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ },
+} as ComponentMeta<typeof BooleanField>;
+
+const Template: ComponentStory<typeof BooleanField> = ({
+ isChecked: checked,
+ onChange: _onChange,
+ ...args
+}) => {
+ const [isChecked, setIsChecked] = useState(checked);
+
+ return (
+ <BooleanField
+ isChecked={isChecked}
+ onChange={() => {
+ setIsChecked(!isChecked);
+ }}
+ {...args}
+ />
+ );
+};
+
+/**
+ * Checkbox Story
+ */
+export const Checkbox = Template.bind({});
+Checkbox.args = {
+ id: 'checkbox',
+ isChecked: false,
+ name: 'checkbox',
+ type: 'checkbox',
+ value: 'checkbox',
+};
+
+/**
+ * Radio Story
+ */
+export const Radio = Template.bind({});
+Radio.args = {
+ id: 'radio',
+ isChecked: false,
+ name: 'radio',
+ type: 'radio',
+ value: 'radio',
+};
diff --git a/src/components/atoms/forms/fields/boolean-field/boolean-field.test.tsx b/src/components/atoms/forms/fields/boolean-field/boolean-field.test.tsx
new file mode 100644
index 0000000..fcd15ad
--- /dev/null
+++ b/src/components/atoms/forms/fields/boolean-field/boolean-field.test.tsx
@@ -0,0 +1,36 @@
+import { render, screen } from '../../../../../../tests/utils';
+import { BooleanField } from './boolean-field';
+
+const handleChange = () => {
+ /**
+ * Do nothing.
+ */
+};
+
+describe('boolean field', () => {
+ it('renders a checkbox', () => {
+ render(
+ <BooleanField
+ id="checkbox"
+ name="checkbox"
+ onChange={handleChange}
+ type="checkbox"
+ value="checkbox"
+ />
+ );
+ expect(screen.getByRole('checkbox')).toBeInTheDocument();
+ });
+
+ it('renders a radio button', () => {
+ render(
+ <BooleanField
+ id="radio"
+ name="radio"
+ onChange={handleChange}
+ type="radio"
+ value="checkbox"
+ />
+ );
+ expect(screen.getByRole('radio')).toBeInTheDocument();
+ });
+});
diff --git a/src/components/atoms/forms/fields/boolean-field/boolean-field.tsx b/src/components/atoms/forms/fields/boolean-field/boolean-field.tsx
new file mode 100644
index 0000000..7985c0b
--- /dev/null
+++ b/src/components/atoms/forms/fields/boolean-field/boolean-field.tsx
@@ -0,0 +1,86 @@
+import { FC, InputHTMLAttributes } from 'react';
+import styles from './boolean-field.module.scss';
+
+export type BooleanFieldProps = Omit<
+ InputHTMLAttributes<HTMLInputElement>,
+ | 'checked'
+ | 'disabled'
+ | 'hidden'
+ | 'name'
+ | 'readOnly'
+ | 'required'
+ | 'type'
+ | 'value'
+> & {
+ /**
+ * Should the field be checked?
+ *
+ * @default false
+ */
+ isChecked?: boolean;
+ /**
+ * Should the field be disabled?
+ *
+ * @default false
+ */
+ isDisabled?: boolean;
+ /**
+ * Should the field be visually hidden?
+ *
+ * @default false
+ */
+ isHidden?: boolean;
+ /**
+ * Should the field be readonly?
+ *
+ * @default false
+ */
+ isReadOnly?: boolean;
+ /**
+ * Should the field be required?
+ *
+ * @default false
+ */
+ isRequired?: boolean;
+ /**
+ * Field name attribute.
+ */
+ name: string;
+ /**
+ * The input type.
+ */
+ type: 'checkbox' | 'radio';
+ /**
+ * Field name attribute.
+ */
+ value: string;
+};
+
+/**
+ * BooleanField component
+ *
+ * Render a checkbox or a radio input type.
+ */
+export const BooleanField: FC<BooleanFieldProps> = ({
+ className = '',
+ isChecked = false,
+ isDisabled = false,
+ isHidden = false,
+ isReadOnly = false,
+ isRequired = false,
+ ...props
+}) => {
+ const visibilityClass = isHidden ? styles['field--hidden'] : '';
+ const inputClass = `${visibilityClass} ${className}`;
+
+ return (
+ <input
+ {...props}
+ checked={isChecked}
+ className={inputClass}
+ disabled={isDisabled}
+ readOnly={isReadOnly}
+ required={isRequired}
+ />
+ );
+};
diff --git a/src/components/atoms/forms/fields/boolean-field/index.ts b/src/components/atoms/forms/fields/boolean-field/index.ts
new file mode 100644
index 0000000..a49d77b
--- /dev/null
+++ b/src/components/atoms/forms/fields/boolean-field/index.ts
@@ -0,0 +1 @@
+export * from './boolean-field';