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

fix(textarea, textbox): ensure inputHint and labelHelp props do not render two seperate DOM elements #6363

Merged
merged 2 commits into from
Oct 27, 2023
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
6 changes: 6 additions & 0 deletions src/components/decimal/decimal.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ import Decimal from "carbon-react/lib/components/decimal";
<Story name="with fieldHelp" story={stories.WithFieldHelp} />
</Canvas>

### With inputHint

<Canvas>
<Story name="with inputHint" story={stories.WithInputHint} />
</Canvas>

### With labelHelp

<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 @@ -108,6 +108,11 @@ WithLabelHelp.args = {
helpAriaLabel: "Help",
};

export const WithInputHint = DefaultStory.bind({});
WithInputHint.args = {
inputHint: "Hint text (optional).",
};

export const Required = DefaultStory.bind({});
Required.args = { required: true };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ import GroupedCharacter from "carbon-react/lib/components/grouped-character";
<Story story={stories.FieldHelp} name="with fieldHelp" />
</Canvas>

### with inputHint

When the `inputHint` prop is passed, please use a full stop `.` at the end. This forces a pause
before any other announcements, this well help screen reader users understand the hint fully.

<Canvas>
<Story name="with inputHint" story={stories.InputHint} />
</Canvas>

### With labelHelp

<Canvas>
Expand Down
19 changes: 19 additions & 0 deletions src/components/grouped-character/grouped-character.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,25 @@ export const FieldHelp = () => {
);
};

export const InputHint = () => {
const [state, setState] = useState("1231231");

const setValue = ({ target }: CustomEvent) => {
setState(target.value.rawValue);
};

return (
<GroupedCharacter
label="GroupedCharacter"
value={state}
onChange={setValue}
groups={[2, 2, 3]}
separator="-"
inputHint="Hint text (optional)."
/>
);
};

