Skip to content

Commit

Permalink
feat(textarea, textbox): surface maxWidth prop on components
Browse files Browse the repository at this point in the history
surfaces the `maxWidth` prop on `Textarea`, `Textbox`, `Decimal`, `GroupedCharacter`, `Number`,
`Search`, `MultiSelect`, `FilterableSelect` and `SimpleSelect` components to allow consumers
to set max-width on the input and to allow label and validation strings to exceed its width

fix #5494, fix #5234
  • Loading branch information
tomdavies73 committed Dec 1, 2022
1 parent 6192c82 commit 21df556
Show file tree
Hide file tree
Showing 40 changed files with 723 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports[`InputPresentation renders presentational div and context provider for i
display: -ms-flexbox;
display: flex;
position: relative;
max-width: 100%;
}
.c1 {
Expand Down
11 changes: 10 additions & 1 deletion src/__internal__/input/input-presentation.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ export interface CommonInputPresentationProps extends ValidationProps {
align?: string;
/** The width of the input as a percentage */
inputWidth?: number;
/**
* Prop for specifying the max width of the input.
* Leaving the `maxWidth` prop with no value will default the width to '100%'
*/
maxWidth?: string;
/** If true, the component will be read-only */
readOnly?: boolean;
/** Size of an input */
Expand All @@ -33,6 +38,7 @@ const InputPresentation = ({
children,
positionedChildren,
inputWidth,
maxWidth,
align,
disabled,
readOnly,
Expand Down Expand Up @@ -63,7 +69,10 @@ const InputPresentation = ({
};

return (
<StyledInputPresentationContainer inputWidth={inputWidth}>
<StyledInputPresentationContainer
inputWidth={inputWidth}
maxWidth={maxWidth}
>
{positionedChildren}
<InputPresentationStyle
hasFocus={hasFocus}
Expand Down
20 changes: 20 additions & 0 deletions src/__internal__/input/input-presentation.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ describe("InputPresentation", () => {
});
});

describe("maxWidth", () => {
it("renders correctly with a custom maxWidth", () => {
assertStyleMatch(
{
maxWidth: "54%",
},
render({ maxWidth: "54%", children: "Children" })
);
});

it("renders correctly as 100% as maxWidth has been left with no value", () => {
assertStyleMatch(
{
maxWidth: "100%",
},
render({ maxWidth: "", children: "Children" })
);
});
});

describe.each([
["error", "var(--colorsSemanticNegative500)"],
["warning", "var(--colorsSemanticCaution500)"],
Expand Down
3 changes: 2 additions & 1 deletion src/__internal__/input/input-presentation.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { InputContextProps } from "../input-behaviour";
import { CarbonProviderProps } from "../../components/carbon-provider";

export const StyledInputPresentationContainer = styled.div<
Pick<CommonInputPresentationProps, "inputWidth">
Pick<CommonInputPresentationProps, "inputWidth" | "maxWidth">
>`
flex: 0 0 ${({ inputWidth }) => inputWidth}%;
display: flex;
position: relative;
max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}` : "100%")};
`;

