Skip to content

Commit

Permalink
Add radio group and checkbox patterns (#86)
Browse files Browse the repository at this point in the history
* Added button, checkbox, radiobutton components. Still need to add functionality to checkbox and radio button.

* Added Radio Group component and updated buton and checkbox components.

* Fixing linting issues.

* Fixing another missed linting issue for checkbox.

* Fixed sass type.

* Format components with repo's Prettier config

* Get RadioGroup working

* Fix props argument on checkbox component

* Remove button component

* Move updated RadioGroup into Form/components directory, and wrap with a RadioGroupPattern component.

* Move updated checkbox component into Form/components and wrap it with a CheckboxPattern component

* Create and wire up checkbox pattern

* Add an initial radio group pattern that limits the ability to edit options. Needs to be updated with a proper UI.

* Add typing for RadioGroupPattern

* Fix case mismatch - CheckBox -> Checkbox

* Radio group "add new" option button added; rename pattern parseData to parseUserInput.

---------

Co-authored-by: Daniel Naab <[email protected]>
Co-authored-by: Daniel Naab <[email protected]>
  • Loading branch information
3 people authored May 1, 2024
1 parent 6f1d27b commit 90d1760
Show file tree
Hide file tree
Showing 18 changed files with 565 additions and 13 deletions.
14 changes: 14 additions & 0 deletions packages/design/src/Form/components/Checkbox/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Checkbox from './Checkbox';

export default {
component: Checkbox,
title: 'Components/Checkbox',
tags: ['autodocs'],
};

export const Primary = {
args: {
id: '1',
label: 'Primary label Text',
},
};
25 changes: 25 additions & 0 deletions packages/design/src/Form/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

type CheckboxProps = {
id: string;
name: string;
label: string;
defaultChecked: boolean;
};

export default function Checkbox(props: CheckboxProps) {
return (
<div className="usa-checkbox">
<input
id={props.id}
name={props.name}
type="checkbox"
className="usa-checkbox__input"
defaultChecked={props.defaultChecked}
/>
<label className="usa-checkbox__label" htmlFor={props.id}>
{props.label}
</label>
</div>
);
}
19 changes: 19 additions & 0 deletions packages/design/src/Form/components/Checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

import { type CheckboxProps } from '@atj/forms';

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

const CheckboxPattern: PatternComponent<CheckboxProps> = props => {
return (
<Checkbox
id={props.id}
defaultChecked={props.defaultChecked}
name={props.name}
label={props.label}
/>
);
};

export default CheckboxPattern;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Meta, Story } from '@storybook/react';

import RadioGroup, { RadioInput } from './RadioGroup';
import React from 'react';

export default {
title: 'Components/RadioGroup',
component: RadioGroup,
tags: ['autodocs'],
} as Meta;

const Template: Story = () => (
<RadioGroup legend="Select an item">
<RadioInput
id="option-1"
name="select-item"
defaultValue="option1"
label="Option 1"
/>
<RadioInput
id="option-2"
name="select-item"
defaultValue="option2"
label="Option 2"
/>
<RadioInput
id="option-3"
name="select-item"
defaultValue="option3"
label="Option 3"
/>
</RadioGroup>
);

export const Default = Template.bind({});
Default.args = {};
41 changes: 41 additions & 0 deletions packages/design/src/Form/components/RadioGroup/RadioGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { type ReactElement } from 'react';

type RadioGroupProps = {
legend: string;
children: ReactElement<RadioProps> | ReactElement<RadioProps>[];
};

export default function RadioGroup({ legend, children }: RadioGroupProps) {
return (
<div className="usa-fieldset">
<legend className="usa-legend">{legend}</legend>
{children}
</div>
);
}

export type RadioProps = {
id: string;
name: string;
label: string;
disabled?: boolean;
defaultChecked: boolean;
};

export const RadioInput = (props: RadioProps) => {
return (
<div className="usa-radio">
<input
id={props.id}
name={props.name}
className="usa-radio__input"
type="radio"
disabled={props.disabled}
defaultChecked={props.defaultChecked}
/>
<label htmlFor={props.id} className="usa-radio__label">
{props.label}
</label>
</div>
);
};
23 changes: 23 additions & 0 deletions packages/design/src/Form/components/RadioGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';

import { type RadioGroupProps } from '@atj/forms';

