Skip to content

Commit

Permalink
Merge branch 'master' into mp/portal-modals-anywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
mperrotti authored Oct 11, 2019
2 parents c95e96d + 189903f commit 25b07e7
Show file tree
Hide file tree
Showing 4 changed files with 896 additions and 44 deletions.
45 changes: 35 additions & 10 deletions packages/toggleInputList/components/ToggleInputList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
fieldsetReset,
legendReset,
padding,
textWeight,
visuallyHidden
} from "../../shared/styles/styleUtils";
import { InputAppearance } from "../../shared/types/inputAppearance";
import { getLabelStyle } from "../../shared/styles/formStyles";
import { DangerText } from "../../index";

export interface ToggleInputProperties {
appearance?: InputAppearance;
Expand Down Expand Up @@ -57,23 +58,34 @@ export interface ToggleInputListProps {
* How the text content of each option vertically aligns with it's related input
*/
vertAlign?: "center" | "top";
/**
* If this entire input list is a required field
*/
required?: boolean;
/**
* Sets the current appearance of the label component. This defaults to InputAppearance.Standard, but supports `InputAppearance.Error` & `InputAppearance.Success` appearances as well.
*/
labelAppearance: InputAppearance;
}

class ToggleInputList extends React.PureComponent<ToggleInputListProps, {}> {
public static defaultProps: Partial<ToggleInputListProps> = {
showListLabel: true,
vertAlign: "center",
selectedItems: []
selectedItems: [],
labelAppearance: InputAppearance.Standard
};

constructor(props) {
super(props);

this.getSelectedItems = this.getSelectedItems.bind(this);
this.listLegendContent = this.listLegendContent.bind(this);
this.inputListItems = this.inputListItems.bind(this);
}

public render() {
const { listLabel, showListLabel, errors, hintContent, id } = this.props;
const { errors, hintContent, id, required } = this.props;

return (
<FormFieldWrapper errors={errors} hintContent={hintContent} id={id}>
Expand All @@ -82,14 +94,10 @@ class ToggleInputList extends React.PureComponent<ToggleInputListProps, {}> {
className={fieldsetReset}
aria-invalid={!isValid}
aria-describedby={describedByIds}
aria-required={required}
role="listbox"
>
<legend
className={cx(legendReset, textWeight("medium"), {
[visuallyHidden]: !showListLabel
})}
>
{listLabel}
</legend>
{this.listLegendContent()}
<ul className={listReset}>{this.inputListItems()}</ul>
{getHintContent}
{getValidationErrors}
Expand All @@ -99,6 +107,23 @@ class ToggleInputList extends React.PureComponent<ToggleInputListProps, {}> {
);
}

private listLegendContent() {
const { labelAppearance, showListLabel, listLabel, required } = this.props;
const requiredContent = required ? (
<DangerText tag="span"> *</DangerText>
) : null;
const hasError = labelAppearance === InputAppearance.Error;
const legendClassName = showListLabel
? getLabelStyle(hasError)
: cx(visuallyHidden);
return (
<legend className={cx(legendReset, legendClassName)}>
{listLabel}
{requiredContent}
</legend>
);
}

private inputListItems() {
const { items } = this.props;

Expand Down
48 changes: 47 additions & 1 deletion packages/toggleInputList/stories/ToggleInputList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,50 @@ storiesOf("Forms/ToggleInputList", module)
/>
)}
</ToggleInputListStoryHelper>
));
))
.add(
"required",
() => (
<ToggleInputListStoryHelper>
{({ changeHandler, selectedItems }) => (
<ToggleInputList
id="checkbox"
items={options}
listLabel="Atmosphere layers"
onChange={changeHandler}
selectedItems={selectedItems}
required={true}
/>
)}
</ToggleInputListStoryHelper>
),
{
info: {
propTables: [ToggleInputList]
}
}
)
.add(
"error with message",
() => (
<ToggleInputListStoryHelper>
{({ changeHandler, selectedItems }) => (
<ToggleInputList
id="checkbox"
items={options}
listLabel="Atmosphere layers"
labelAppearance={InputAppearance.Error}
onChange={changeHandler}
selectedItems={[]}
errors={["Please select an item."]}
required={true}
/>
)}
</ToggleInputListStoryHelper>
),
{
info: {
propTables: [ToggleInputList]
}
}
);
26 changes: 26 additions & 0 deletions packages/toggleInputList/tests/ToggleInputList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as emotion from "emotion";
import { createSerializer } from "jest-emotion";
import toJson from "enzyme-to-json";
import { ToggleInputList } from "../";
import { InputAppearance } from "../../shared/types/inputAppearance";

const options = [
{ inputLabel: "Sample label", id: "id.1", value: "value.1" },
Expand Down Expand Up @@ -61,6 +62,31 @@ describe("ToggleInputList", () => {
expect(toJson(component)).toMatchSnapshot();
});

it("renders with required", () => {
const component = mount(
<ToggleInputList
id="checkbox"
items={options}
listLabel="Sample legend"
required={true}
/>
);
expect(toJson(component)).toMatchSnapshot();
});

it("renders with error label appearance", () => {
const component = mount(
<ToggleInputList
id="checkbox"
items={options}
listLabel="Sample legend"
labelAppearance={InputAppearance.Error}
errors={["error.1", "error.2"]}
/>
);
expect(toJson(component)).toMatchSnapshot();
});

it("calls onChange prop with the selected values", () => {
const onChangeFn = jest.fn();
const component = mount(
Expand Down
Loading

0 comments on commit 25b07e7

Please sign in to comment.