function stylingForValidations({
Expand Down
1 change: 1 addition & 0 deletions src/components/date/date.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ const DateInput = ({

DateInput.propTypes = {
...Textbox.propTypes,
maxWidth: undefined,
...marginPropTypes,
/** Pass any props that match the [DayPickerProps](https://react-day-picker-v7.netlify.app/docs/getting-started/)
* interface to override default behaviors
Expand Down
1 change: 1 addition & 0 deletions src/components/date/date.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ Due to the `Textbox` component being used internally by the `Date` component the
<ArgsTable
of={Textbox}
exclude={[
"maxWidth",
"value",
"formattedValue",
"rawValue",
Expand Down
29 changes: 28 additions & 1 deletion src/components/decimal/decimal.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React from "react";
import ReactDOM from "react-dom";
import { mount as enzymeMount, ReactWrapper } from "enzyme";
import { InputPresentation } from "../../__internal__/input";

import Decimal, { DecimalProps, CustomEvent } from "./decimal.component";
import { testStyledSystemMargin } from "../../__spec_helper__/test-utils";
import {
assertStyleMatch,
testStyledSystemMargin,
} from "../../__spec_helper__/test-utils";
import Textbox from "../textbox/textbox.component";
import Label from "../../__internal__/label";
import FormFieldStyle from "../../__internal__/form-field/form-field.style";
Expand Down Expand Up @@ -1457,4 +1461,27 @@ describe("Decimal", () => {
expect(label.prop("isRequired")).toBe(true);
});
});

describe("when maxWidth is passed", () => {
it("should be passed to InputPresentation", () => {
mount(<Decimal maxWidth="67%" />);

assertStyleMatch(
{
maxWidth: "67%",
},
wrapper.find(InputPresentation)
);
});

it("renders correctly as 100% as maxWidth has been left with no value", () => {
mount(<Decimal maxWidth="" />);
assertStyleMatch(
{
maxWidth: "100%",
},
wrapper.find(InputPresentation)
);
});
});
});
9 changes: 9 additions & 0 deletions src/components/decimal/decimal.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ import Decimal from "carbon-react/lib/components/decimal";
/>
</Canvas>

### With custom maxWidth

<Canvas>
<Story
name="with custom maxWidth"
story={stories.WithCustomMaxWidth}
/>
</Canvas>

### With fieldHelp

<Canvas>
Expand Down
5 changes: 5 additions & 0 deletions src/components/decimal/decimal.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ WithCustomLabelWidthAndInputWidth.args = {
labelInline: true,
};

export const WithCustomMaxWidth = DefaultStory.bind({});
WithCustomMaxWidth.args = {
maxWidth: "50%",
};

export const WithFieldHelp = DefaultStory.bind({});
WithFieldHelp.args = { fieldHelp: "Help" };

Expand Down
27 changes: 27 additions & 0 deletions src/components/decimal/decimal.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,33 @@ context("Tests for Decimal component", () => {
});
});

it.each([
["10%", "10%"],
["30%", "30%"],
["50%", "50%"],
["80%", "80%"],
["100%", "100%"],
])(
"should use %s as maxWidth and render it with correct corresponding max-width percentage",
(input, totalWidth) => {
CypressMountWithProviders(<Decimal maxWidth={input} />);

getDataElementByValue("input")
.parent()
.parent()
.should("have.css", "max-width", totalWidth);
}
);

it("as maxWidth has no value it should render as 100%", () => {
CypressMountWithProviders(<Decimal maxWidth="" />);

getDataElementByValue("input")
.parent()
.parent()
.should("have.css", "max-width", "100%");
});

it("can have a custom onChange handler", () => {
const CustomDecimalComponent = ({ onChange, value, ...props }) => {
const [state, setState] = React.useState("0.01");
Expand Down
39 changes: 38 additions & 1 deletion src/components/grouped-character/grouped-character.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import React from "react";
import { HTMLAttributes, mount, ReactWrapper } from "enzyme";

import { testStyledSystemMargin } from "../../__spec_helper__/test-utils";
import GroupedCharacter, {
GroupedCharacterProps,
} from "./grouped-character.component";
import {
assertStyleMatch,
testStyledSystemMargin,
} from "../../__spec_helper__/test-utils";
import FormFieldStyle from "../../__internal__/form-field/form-field.style";
import Label from "../../__internal__/label";
import { InputPresentation } from "../../__internal__/input";

const mountComponent = (props: GroupedCharacterProps) =>
mount(<GroupedCharacter {...props} />);

function renderGroupedCharacter(
props: Partial<GroupedCharacterProps>,
renderer = mount
) {
return renderer(
<GroupedCharacter groups={[2, 2, 3]} separator="-" {...props} />
);
}

describe("GroupedCharacter", () => {
jest.useFakeTimers();
const basicGroupConfig = [2, 2, 4];
Expand Down Expand Up @@ -245,4 +258,28 @@ describe("GroupedCharacter", () => {
expect(label.prop("isRequired")).toBe(true);
});
});

describe("when maxWidth is passed", () => {
it("should be passed to InputPresentation", () => {
const wrapper = renderGroupedCharacter({ maxWidth: "67%" });

assertStyleMatch(
{
maxWidth: "67%",
},
wrapper.find(InputPresentation)
);
});

it("renders correctly as 100% as maxWidth has been left with no value", () => {
const wrapper = renderGroupedCharacter({ maxWidth: "" });

assertStyleMatch(
{
maxWidth: "100%",
},
wrapper.find(InputPresentation)
);
});
});
});
24 changes: 24 additions & 0 deletions src/components/grouped-character/grouped-character.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ import GroupedCharacter from "carbon-react/lib/components/grouped-character";
/>
</Canvas>

### With custom maxWidth

<Canvas>
<Story name="with custom maxWidth">
{() => {
const [state, setState] = useState("1231231");
const setValue = ({ target }) => {
setState(target.value.rawValue);
};
return (
<GroupedCharacter
label="GroupedCharacter"
value={state}
onChange={setValue}
groups={[2, 2, 3]}
separator="-"
maxWidth="50%"
/>
);
}}
</Story>
</Canvas>


### With fieldHelp

<Canvas>
Expand Down
27 changes: 27 additions & 0 deletions src/components/grouped-character/grouped-character.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,33 @@ context("Tests for GroupedCharacter component", () => {
);
});

it.each([
["10%", "10%"],
["30%", "30%"],
["50%", "50%"],
["80%", "80%"],
["100%", "100%"],
])(
"should use %s as maxWidth and render it with correct corresponding max-width percentage",
(input, totalWidth) => {
CypressMountWithProviders(<GroupedCharacterComponent maxWidth={input} />);

getDataElementByValue("input")
.parent()
.parent()
.should("have.css", "max-width", totalWidth);
}
);

it("as maxWidth has no value it should render as 100%", () => {
CypressMountWithProviders(<GroupedCharacterComponent maxWidth="" />);

getDataElementByValue("input")
.parent()
.parent()
.should("have.css", "max-width", "100%");
});

describe("check events for GroupedCharacter component", () => {
let callback;

Expand Down
25 changes: 25 additions & 0 deletions src/components/number/number.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { mount } from "enzyme";
import Number from "./number.component";
import Textbox from "../textbox";
import Label from "../../__internal__/label";
import { assertStyleMatch } from "../../__spec_helper__/test-utils";
import InputPresentation from "../../__internal__/input/input-presentation.component";

describe("Number Input", () => {
let wrapper, input, onChangeFn, onKeyDownFn;
Expand Down Expand Up @@ -127,6 +129,29 @@ describe("Number Input", () => {
expect(label.prop("isRequired")).toBe(true);
});
});

describe("when maxWidth is passed", () => {
it("should be passed to InputPresentation", () => {
wrapper = renderNumberInput({ maxWidth: "67%" });

assertStyleMatch(
{
maxWidth: "67%",
},
wrapper.find(InputPresentation)
);
});

it("renders correctly as 100% as maxWidth has been left with no value", () => {
wrapper = renderNumberInput({ maxWidth: "" });
assertStyleMatch(
{
maxWidth: "100%",
},
wrapper.find(InputPresentation)
);
});
});
});

function renderNumberInput(props, renderer = mount) {
Expand Down
12 changes: 12 additions & 0 deletions src/components/number/number.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ import Number from "carbon-react/lib/components/number";
</Story>
</Canvas>

### With custom maxWidth

<Canvas>
<Story name="with custom maxWidth">
<Number
label="Number"
value="123456"
maxWidth="50%"
/>
</Story>
</Canvas>

### With fieldHelp

<Canvas>
Expand Down
Loading

0 comments on commit 21df556

Please sign in to comment.