diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-09-22 19:34:01 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-10-24 12:23:48 +0200 |
| commit | a6ff5eee45215effb3344cb5d631a27a7c0369aa (patch) | |
| tree | 5051747acf72318b4fc5c18d603e3757fbefdfdb /src/components/atoms/forms/fieldset | |
| parent | 651ea4fc992e77d2f36b3c68f8e7a70644246067 (diff) | |
refactor(components): rewrite form components
Diffstat (limited to 'src/components/atoms/forms/fieldset')
5 files changed, 184 insertions, 0 deletions
diff --git a/src/components/atoms/forms/fieldset/fieldset.module.scss b/src/components/atoms/forms/fieldset/fieldset.module.scss new file mode 100644 index 0000000..ed545a7 --- /dev/null +++ b/src/components/atoms/forms/fieldset/fieldset.module.scss @@ -0,0 +1,17 @@ +.fieldset { + display: flex; + gap: var(--spacing-2xs); + max-width: 100%; + margin: 0; + padding: 0; + border: none; + + &--inline { + flex-flow: row wrap; + align-items: center; + } + + &--stack { + flex-flow: column wrap; + } +} diff --git a/src/components/atoms/forms/fieldset/fieldset.stories.tsx b/src/components/atoms/forms/fieldset/fieldset.stories.tsx new file mode 100644 index 0000000..faf355f --- /dev/null +++ b/src/components/atoms/forms/fieldset/fieldset.stories.tsx @@ -0,0 +1,63 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Fieldset as FieldsetComponent } from './fieldset'; +import { Input } from '../fields'; +import { Legend } from '../legend'; + +/** + * Fieldset - Storybook Meta + */ +export default { + title: 'Atoms/Forms', + component: FieldsetComponent, + args: { + isDisabled: false, + }, + argTypes: { + isDisabled: { + control: { + type: 'boolean', + }, + description: + 'Define if the fields inside the fieldset should be disabled.', + table: { + category: 'Options', + defaultValue: { summary: false }, + }, + type: { + name: 'boolean', + required: false, + }, + }, + }, +} as ComponentMeta<typeof FieldsetComponent>; + +const Template: ComponentStory<typeof FieldsetComponent> = (args) => { + return ( + <FieldsetComponent {...args}> + <div> + <Input + aria-label="A field example" + id="field1" + name="field1" + type="text" + /> + </div> + <div> + <Input + aria-label="Another field example" + id="field2" + name="field2" + type="text" + /> + </div> + </FieldsetComponent> + ); +}; + +/** + * Fieldset Story + */ +export const Fieldset = Template.bind({}); +Fieldset.args = { + legend: <Legend>The fieldset legend</Legend>, +}; diff --git a/src/components/atoms/forms/fieldset/fieldset.test.tsx b/src/components/atoms/forms/fieldset/fieldset.test.tsx new file mode 100644 index 0000000..08a0aaa --- /dev/null +++ b/src/components/atoms/forms/fieldset/fieldset.test.tsx @@ -0,0 +1,35 @@ +import { render, screen } from '../../../../../tests/utils'; +import { Input } from '../fields'; +import { Fieldset } from './fieldset'; + +describe('fieldset', () => { + it('renders a fieldset', () => { + render( + <Fieldset> + <Input + aria-label="A field example" + id="field" + name="field" + type="text" + /> + </Fieldset> + ); + expect(screen.getByRole('group')).toBeInTheDocument(); + expect(screen.getByRole('textbox')).not.toBeDisabled(); + }); + + it('renders a disabled fieldset', () => { + render( + <Fieldset isDisabled> + <Input + aria-label="A field example" + id="field" + name="field" + type="text" + /> + </Fieldset> + ); + expect(screen.getByRole('group')).toBeInTheDocument(); + expect(screen.getByRole('textbox')).toBeDisabled(); + }); +}); diff --git a/src/components/atoms/forms/fieldset/fieldset.tsx b/src/components/atoms/forms/fieldset/fieldset.tsx new file mode 100644 index 0000000..eb42961 --- /dev/null +++ b/src/components/atoms/forms/fieldset/fieldset.tsx @@ -0,0 +1,68 @@ +import { + forwardRef, + type FieldsetHTMLAttributes, + ForwardRefRenderFunction, + ReactElement, +} from 'react'; +import styles from './fieldset.module.scss'; +import { LegendProps } from '../legend'; + +export type FieldsetProps = Omit< + FieldsetHTMLAttributes<HTMLFieldSetElement>, + 'disabled' | 'hidden' +> & { + /** + * Should the fieldset be disabled? + * + * @default false + */ + isDisabled?: boolean; + /** + * Should the fieldset contents be inlined? + * + * @default false + */ + isInline?: boolean; + /** + * The fieldset legend. + */ + legend?: ReactElement<LegendProps>; +}; + +/** + * Fieldset component. + */ +const FieldsetWithRef: ForwardRefRenderFunction< + HTMLFieldSetElement, + FieldsetProps +> = ( + { + children, + className = '', + isDisabled = false, + isInline = false, + legend, + ...props + }, + ref +) => { + const layoutModifier = isInline + ? styles['fieldset--inline'] + : styles['fieldset--stack']; + const legendModifier = legend ? styles['fieldset--has-legend'] : ''; + const fieldsetClass = `${styles.fieldset} ${legendModifier} ${layoutModifier} ${className}`; + + return ( + <fieldset + {...props} + className={fieldsetClass} + disabled={isDisabled} + ref={ref} + > + {legend} + {children} + </fieldset> + ); +}; + +export const Fieldset = forwardRef(FieldsetWithRef); diff --git a/src/components/atoms/forms/fieldset/index.ts b/src/components/atoms/forms/fieldset/index.ts new file mode 100644 index 0000000..00ef1f8 --- /dev/null +++ b/src/components/atoms/forms/fieldset/index.ts @@ -0,0 +1 @@ +export * from './fieldset'; |
