Skip to content

Commit 9c7e294

Browse files
Support standard HTML aria attribute names
Add support for standard HTML aria attribute names (aria-describedby, aria-invalid, aria-labelledby, aria-required) in addition to the existing camelCase prop names (ariaDescribedBy, ariaInvalid, ariaLabelledBy, ariaRequired). The standard HTML attribute names take precedence when both are provided. This allows developers to use the familiar HTML attribute syntax when passing aria attributes to the DatePicker component, including when using custom inputs. Fixes #5580 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 43acb66 commit 9c7e294

2 files changed

Lines changed: 106 additions & 4 deletions

File tree

src/index.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ export type DatePickerProps = OmitUnion<
194194
ariaInvalid?: string;
195195
ariaLabelledBy?: string;
196196
ariaRequired?: string;
197+
"aria-describedby"?: string;
198+
"aria-invalid"?: string;
199+
"aria-labelledby"?: string;
200+
"aria-required"?: string;
197201
rangeSeparator?: string;
198202
onChangeRaw?: (
199203
event?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
@@ -1596,10 +1600,12 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
15961600
readOnly: this.props.readOnly,
15971601
required: this.props.required,
15981602
tabIndex: this.props.tabIndex,
1599-
"aria-describedby": this.props.ariaDescribedBy,
1600-
"aria-invalid": this.props.ariaInvalid,
1601-
"aria-labelledby": this.props.ariaLabelledBy,
1602-
"aria-required": this.props.ariaRequired,
1603+
"aria-describedby":
1604+
this.props["aria-describedby"] ?? this.props.ariaDescribedBy,
1605+
"aria-invalid": this.props["aria-invalid"] ?? this.props.ariaInvalid,
1606+
"aria-labelledby":
1607+
this.props["aria-labelledby"] ?? this.props.ariaLabelledBy,
1608+
"aria-required": this.props["aria-required"] ?? this.props.ariaRequired,
16031609
});
16041610
};
16051611

src/test/datepicker_test.test.tsx

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4273,6 +4273,102 @@ describe("DatePicker", () => {
42734273
});
42744274
});
42754275

4276+
describe("aria attributes on input", () => {
4277+
it("should pass aria-describedby to the input using standard HTML attribute name", () => {
4278+
const { container } = render(
4279+
<DatePicker selected={newDate()} aria-describedby="description-id" />,
4280+
);
4281+
const input = safeQuerySelector(container, "input");
4282+
expect(input.getAttribute("aria-describedby")).toBe("description-id");
4283+
});
4284+
4285+
it("should pass aria-describedby to the input using camelCase prop name", () => {
4286+
const { container } = render(
4287+
<DatePicker selected={newDate()} ariaDescribedBy="description-id" />,
4288+
);
4289+
const input = safeQuerySelector(container, "input");
4290+
expect(input.getAttribute("aria-describedby")).toBe("description-id");
4291+
});
4292+
4293+
it("should prefer standard HTML attribute name over camelCase for aria-describedby", () => {
4294+
const { container } = render(
4295+
<DatePicker
4296+
selected={newDate()}
4297+
aria-describedby="standard-id"
4298+
ariaDescribedBy="camelcase-id"
4299+
/>,
4300+
);
4301+
const input = safeQuerySelector(container, "input");
4302+
expect(input.getAttribute("aria-describedby")).toBe("standard-id");
4303+
});
4304+
4305+
it("should pass aria-invalid to the input using standard HTML attribute name", () => {
4306+
const { container } = render(
4307+
<DatePicker selected={newDate()} aria-invalid="true" />,
4308+
);
4309+
const input = safeQuerySelector(container, "input");
4310+
expect(input.getAttribute("aria-invalid")).toBe("true");
4311+
});
4312+
4313+
it("should pass aria-invalid to the input using camelCase prop name", () => {
4314+
const { container } = render(
4315+
<DatePicker selected={newDate()} ariaInvalid="true" />,
4316+
);
4317+
const input = safeQuerySelector(container, "input");
4318+
expect(input.getAttribute("aria-invalid")).toBe("true");
4319+
});
4320+
4321+
it("should pass aria-labelledby to the input using standard HTML attribute name", () => {
4322+
const { container } = render(
4323+
<DatePicker selected={newDate()} aria-labelledby="label-id" />,
4324+
);
4325+
const input = safeQuerySelector(container, "input");
4326+
expect(input.getAttribute("aria-labelledby")).toBe("label-id");
4327+
});
4328+
4329+
it("should pass aria-labelledby to the input using camelCase prop name", () => {
4330+
const { container } = render(
4331+
<DatePicker selected={newDate()} ariaLabelledBy="label-id" />,
4332+
);
4333+
const input = safeQuerySelector(container, "input");
4334+
expect(input.getAttribute("aria-labelledby")).toBe("label-id");
4335+
});
4336+
4337+
it("should pass aria-required to the input using standard HTML attribute name", () => {
4338+
const { container } = render(
4339+
<DatePicker selected={newDate()} aria-required="true" />,
4340+
);
4341+
const input = safeQuerySelector(container, "input");
4342+
expect(input.getAttribute("aria-required")).toBe("true");
4343+
});
4344+
4345+
it("should pass aria-required to the input using camelCase prop name", () => {
4346+
const { container } = render(
4347+
<DatePicker selected={newDate()} ariaRequired="true" />,
4348+
);
4349+
const input = safeQuerySelector(container, "input");
4350+
expect(input.getAttribute("aria-required")).toBe("true");
4351+
});
4352+
4353+
it("should pass aria attributes to custom input using standard HTML attribute names", () => {
4354+
const { container } = render(
4355+
<DatePicker
4356+
selected={newDate()}
4357+
customInput={<CustomInput />}
4358+
aria-describedby="desc-id"
4359+
aria-invalid="true"
4360+
aria-labelledby="label-id"
4361+
aria-required="true"
4362+
/>,
4363+
);
4364+
const input = safeQuerySelector(container, "input");
4365+
expect(input.getAttribute("aria-describedby")).toBe("desc-id");
4366+
expect(input.getAttribute("aria-invalid")).toBe("true");
4367+
expect(input.getAttribute("aria-labelledby")).toBe("label-id");
4368+
expect(input.getAttribute("aria-required")).toBe("true");
4369+
});
4370+
});
4371+
42764372
it("should not customize the className attribute if showIcon is set to false", () => {
42774373
const { container } = render(
42784374
<DatePicker selected={newDate("2021-04-15")} />,

0 commit comments

Comments
 (0)