From c522def046464a392f50859667689c0fe00cea58 Mon Sep 17 00:00:00 2001 From: Doug MacKenzie Date: Fri, 24 Nov 2023 12:18:48 +1100 Subject: [PATCH] fix(RTE): Move aria-describedby to textbox element (#55) * fix(RTE): Move aria-describedby to textbox element * Add changeset --- .changeset/large-ants-attend.md | 5 ++ .../RichTextEditor/RichTextEditor.spec.tsx | 48 +++++++++++++++++++ .../src/RichTextEditor/RichTextEditor.tsx | 27 ++++++----- 3 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 .changeset/large-ants-attend.md diff --git a/.changeset/large-ants-attend.md b/.changeset/large-ants-attend.md new file mode 100644 index 0000000..e25ec08 --- /dev/null +++ b/.changeset/large-ants-attend.md @@ -0,0 +1,5 @@ +--- +"@kaizen/rich-text-editor": patch +--- + +aria-describedby put on textbox element instead of container div diff --git a/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.spec.tsx b/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.spec.tsx index b474315..8232172 100644 --- a/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.spec.tsx +++ b/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.spec.tsx @@ -44,6 +44,54 @@ const TestRTE = ( ) } +describe("accessible name and description", () => { + it("has the correct accessible name", () => { + render() + expect( + screen.getByRole("textbox", { name: "Some label" }) + ).toBeInTheDocument() + }) + + it("has the correct name and description when added with aria-labelledby and aria-describedby", () => { + render( + <> +
External label
+
External description
+ + + ) + expect( + screen.getByRole("textbox", { + name: "External label", + description: "External description", + }) + ).toBeInTheDocument() + }) + + it("has the correct description with a description passed in, validation error, and aria-describedby", () => { + render( + <> +
External description
+ + + ) + expect( + screen.getByRole("textbox", { + name: "Some label", + description: "Some error Some help text External description", + }) + ).toBeInTheDocument() + }) +}) + describe("RTE receives list controls", () => { it("renders list buttons when receiving a list controls", () => { render() diff --git a/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.tsx b/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.tsx index cf355f0..500cb7d 100644 --- a/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.tsx +++ b/packages/rich-text-editor/src/RichTextEditor/RichTextEditor.tsx @@ -82,6 +82,15 @@ export const RichTextEditor = (props: RichTextEditorProps): JSX.Element => { ) const [labelId] = useState(labelledBy || v4()) const [editorId] = useState(v4()) + const validationMessageAria = validationMessage + ? `${editorId}-rte-validation-message` + : "" + const descriptionAria = description ? `${editorId}-rte-description` : "" + const ariaDescribedBy = classnames( + validationMessageAria, + descriptionAria, + describedBy + ) const useRichTextEditorResult = ((): | ReturnType @@ -99,7 +108,11 @@ export const RichTextEditor = (props: RichTextEditorProps): JSX.Element => { schema, plugins: getPlugins(controls, schema), }), - { "aria-labelledby": labelId, role: "textbox" } + { + "aria-labelledby": labelId, + role: "textbox", + "aria-describedby": ariaDescribedBy, + } ) } catch { return new Error("Bad data error") @@ -124,17 +137,6 @@ export const RichTextEditor = (props: RichTextEditorProps): JSX.Element => { // Including `onContentChange` in the dependencies here will cause a 'Maximum update depth exceeded' issue }, [editorState]) - const validationMessageAria = validationMessage - ? `${editorId}-rte-validation-message` - : "" - const descriptionAria = description ? `${editorId}-rte-description` : "" - - const ariaDescribedBy = classnames( - validationMessageAria, - descriptionAria, - describedBy - ) - return ( <> {!labelledBy && labelText &&