From 21eb67ef5e59d36b996392f60b5045f152a64604 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 22:57:12 +0200 Subject: chore: add a labelled select field component --- src/components/atoms/forms/select.stories.tsx | 10 +- src/components/atoms/forms/select.tsx | 6 +- .../molecules/forms/labelled-select.stories.tsx | 127 +++++++++++++++++++++ .../molecules/forms/labelled-select.test.tsx | 25 ++++ src/components/molecules/forms/labelled-select.tsx | 25 ++++ 5 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 src/components/molecules/forms/labelled-select.stories.tsx create mode 100644 src/components/molecules/forms/labelled-select.test.tsx create mode 100644 src/components/molecules/forms/labelled-select.tsx (limited to 'src') diff --git a/src/components/atoms/forms/select.stories.tsx b/src/components/atoms/forms/select.stories.tsx index 683e3b5..ed487f8 100644 --- a/src/components/atoms/forms/select.stories.tsx +++ b/src/components/atoms/forms/select.stories.tsx @@ -30,12 +30,9 @@ export default { type: 'text', }, description: 'Field id.', - table: { - category: 'Options', - }, type: { name: 'string', - required: false, + required: true, }, }, name: { @@ -43,12 +40,9 @@ export default { type: 'text', }, description: 'Field name.', - table: { - category: 'Options', - }, type: { name: 'string', - required: false, + required: true, }, }, options: { diff --git a/src/components/atoms/forms/select.tsx b/src/components/atoms/forms/select.tsx index 6e46660..e434a82 100644 --- a/src/components/atoms/forms/select.tsx +++ b/src/components/atoms/forms/select.tsx @@ -7,7 +7,7 @@ type SelectOptions = { value: string; }; -type SelectProps = { +export type SelectProps = { /** * Field state. Either enabled (false) or disabled (true). */ @@ -15,11 +15,11 @@ type SelectProps = { /** * Field id attribute. */ - id?: string; + id: string; /** * Field name attribute. */ - name?: string; + name: string; /** * True if the field is required. Default: false. */ diff --git a/src/components/molecules/forms/labelled-select.stories.tsx b/src/components/molecules/forms/labelled-select.stories.tsx new file mode 100644 index 0000000..0966e13 --- /dev/null +++ b/src/components/molecules/forms/labelled-select.stories.tsx @@ -0,0 +1,127 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import LabelledSelectComponent from './labelled-select'; + +const selectOptions = [ + { id: 'option1', name: 'Option 1', value: 'option1' }, + { id: 'option2', name: 'Option 2', value: 'option2' }, + { id: 'option3', name: 'Option 3', value: 'option3' }, +]; + +export default { + title: 'Molecules/Forms', + component: LabelledSelectComponent, + args: { + disabled: false, + required: false, + }, + argTypes: { + disabled: { + control: { + type: 'boolean', + }, + description: 'Field state: either enabled or disabled.', + table: { + category: 'Options', + defaultValue: { summary: false }, + }, + type: { + name: 'boolean', + required: false, + }, + }, + id: { + control: { + type: 'text', + }, + description: 'Field id.', + type: { + name: 'string', + required: true, + }, + }, + label: { + control: { + type: 'text', + }, + description: 'Field label.', + type: { + name: 'string', + required: true, + }, + }, + name: { + control: { + type: 'text', + }, + description: 'Field name.', + type: { + name: 'string', + required: true, + }, + }, + options: { + control: { + type: null, + }, + description: 'Select options.', + type: { + name: 'array', + required: true, + value: { + name: 'string', + }, + }, + }, + required: { + control: { + type: 'boolean', + }, + description: 'Determine if the field is required.', + table: { + category: 'Options', + defaultValue: { summary: false }, + }, + type: { + name: 'boolean', + required: false, + }, + }, + setValue: { + control: { + type: null, + }, + description: 'Callback function to set field value.', + table: { + category: 'Events', + }, + type: { + name: 'function', + required: true, + }, + }, + value: { + control: { + type: 'text', + }, + description: 'Field value.', + type: { + name: 'string', + required: true, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const LabelledSelect = Template.bind({}); +LabelledSelect.args = { + id: 'labelled-select-storybook', + label: 'Labelled select', + name: 'labelled-select-storybook', + options: selectOptions, + setValue: () => null, + value: '', +}; diff --git a/src/components/molecules/forms/labelled-select.test.tsx b/src/components/molecules/forms/labelled-select.test.tsx new file mode 100644 index 0000000..9a50d6e --- /dev/null +++ b/src/components/molecules/forms/labelled-select.test.tsx @@ -0,0 +1,25 @@ +import { render, screen } from '@test-utils'; +import LabelledSelect from './labelled-select'; + +const selectOptions = [ + { id: 'option1', name: 'Option 1', value: 'option1' }, + { id: 'option2', name: 'Option 2', value: 'option2' }, + { id: 'option3', name: 'Option 3', value: 'option3' }, +]; + +describe('LabelledSelect', () => { + it('renders a labelled select', () => { + render( + null} + /> + ); + expect(screen.getByLabelText('Jest select field')).toBeInTheDocument(); + expect(screen.getByRole('combobox')).toHaveValue('option1'); + }); +}); diff --git a/src/components/molecules/forms/labelled-select.tsx b/src/components/molecules/forms/labelled-select.tsx new file mode 100644 index 0000000..442e91a --- /dev/null +++ b/src/components/molecules/forms/labelled-select.tsx @@ -0,0 +1,25 @@ +import Label from '@components/atoms/forms/label'; +import Select, { type SelectProps } from '@components/atoms/forms/select'; +import { FC } from 'react'; + +type LabelledSelectProps = SelectProps & { + label: string; +}; + +const LabelledSelect: FC = ({ + id, + label, + required, + ...props +}) => { + return ( + <> + +