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

Improve edit component structure #110

Merged
merged 18 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7b4067a
stub stories for fieldset view component
danielnaab Apr 16, 2024
0eda5cd
Merge remote-tracking branch 'origin/main' into section-styling
danielnaab Apr 17, 2024
989483b
Stub out fieldset edit form
danielnaab Apr 18, 2024
c41a21d
Move edit components from design/config to design/FormManager/FormEdi…
danielnaab Apr 18, 2024
dd123a7
Move pattern view components from design/config/view to design/form/c…
danielnaab Apr 18, 2024
b132dd6
Add edit actions to paragraph and fieldset edit components
danielnaab Apr 18, 2024
7b230e5
Refactoring of components, for reference. Going to revert this and do…
danielnaab Apr 18, 2024
8958073
Revert "Refactoring of components, for reference. Going to revert thi…
danielnaab Apr 18, 2024
24c605d
Switch PatternEdit to work on a specific pattern, rather than just th…
danielnaab Apr 18, 2024
f7df5c3
Remove close button on inline pattern edit forms, and save on input i…
danielnaab Apr 19, 2024
f9c9ef3
Merge PatternEdit into PreviewPattern.
danielnaab Apr 19, 2024
346a68b
Simplify merged component
danielnaab Apr 19, 2024
bb3a042
Remove currently-unused bits
danielnaab Apr 19, 2024
1da03c6
Save form edit onBlur instead of onInput
danielnaab Apr 19, 2024
0bba187
Use PatternEditLayout in all the edit components, for a consistent wa…
danielnaab Apr 19, 2024
2879a0b
Don't use a layout for form behavior; have an explicit form component…
danielnaab Apr 19, 2024
bfeb9f8
Stub in an "empty state" for the fieldset preview, where we can slot …
danielnaab Apr 19, 2024
4f620bf
Type PatternEditComponent with component prop rather than a pattern t…
danielnaab Apr 19, 2024
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
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import classNames from 'classnames';
import React from 'react';
import { useFormContext } from 'react-hook-form';

import { type PatternComponent } from '../../../Form';
import { AddressComponentProps } from '@atj/forms/src/patterns/address';
import classNames from 'classnames';

import { type PatternComponent } from '../..';

const Address: PatternComponent<AddressComponentProps> = props => {
const { register } = useFormContext();
Expand Down
25 changes: 25 additions & 0 deletions packages/design/src/Form/components/Fieldset/Fieldset.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Meta, StoryObj } from '@storybook/react';

import Fieldset from '.';

export default {
title: 'patterns/Fieldset',
component: Fieldset,
tags: ['autodocs'],
} satisfies Meta<typeof Fieldset>;

export const FieldsetSection1 = {
args: {
legend: 'Section 1',
type: 'fieldset',
_patternId: 'test-id',
},
} satisfies StoryObj<typeof Fieldset>;

export const FieldsetSection2 = {
args: {
legend: 'Section 2',
type: 'fieldset',
_patternId: 'test-id',
},
} satisfies StoryObj<typeof Fieldset>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @vitest-environment jsdom
*/
import { describeStories } from '../../../test-helper';
import meta, * as stories from './Fieldset.stories';

describeStories(meta.title, stories);
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { type ComponentForPattern } from '..';

import Address from './Address';
import Fieldset from './Fieldset';
import FormSummary from './FormSummary';
import Paragraph from './Paragraph';
import Sequence from './Sequence';
import SubmissionConfirmation from './SubmissionConfirmation';
import TextInput from './TextInput';
import { type ComponentForPattern } from '../../Form';

