Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Field): cleanup stories and position prop #2931

Merged
merged 3 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/poor-roses-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@digdir/designsystemet-react": patch
---

Field: Fix `position` not working
112 changes: 48 additions & 64 deletions packages/react/src/components/Field/Field.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import type { Meta, StoryFn } from '@storybook/react';

import { useEffect } from 'react';
import { Label } from '../Label';

import { Field } from '.';
import { Input } from '../Input';
import { Select } from '../Select';
import { Textarea } from '../Textarea';
import { ValidationMessage } from '../ValidationMessage';
import {
Field,
Fieldset,
Input,
Select,
Textarea,
ValidationMessage,
} from '../';

type Story = StoryFn<typeof Field>;

export default {
title: 'Komponenter/Field',
component: Field,
argTypes: {
type: {
control: { type: 'radio' },
options: ['textarea', 'input', 'select', false],
mapping: { textarea: Textarea, input: Input, select: Select },
},
},
parameters: {
customStyles: {
maxWidth: 600,
Expand All @@ -29,63 +23,17 @@ export default {
},
} as Meta;

// TMP toggles to test a11yField utility
const toggles = {
type: 'textarea',
inputId: '',
label: true,
labelFor: '',
description: true,
descriptionId: '',
validation: true,
validationId: '',
moveToBody: false,
};

export const Preview: Story = (args) => {
const {
type,
inputId,
label,
labelFor,
description,
descriptionId,
validation,
validationId,
moveToBody,
} = args as typeof toggles;
const Component = type as keyof JSX.IntrinsicElements;

useEffect(() => {
const label = document.querySelector('label');
const valid = document.querySelector('[data-my-validation]');
const field = document.querySelector('[data-my-field]');
const root = moveToBody ? document.body : field;
if (valid && valid.parentElement !== root) root?.append(valid);
if (label && label.parentElement !== root) root?.prepend(label);
}, [moveToBody]);

return (
<Field data-my-field>
{label && <Label htmlFor={labelFor || undefined}>Kort beskrivelse</Label>}
{description && (
<Field.Description id={descriptionId || undefined}>
Beskrivelse
</Field.Description>
)}
{type && <Component id={inputId || undefined} />}
{validation && (
<ValidationMessage data-my-validation id={validationId || undefined}>
Feilmelding
</ValidationMessage>
)}
<Label>Kort beskrivelse</Label>
<Field.Description>Beskrivelse</Field.Description>
<Input />
<ValidationMessage>Feilmelding</ValidationMessage>
</Field>
);
};

// @ts-expect-error ts2559: Preview.args uses more properties for testing than what is supported by <Field>
Preview.args = toggles;

export const Affix: Story = () => (
<div>
<Field>
Expand Down Expand Up @@ -166,3 +114,39 @@ export const Counter: Story = () => (
<Field.Counter limit={10} />
</Field>
);

export const Position: Story = () => (
<>
<Fieldset>
<Fieldset.Legend>Fields with position="start"</Fieldset.Legend>
<Field position='start'>
<Label>Radio</Label>
<Input type='radio' />
</Field>
<Field position='start'>
<Label>Checkbox</Label>
<Input type='checkbox' />
</Field>
<Field position='start'>
<Label>Switch</Label>
<Input type='checkbox' role='switch' />
</Field>
</Fieldset>
<br />
<Fieldset>
<Fieldset.Legend>Fields with position="end"</Fieldset.Legend>
<Field position='end'>
<Label>Radio</Label>
<Input type='radio' />
</Field>
<Field position='end'>
<Label>Checkbox</Label>
<Input type='checkbox' />
</Field>
<Field position='end'>
<Label>Switch</Label>
<Input type='checkbox' role='switch' />
</Field>
</Fieldset>
</>
);
9 changes: 7 additions & 2 deletions packages/react/src/components/Field/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ export type FieldProps = {
DefaultProps;

export const Field = forwardRef<HTMLDivElement, FieldProps>(function Field(
{ className, ...rest },
{ className, position, ...rest },
ref,
) {
const fieldRef = useRef<HTMLDivElement>(null);
const mergedRefs = useMergeRefs([fieldRef, ref]);
useEffect(() => fieldObserver(fieldRef.current), []);

return (
<div className={cl('ds-field', className)} ref={mergedRefs} {...rest} />
<div
className={cl('ds-field', className)}
data-position={position}
ref={mergedRefs}
{...rest}
/>
);
});
Loading