import { type PatternComponent } from '../../../Form';
import RadioGroup, { RadioInput } from './RadioGroup';

const RadioGroupPattern: PatternComponent<RadioGroupProps> = props => {
return (
<RadioGroup legend={props.legend}>
{props.options.map((option, index) => (
<RadioInput
key={index}
id={option.id}
name={option.name}
label={option.label}
defaultChecked={option.defaultChecked}
></RadioInput>
))}
</RadioGroup>
);
};
export default RadioGroupPattern;
4 changes: 4 additions & 0 deletions packages/design/src/Form/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { type ComponentForPattern } from '..';

import Address from './Address';
import Checkbox from './Checkbox';
import Fieldset from './Fieldset';
import FormSummary from './FormSummary';
import Paragraph from './Paragraph';
import RadioGroup from './RadioGroup';
import Sequence from './Sequence';
import SubmissionConfirmation from './SubmissionConfirmation';
import TextInput from './TextInput';

export const defaultPatternComponents: ComponentForPattern = {
address: Address,
checkbox: Checkbox,
fieldset: Fieldset,
'form-summary': FormSummary,
input: TextInput,
paragraph: Paragraph,
'radio-group': RadioGroup,
sequence: Sequence,
'submission-confirmation': SubmissionConfirmation,
};
7 changes: 4 additions & 3 deletions packages/design/src/Form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ export type FormUIContext = {
uswdsRoot: `${string}/`;
};

export type ComponentForPattern<
T extends PatternProps = PatternProps<unknown>,
> = Record<string, PatternComponent<T>>;
export type ComponentForPattern<T extends PatternProps = PatternProps> = Record<
string,
PatternComponent<T>
>;

export type PatternComponent<T extends PatternProps = PatternProps<unknown>> =
React.ComponentType<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';

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

import Checkbox from '../../../Form/components/Checkbox';
import { useFormManagerStore } from '../../store';
import { PatternEditComponent } from '../types';

import { PatternEditActions } from './common/PatternEditActions';
import {
PatternEditForm,
usePatternEditFormContext,
} from './common/PatternEditForm';

const CheckboxPatternEdit: PatternEditComponent<CheckboxProps> = props => {
const isSelected = useFormManagerStore(
state => state.focusedPattern?.id === props.previewProps._patternId
);
return (
<>
{isSelected ? (
<PatternEditForm
patternId={props.previewProps._patternId}
editComponent={
<CheckboxEditComponent patternId={props.previewProps._patternId} />
}
></PatternEditForm>
) : (
<Checkbox {...props.previewProps} />
)}
</>
);
};

const CheckboxEditComponent = ({ patternId }: { patternId: PatternId }) => {
const pattern = useFormManagerStore(state => state.form.patterns[patternId]);
const methods = usePatternEditFormContext();

return (
<div className="grid-row grid-gap">
<div className="tablet:grid-col-6 mobile-lg:grid-col-12">
<label className="usa-label" htmlFor={`${pattern.id}.data.label`}>
Field label
</label>
<input
className="usa-input"
id={`${pattern.id}.data.label`}
defaultValue={`${pattern.id}`}
{...methods.register(`${pattern.id}.data.label`)}
type="text"
></input>
</div>
<div className="tablet:grid-col-6 mobile-lg:grid-col-12">
<div className="usa-checkbox">
<input
id={`${pattern.id}.data.defaultChecked`}
type="checkbox"
{...methods.register(`${pattern.id}.data.defaultChecked`)}
className="usa-checkbox__input"
/>
<label
className="usa-checkbox__label"
htmlFor={`${pattern.id}.data.defaultChecked`}
>
Default field value
</label>
</div>
</div>
<div className="grid-col-12">
<PatternEditActions>
<span className="usa-checkbox">
<input
style={{ display: 'inline-block' }}
className="usa-checkbox__input"
type="checkbox"
id={`${pattern.id}.data.required`}
{...methods.register(`${pattern.id}.data.required`)}
/>
<label
style={{ display: 'inline-block' }}
className="usa-checkbox__label"
htmlFor={`${pattern.id}.data.required`}
>
Required
</label>
</span>
</PatternEditActions>
</div>
</div>
);
};

export default CheckboxPatternEdit;
Loading

0 comments on commit 90d1760

Please sign in to comment.