export const defaultPatternComponents: ComponentForPattern = {
address: Address,
Expand Down
7 changes: 0 additions & 7 deletions packages/design/src/FormManager/FormEdit/FormEdit.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,6 @@ const editFieldLabel = async (
await userEvent.clear(input);
await userEvent.type(input, updatedLabel);

// Save the field to the form
await userEvent.click(
canvas.getByRole('button', {
name: 'Exit editing mode for this pattern',
})
);

waitFor(
async () => {
const newLabel = await canvas.getByLabelText(updatedLabel);
Expand Down
57 changes: 0 additions & 57 deletions packages/design/src/FormManager/FormEdit/PatternEdit.tsx

This file was deleted.

17 changes: 2 additions & 15 deletions packages/design/src/FormManager/FormEdit/PatternEditActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,7 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
})}
>
<button
aria-label="Exit editing mode for this pattern"
title="Exit editing mode for this pattern"
className="usa-button--outline usa-button--unstyled"
>
<svg
className="usa-icon usa-icon--size-3 margin-1"
style={{ verticalAlign: 'middle' }}
aria-hidden="true"
focusable="false"
role="img"
>
<use xlinkHref={`${context.uswdsRoot}img/sprite.svg#close`}></use>
</svg>
</button>
<button
type="button"
aria-label="Delete this pattern"
title="Delete this pattern"
className="usa-button--outline usa-button--unstyled"
Expand All @@ -60,6 +46,7 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
</svg>
</button>
<button
type="button"
aria-label="Create a copy of this pattern"
title="Create a copy of this pattern"
className="usa-button--outline usa-button--unstyled"
Expand Down
43 changes: 43 additions & 0 deletions packages/design/src/FormManager/FormEdit/PatternEditForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { FormProvider, useForm, useFormContext } from 'react-hook-form';

import { type PatternId, type PatternMap } from '@atj/forms';

import { useFormEditStore, usePattern } from './store';

type PatternEditFormProps = {
patternId: PatternId;
editComponent: React.ReactNode;
};

export const PatternEditForm = ({
patternId,
editComponent,
}: PatternEditFormProps) => {
const { updatePatternById } = useFormEditStore(state => ({
updatePatternById: state.updatePatternById,
}));
const pattern = usePattern(patternId);
const methods = useForm<PatternMap>({
defaultValues: {
[patternId]: pattern,
},
});
return (
<FormProvider {...methods}>
<form
onBlur={methods.handleSubmit(formData => {
updatePatternById(pattern.id, formData);
})}
>
<div className="border-1 radius-md border-primary-light padding-1">
{editComponent}
</div>
</form>
</FormProvider>
);
};

export const usePatternEditFormContext = () => {
return useFormContext<PatternMap>();
};
29 changes: 14 additions & 15 deletions packages/design/src/FormManager/FormEdit/PreviewPattern.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,31 @@ import React from 'react';

import { PatternComponent } from '../../Form';
import { useFormEditStore } from './store';
import { PatternEdit } from './PatternEdit';

export const PreviewPattern: PatternComponent = function PreviewPattern(props) {
const context = useFormEditStore(state => state.context);
const focusedPattern = useFormEditStore(state => state.focusedPattern);
const setFocus = useFormEditStore(state => state.setFocus);

const isSelected = focusedPattern?.id === props._patternId;
const divClassNames = isSelected
? 'form-group-row field-selected'
: 'form-group-row';
const Component = context.components[props.type];
const { context, setFocus } = useFormEditStore(state => ({
context: state.context,
setFocus: state.setFocus,
updatePatternById: state.updatePatternById,
}));
const EditComponent = context.editComponents[props.type];

const selected = focusedPattern?.id === props._patternId;
return (
<div
className={divClassNames}
data-id={props._patternId}
onFocus={() => {
onClick={event => {
if (EditComponent) {
event.stopPropagation();
setFocus(props._patternId);
}
}}
onFocus={event => {
if (EditComponent) {
event.stopPropagation();
setFocus(props._patternId);
}
}}
>
{selected ? <PatternEdit /> : <Component {...props} />}
<EditComponent context={context} previewProps={props} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';

import { PatternId, type FieldsetProps } from '@atj/forms';
import { FieldsetPattern } from '@atj/forms/src/patterns/fieldset';

import Fieldset from '../../../Form/components/Fieldset';

import { PatternEditActions } from '../PatternEditActions';
import { PatternEditForm } from '../PatternEditForm';
import { useIsPatternSelected, usePattern } from '../store';
import { PatternEditComponent } from '../types';

const FieldsetEdit: PatternEditComponent<FieldsetProps> = props => {
const isSelected = useIsPatternSelected(props.previewProps._patternId);
return (
<>
{isSelected ? (
<PatternEditForm
patternId={props.previewProps._patternId}
editComponent={
<EditComponent patternId={props.previewProps._patternId} />
}
></PatternEditForm>
) : (
<FieldsetPreview {...props.previewProps} />
)}
</>
);
};

const FieldsetPreview = (props: FieldsetProps) => {
const pattern = usePattern<FieldsetPattern>(props._patternId);
return (
<>
{pattern.data.patterns.length === 0 && <em>[Empty fieldset]</em>}
<Fieldset {...(props as FieldsetProps)} />
</>
);
};

const EditComponent = ({ patternId }: { patternId: PatternId }) => {
const pattern = usePattern(patternId);
//const { register } = usePatternEditFormContext();
return (
<div>
Fieldset settings go here. {JSON.stringify(pattern)}
<Fieldset type="fieldset" _patternId={patternId} />
<PatternEditActions />
</div>
);
};

export default FieldsetEdit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';

import { type FormSummaryProps, type PatternId } from '@atj/forms';

import FormSummary from '../../../Form/components/FormSummary';
import { PatternEditForm, usePatternEditFormContext } from '../PatternEditForm';
import { useIsPatternSelected } from '../store';
import { PatternEditComponent } from '../types';

const FormSummaryEdit: PatternEditComponent<FormSummaryProps> = props => {
const isSelected = useIsPatternSelected(props.previewProps._patternId);
return (
<>
{isSelected ? (
<PatternEditForm
patternId={props.previewProps._patternId}
editComponent={
<EditComponent patternId={props.previewProps._patternId} />
}
></PatternEditForm>
) : (
<FormSummary {...props.previewProps} />
)}
</>
);
};

const EditComponent = ({ patternId }: { patternId: PatternId }) => {
const { register } = usePatternEditFormContext();
return (
<div className="grid-row grid-gap">
<div className="grid-col grid-col-4">
<label className="usa-label">
Title
<input
className="usa-input"
{...register(`${patternId}.data.title`)}
type="text"
></input>
</label>
</div>
<div className="grid-col grid-col-2">
<label className="usa-label">
Description
<textarea
className="usa-textarea"
{...register(`${patternId}.data.description`)}
></textarea>
</label>
</div>
</div>
);
};

export default FormSummaryEdit;
Loading
Loading