export const LabelHelp = () => {
const [state, setState] = useState("1231231");

Expand Down
9 changes: 9 additions & 0 deletions src/components/number/number.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ import Number from "carbon-react/lib/components/number";
<Story name="with fieldHelp" story={stories.WithFieldHelp} />
</Canvas>

### with inputHint

When the `inputHint` prop is passed, please use a full stop `.` at the end. This forces a pause
before any other announcements, this well help screen reader users understand the hint fully.

<Canvas>
<Story name="with inputHint" story={stories.WithInputHint} />
</Canvas>

### With labelHelp

<Canvas>
Expand Down
4 changes: 4 additions & 0 deletions src/components/number/number.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ export const WithFieldHelp: ComponentStory<typeof Number> = () => (
<Number label="Number" value="123456" fieldHelp="Help" />
);

export const WithInputHint: ComponentStory<typeof Number> = () => (
<Number label="Number" value="123456" inputHint="Hint text (optional)." />
);

export const WithLabelHelp: ComponentStory<typeof Number> = () => (
<Number label="Number" value="123456" labelHelp="Help" helpAriaLabel="Help" />
);
3 changes: 3 additions & 0 deletions src/components/password/password.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ the input type will not be able to be changed to `text`. To be used primarily to

### with inputHint

When the `inputHint` prop is passed, please use a full stop `.` at the end. This forces a pause
before any other announcements, this well help screen reader users understand the hint fully.

<Canvas>
<Story name="with inputHint" story={stories.InputHint} />
</Canvas>
Expand Down
6 changes: 3 additions & 3 deletions src/components/password/password.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const InputHint = () => {

return (
<Password
inputHint="Please enter a password with at least 8 characters"
inputHint="Hint text (optional)."
label="Password"
value={state}
onChange={setValue}
Expand Down Expand Up @@ -402,7 +402,7 @@ export const NewDesignsValidation = () => {
label={`${size} - ${validationType}`}
value={state}
onChange={setValue}
labelHelp="Hint text (optional)"
inputHint="Hint text (optional)"
size={size}
{...{ [validationType]: "Message" }}
/>
Expand All @@ -411,7 +411,7 @@ export const NewDesignsValidation = () => {
label={`readOnly - ${size} - ${validationType}`}
value="Password"
size={size}
labelHelp="Hint text (optional)"
inputHint="Hint text (optional)."
readOnly
{...{ [validationType]: "Message" }}
/>
Expand Down
22 changes: 9 additions & 13 deletions src/components/textarea/textarea.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import StyledTextarea, { MIN_HEIGHT } from "./textarea.style";
import { TooltipProvider } from "../../__internal__/tooltip-provider";
import useInputAccessibility from "../../hooks/__internal__/useInputAccessibility";
import { NewValidationContext } from "../carbon-provider/carbon-provider.component";
import {
ErrorBorder,
StyledHintText,
StyledInputHint,
} from "../textbox/textbox.style";
import { ErrorBorder, StyledHintText } from "../textbox/textbox.style";
import ValidationMessage from "../../__internal__/validation-message";
import Box from "../box";
import Logger from "../../__internal__/utils/logger";
Expand Down Expand Up @@ -84,7 +80,10 @@ export interface TextareaProps
label?: string;
/** Inline label alignment */
labelAlign?: "left" | "right";
/** Text applied to label help tooltip */
/** [Legacy] Text applied to label help tooltip. When opted into new design validations
* it will render as a hint above the input, unless an `inputHint`
* prop is also passed
*/
labelHelp?: React.ReactNode;
/** When true, label is placed in line an input */
labelInline?: boolean;
Expand Down Expand Up @@ -382,13 +381,10 @@ export const Textarea = React.forwardRef(
adaptiveLabelBreakpoint={adaptiveLabelBreakpoint}
validationRedesignOptIn={validationRedesignOptIn}
>
{inputHint ? (
<StyledInputHint id={inputHintId} data-element="input-hint">
{inputHint}
</StyledInputHint>
) : null}
{validationRedesignOptIn && labelHelp && (
<StyledHintText>{labelHelp}</StyledHintText>
{(inputHint || (labelHelp && validationRedesignOptIn)) && (
<StyledHintText id={inputHintId} data-element="input-hint">
{inputHint || labelHelp}
</StyledHintText>
)}
{validationRedesignOptIn ? (
<Box position="relative">
Expand Down
23 changes: 16 additions & 7 deletions src/components/textarea/textarea.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ import { StyledLabelContainer } from "../../__internal__/label/label.style";
import Tooltip from "../tooltip";
import StyledHelp from "../help/help.style";
import CarbonProvider from "../carbon-provider/carbon-provider.component";
import {
ErrorBorder,
StyledHintText,
StyledInputHint,
} from "../textbox/textbox.style";
import { ErrorBorder, StyledHintText } from "../textbox/textbox.style";
import StyledValidationMessage from "../../__internal__/validation-message/validation-message.style";
import StyledTextarea from "./textarea.style";
import Logger from "../../__internal__/utils/logger";
Expand Down Expand Up @@ -257,12 +253,12 @@ describe("Textarea", () => {
describe("and inputHint props are present", () => {
it("renders a character counter hint", () => {
wrapper = mount(<Textarea value="test string" inputHint="foo" />);
expect(wrapper.find(StyledInputHint).text()).toBe("foo");
expect(wrapper.find(StyledHintText).text()).toBe("foo");
});

it("assigns a character counter hint via guid", () => {
wrapper = mount(<Textarea value="test string" inputHint="bar" />);
expect(wrapper.find(StyledInputHint).prop("id")).toBe(mockedGuid);
expect(wrapper.find(StyledHintText).prop("id")).toBe(mockedGuid);
});

it("should render a valid 'aria-describedby' on input", () => {
Expand All @@ -271,6 +267,19 @@ describe("Textarea", () => {
mockedGuid
);
});

it("rendered text should be provided via inputHint, when labelHelp is also passed", () => {
wrapper = mount(
<CarbonProvider validationRedesignOptIn>
<Textarea
labelHelp="labelHelp"
inputHint="inputHint"
error="foo"
/>
</CarbonProvider>
);
expect(wrapper.find(StyledHintText).text()).toBe("inputHint");
});
});

describe("and fieldHelp props are present", () => {
Expand Down
9 changes: 9 additions & 0 deletions src/components/textarea/textarea.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ Include the formatted number count wherever makes sense for the language you're
<Story name="with fieldHelp" story={stories.FieldHelpStory} />
</Canvas>

### With inputHint

When the `inputHint` prop is passed, please use a full stop `.` at the end. This forces a pause
before any other announcements, this well help screen reader users understand the hint fully.

<Canvas>
<Story name="with inputHint" story={stories.InputHintStory} />
</Canvas>

### With labelHelp

<Canvas>
Expand Down
6 changes: 6 additions & 0 deletions src/components/textarea/textarea.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ export const MaxWidthStory: ComponentStory<typeof Textarea> = () => {
return <Textarea label="Textarea" maxWidth="70%" />;
};

export const InputHintStory: ComponentStory<typeof Textarea> = () => {
return <Textarea label="Textarea" inputHint="Hint text (optional)." />;
};

export const LabelHelpStory: ComponentStory<typeof Textarea> = () => {
return <Textarea label="Textarea" labelHelp="Help" helpAriaLabel="Help" />;
};
Expand Down Expand Up @@ -231,11 +235,13 @@ export const NewDesignValidationStory: ComponentStory<typeof Textarea> = () => {
>
<Textarea
label={`${validationType}`}
inputHint="Hint text (optional)."
{...{ [validationType]: "Message" }}
m={4}
/>
<Textarea
label={`readOnly - ${validationType}`}
inputHint="Hint text (optional)."
readOnly
{...{ [validationType]: "Message" }}
m={4}
Expand Down
18 changes: 9 additions & 9 deletions src/components/textbox/textbox.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import StyledPrefix from "./__internal__/prefix.style";
import { TooltipProvider } from "../../__internal__/tooltip-provider";
import useCharacterCount from "../../hooks/__internal__/useCharacterCount";
import useInputAccessibility from "../../hooks/__internal__/useInputAccessibility/useInputAccessibility";
import { ErrorBorder, StyledInputHint, StyledHintText } from "./textbox.style";
import { ErrorBorder, StyledHintText } from "./textbox.style";
import ValidationMessage from "../../__internal__/validation-message";
import { NewValidationContext } from "../carbon-provider/carbon-provider.component";
import NumeralDateContext from "../numeral-date/numeral-date-context";
Expand Down Expand Up @@ -79,7 +79,10 @@ export interface CommonTextboxProps
label?: string;
/** Inline label alignment */
labelAlign?: "left" | "right";
/** A message that the Help component will display */
/** [Legacy] Text applied to label help tooltip. When opted into new design validations
edleeks87 marked this conversation as resolved.
Show resolved Hide resolved
* it will render as a hint above the input, unless an `inputHint`
* prop is also passed
*/
labelHelp?: React.ReactNode;
/** When true label is inline */
labelInline?: boolean;
Expand Down Expand Up @@ -342,13 +345,10 @@ export const Textbox = React.forwardRef(
validationRedesignOptIn={validationRedesignOptIn}
{...filterStyledSystemMarginProps(props)}
>
{inputHint ? (
<StyledInputHint id={inputHintId} data-element="input-hint">
{inputHint}
</StyledInputHint>
) : null}
{validationRedesignOptIn && labelHelp && (
<StyledHintText>{labelHelp}</StyledHintText>
{(inputHint || (labelHelp && validationRedesignOptIn)) && (
<StyledHintText id={inputHintId} data-element="input-hint">
{inputHint || labelHelp}
</StyledHintText>
)}
{validationRedesignOptIn ? (
<Box position="relative">
Expand Down
15 changes: 12 additions & 3 deletions src/components/textbox/textbox.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import Tooltip from "../tooltip";
import StyledHelp from "../help/help.style";
import createGuid from "../../__internal__/utils/helpers/guid";
import { ErrorBorder, StyledHintText, StyledInputHint } from "./textbox.style";
import { ErrorBorder, StyledHintText } from "./textbox.style";
import StyledValidationMessage from "../../__internal__/validation-message/validation-message.style";
import CarbonProvider from "../carbon-provider/carbon-provider.component";
import Logger from "../../__internal__/utils/logger";
Expand Down Expand Up @@ -403,12 +403,12 @@ describe("Textbox", () => {
describe("and inputHint props are present", () => {
it("renders a character counter hint", () => {
const wrapper = mount(<Textbox value="test string" inputHint="foo" />);
expect(wrapper.find(StyledInputHint).text()).toBe("foo");
expect(wrapper.find(StyledHintText).text()).toBe("foo");
});

it("assigns a character counter hint via guid", () => {
const wrapper = mount(<Textbox value="test string" inputHint="bar" />);
expect(wrapper.find(StyledInputHint).prop("id")).toBe(mockedGuid);
expect(wrapper.find(StyledHintText).prop("id")).toBe(mockedGuid);
});

it("should render a valid 'aria-describedby' on input", () => {
Expand All @@ -417,6 +417,15 @@ describe("Textbox", () => {
mockedGuid
);
});

it("rendered text should be provided via inputHint, when labelHelp is also passed", () => {
edleeks87 marked this conversation as resolved.
Show resolved Hide resolved
const wrapper = mount(
<CarbonProvider validationRedesignOptIn>
<Textbox labelHelp="labelHelp" inputHint="inputHint" error="foo" />
</CarbonProvider>
);
expect(wrapper.find(StyledHintText).text()).toBe("inputHint");
});
});

describe("when maxWidth is passed", () => {
Expand Down
9 changes: 9 additions & 0 deletions src/components/textbox/textbox.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ Include the formatted number count wherever makes sense for the language you're
<Story name="with fieldHelp" story={stories.WithFieldHelp} />
</Canvas>

### With inputHint

When the `inputHint` prop is passed, please use a full stop `.` at the end. This forces a pause
before any other announcements, this well help screen reader users understand the hint fully.

<Canvas>
<Story name="with inputHint" story={stories.WithInputHint} />
</Canvas>

### With labelHelp

<Canvas>
Expand Down
14 changes: 12 additions & 2 deletions src/components/textbox/textbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ export const WithFieldHelp: ComponentStory<typeof Textbox> = () => {
return <Textbox label="Textbox" value="Textbox" fieldHelp="Help" />;
};

export const WithInputHint: ComponentStory<typeof Textbox> = () => {
return (
<Textbox
label="Textbox"
value="Textbox"
inputHint="Hint text (optional)."
/>
);
};

export const WithLabelHelp: ComponentStory<typeof Textbox> = () => {
return (
<Textbox
Expand Down Expand Up @@ -271,7 +281,7 @@ export const NewDesignsValidation: ComponentStory<typeof Textbox> = () => {
m={4}
label={`${size} - ${validationType}`}
defaultValue="Textbox"
labelHelp="Hint text (optional)"
inputHint="Hint text (optional)."
size={size}
{...{ [validationType]: "Message" }}
/>
Expand All @@ -280,7 +290,7 @@ export const NewDesignsValidation: ComponentStory<typeof Textbox> = () => {
label={`readOnly - ${size} - ${validationType}`}
defaultValue="Textbox"
size={size}
labelHelp="Hint text (optional)"
inputHint="Hint text (optional)."
readOnly
{...{ [validationType]: "Message" }}
/>
Expand Down
Loading
Loading