Skip to content
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
Binary file added canonical-react-components-v0.47.3.tgz
Binary file not shown.
33 changes: 33 additions & 0 deletions src/components/Field/Field.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ describe("Field ", () => {
);
});

it("can display the help message after the label", () => {
render(
<Field
label="Test label"
help="This is how you do it"
data-testid="field"
helpAfterLabel
/>,
);
const field = screen.getByTestId("field");
expect(field.childNodes[0]).toHaveClass("p-form__label");
expect(field.childNodes[1]).toHaveClass("p-form-help-text");
});

it("can display the label before the input", () => {
render(
<Field
Expand Down Expand Up @@ -179,4 +193,23 @@ describe("Field ", () => {
).toBeInTheDocument();
expect(screen.getByTestId("field")).toHaveClass("row");
});

it("can set custom column widths when stacked", () => {
render(
<Field
stacked={true}
label="Test label"
data-testid="field"
stackedFieldColumns={6}
stackedLabelColumns={2}
/>,
);
// The Label should be inside a col-2.
expect(document.querySelector(".col-2 .p-form__label")).toBeInTheDocument();
// The control should be inside a col-6.
expect(
document.querySelector(".col-6 .p-form__control"),
).toBeInTheDocument();
expect(screen.getByTestId("field")).toHaveClass("row");
});
});
61 changes: 41 additions & 20 deletions src/components/Field/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import type { ReactNode } from "react";

import Label from "../Label";
import Col from "../Col";
import Col, { ColSize } from "../Col";

import type { ClassName } from "types";

