aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/atoms/forms/fieldset
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/atoms/forms/fieldset')
-rw-r--r--src/components/atoms/forms/fieldset/fieldset.module.scss17
-rw-r--r--src/components/atoms/forms/fieldset/fieldset.stories.tsx63
-rw-r--r--src/components/atoms/forms/fieldset/fieldset.test.tsx35
-rw-r--r--src/components/atoms/forms/fieldset/fieldset.tsx68
-rw-r--r--src/components/atoms/forms/fieldset/index.ts1
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';