Expand Down Expand Up @@ -39,6 +39,10 @@ export type Props = {
* Optional class(es) to pass to the help text element.
*/
helpClassName?: string;
/**
* Whether the help should appear after the label (by default it will appear below the field).
*/
helpAfterLabel?: boolean;
/**
* An id to give to the help element.
*/
Expand Down Expand Up @@ -71,6 +75,14 @@ export type Props = {
* Whether the form field should have a stacked appearance.
*/
stacked?: boolean;
/**
* The number of columns the field should have when stacked.
*/
stackedFieldColumns?: ColSize;
/**
* The number of columns the label should have when stacked.
*/
stackedLabelColumns?: ColSize;
/**
* The content for success validation.
*/
Expand Down Expand Up @@ -120,17 +132,23 @@ const generateLabel = (
label: Props["label"],
labelClassName: Props["labelClassName"],
stacked: Props["stacked"],
stackedLabelColumns: Props["stackedLabelColumns"],
help: ReactNode,
helpAfterLabel: Props["helpAfterLabel"],
) => {
if (!label) {
return null;
}
const labelNode = (
<Label className={labelClassName} forId={forId} required={required}>
{label}
</Label>
<>
<Label className={labelClassName} forId={forId} required={required}>
{label}
</Label>
{helpAfterLabel ? help : null}
</>
);
if (stacked) {
return <Col size={4}>{labelNode}</Col>;
return <Col size={stackedLabelColumns}>{labelNode}</Col>;
}
return labelNode;
};
Expand All @@ -141,17 +159,15 @@ const generateContent = ({
labelFirst,
labelNode,
help,
helpClassName,
error,
caution,
success,
validationId,
helpId,
isTickElement,
helpAfterLabel,
}: Partial<Props> & {
labelNode: React.JSX.Element | null;
validationId: string;
helpId: string;
help: ReactNode;
}) => (
<div className="p-form__control u-clearfix">
{isSelect ? (
Expand All @@ -160,12 +176,7 @@ const generateContent = ({
children
)}
{!labelFirst && labelNode}
{generateHelpText({
helpId,
help,
helpClassName,
isTickElement,
})}
{helpAfterLabel ? null : help}
{generateError(error, caution, success, validationId)}
</div>
);
Expand All @@ -178,6 +189,7 @@ const Field = ({
forId,
help,
helpClassName,
helpAfterLabel,
helpId,
isSelect,
isTickElement,
Expand All @@ -186,31 +198,40 @@ const Field = ({
labelFirst = true,
required,
stacked,
stackedFieldColumns = 8,
stackedLabelColumns = 4,
success,
validationId,
...props
}: Props): React.JSX.Element => {
const helpNode = generateHelpText({
helpId,
help,
helpClassName,
isTickElement,
});
const labelNode = generateLabel(
forId,
required,
label,
labelClassName,
stacked,
stackedLabelColumns,
helpNode,
helpAfterLabel,
);

const content = generateContent({
isSelect,
isTickElement,
children,
labelFirst,
labelNode,
help,
helpClassName,
help: helpNode,
error,
caution,
success,
validationId,
helpId,
helpAfterLabel,
});
return (
<div
Expand All @@ -223,7 +244,7 @@ const Field = ({
{...props}
>
{labelFirst && labelNode}
{stacked ? <Col size={8}>{content}</Col> : content}
{stacked ? <Col size={stackedFieldColumns}>{content}</Col> : content}
</div>
);
};
Expand Down
19 changes: 19 additions & 0 deletions src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import CheckboxInput from "../CheckboxInput";
import RadioInput from "../RadioInput";

import type { ClassName, PropsWithSpread } from "types";
import { ColSize } from "components/Col";

/**
* The props for the Input component.
Expand Down Expand Up @@ -37,6 +38,10 @@ export type Props = PropsWithSpread<
* The id of the input.
*/
id?: string;
/**
* Whether the help should appear after the label (by default it will appear below the field).
*/
helpAfterLabel?: boolean;
/**
* The label for the field.
*/
Expand All @@ -53,6 +58,14 @@ export type Props = PropsWithSpread<
* Whether the form field should have a stacked appearance.
*/
stacked?: boolean;
/**
* The number of columns the field should have when stacked.
*/
stackedFieldColumns?: ColSize;
/**
* The number of columns the label should have when stacked.
*/
stackedLabelColumns?: ColSize;
/**
* The content for success validation.
*/
Expand Down Expand Up @@ -83,12 +96,15 @@ const Input = ({
className,
error,
help,
helpAfterLabel,
helpClassName,
id,
label,
labelClassName,
required,
stacked,
stackedFieldColumns,
stackedLabelColumns,
success,
takeFocus,
takeFocusDelay,
Expand Down Expand Up @@ -160,13 +176,16 @@ const Input = ({
error={error}
forId={inputId}
help={help}
helpAfterLabel={helpAfterLabel}
helpClassName={helpClassName}
helpId={helpId}
isTickElement={type === "checkbox" || type === "radio"}
label={fieldLabel}
labelClassName={labelClassName}
required={required}
stacked={stacked}
stackedFieldColumns={stackedFieldColumns}
stackedLabelColumns={stackedLabelColumns}
success={success}
validationId={validationId}
>
Expand Down
19 changes: 19 additions & 0 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
import Field from "../Field";

import type { ClassName, PropsWithSpread } from "types";
import { ColSize } from "components/Col";

type Option = OptionHTMLAttributes<HTMLOptionElement>;

Expand All @@ -34,6 +35,10 @@ export type Props = PropsWithSpread<
* Help text to show below the field.
*/
help?: ReactNode;
/**
* Whether the help should appear after the label (by default it will appear below the field).
*/
helpAfterLabel?: boolean;
/**
* Optional class(es) to pass to the help text element.
*/
Expand Down Expand Up @@ -66,6 +71,14 @@ export type Props = PropsWithSpread<
* Whether the form field should have a stacked appearance.
*/
stacked?: boolean;
/**
* The number of columns the field should have when stacked.
*/
stackedFieldColumns?: ColSize;
/**
* The number of columns the label should have when stacked.
*/
stackedLabelColumns?: ColSize;
/**
* The content for success validation.
*/
Expand Down Expand Up @@ -99,6 +112,7 @@ const Select = ({
className,
error,
help,
helpAfterLabel,
helpClassName,
id,
label,
Expand All @@ -107,6 +121,8 @@ const Select = ({
options,
required,
stacked,
stackedFieldColumns,
stackedLabelColumns,
success,
takeFocus,
wrapperClassName,
Expand All @@ -132,13 +148,16 @@ const Select = ({
error={error}
forId={selectId}
help={help}
helpAfterLabel={helpAfterLabel}
helpClassName={helpClassName}
helpId={helpId}
isSelect={true}
label={label}
labelClassName={labelClassName}
required={required}
stacked={stacked}
stackedFieldColumns={stackedFieldColumns}
stackedLabelColumns={stackedLabelColumns}
success={success}
validationId={validationId}
>
Expand Down
Loading