diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a20138da..e7dc68c285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -420,6 +420,7 @@ Breaking changes in this release: - Fixed virtual keyboard should be collapsed after being suppressed, in iOS 26.3, by [@compulim](https://github.com/compulim) in PR [#5757](https://github.com/microsoft/BotFramework-WebChat/pull/5757) - Fixed Fluent/Copilot typing indicator animation background color, in PR [#5770](https://github.com/microsoft/BotFramework-WebChat/pull/5770), by [@OEvgeny](https://github.com/OEvgeny) - Fixed `` should not re-render when `attachment[ForScreenReader]Middleware` is updated without noticeable different (`iterateEquals`), by [@compulim](https://github.com/compulim), in PR [#5779](https://github.com/microsoft/BotFramework-WebChat/pull/5779) +- Fixed send box should narrate `aria-label` prop, by [@compulim](https://github.com/compulim), in PR [#5805](https://github.com/microsoft/BotFramework-WebChat/pull/5805) ## [4.18.0] - 2024-07-10 diff --git a/__tests__/html2/accessibility/sendBox/ariaLabel.fluent.html b/__tests__/html2/accessibility/sendBox/ariaLabel.fluent.html new file mode 100644 index 0000000000..0889865ec1 --- /dev/null +++ b/__tests__/html2/accessibility/sendBox/ariaLabel.fluent.html @@ -0,0 +1,91 @@ + + + + + + + +
+ + + + + diff --git a/__tests__/html2/accessibility/sendBox/ariaLabel.html b/__tests__/html2/accessibility/sendBox/ariaLabel.html new file mode 100644 index 0000000000..9061c02dc6 --- /dev/null +++ b/__tests__/html2/accessibility/sendBox/ariaLabel.html @@ -0,0 +1,53 @@ + + + + + + +
+ + + + diff --git a/__tests__/html2/accessibility/sendBox/ariaLabel.multilineTextBox.html b/__tests__/html2/accessibility/sendBox/ariaLabel.multilineTextBox.html new file mode 100644 index 0000000000..fd62d44ecf --- /dev/null +++ b/__tests__/html2/accessibility/sendBox/ariaLabel.multilineTextBox.html @@ -0,0 +1,56 @@ + + + + + + +
+ + + + diff --git a/packages/component/src/TextArea/TextArea.tsx b/packages/component/src/TextArea/TextArea.tsx index 8ea830fb0b..a6331257a8 100644 --- a/packages/component/src/TextArea/TextArea.tsx +++ b/packages/component/src/TextArea/TextArea.tsx @@ -1,5 +1,5 @@ -import { hooks } from 'botframework-webchat-api'; import { useStyles } from '@msinternal/botframework-webchat-styles/react'; +import { hooks } from 'botframework-webchat-api'; import cx from 'classnames'; import React, { forwardRef, @@ -8,23 +8,23 @@ import React, { useRef, type FormEventHandler, type KeyboardEventHandler, - type MouseEventHandler, - type ReactNode + type MouseEventHandler } from 'react'; +import { boolean, custom, number, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; +import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot'; import styles from './TextArea.module.css'; const { useUIState } = hooks; -const TextArea = forwardRef< - HTMLTextAreaElement, - Readonly<{ - 'aria-describedby'?: string | undefined; - 'aria-labelledby'?: string | undefined; - className?: string | undefined; - completion?: ReactNode | undefined; - 'data-testid'?: string | undefined; - +const TextAreaPropsSchema = pipe( + object({ + 'aria-describedby': optional(string()), + 'aria-label': optional(string()), + 'aria-labelledby': optional(string()), + className: optional(string()), + completion: optional(reactNode()), + 'data-testid': optional(string()), /** * `true`, if the text area should be hidden but stay in the DOM, otherwise, `false`. * @@ -33,15 +33,22 @@ const TextArea = forwardRef< * - When the DTMF keypad is going away, we need to send focus to the text area before we unmount DTMF keypad, * This ensures the flow of focus did not sent to document body */ - hidden?: boolean | undefined; - onClick?: MouseEventHandler | undefined; - onInput?: FormEventHandler | undefined; - placeholder?: string | undefined; - readOnly?: boolean | undefined; - startRows?: number | undefined; - value?: string | undefined; - }> ->((props, ref) => { + hidden: optional(boolean()), + onClick: optional(custom>(value => typeof value === 'function')), + onInput: optional(custom>(value => typeof value === 'function')), + placeholder: optional(string()), + readOnly: optional(boolean()), + startRows: optional(number()), + value: optional(string()) + }), + readonly() +); + +type TextAreaProps = InferInput; + +const TextArea = forwardRef((rawProps, ref) => { + const props = validateProps(TextAreaPropsSchema, rawProps); + const [uiState] = useUIState(); const classNames = useStyles(styles); const isInCompositionRef = useRef(false); @@ -84,11 +91,12 @@ const TextArea = forwardRef< ) : (
- {props.completion ? props.completion : props.value}{' '} + {props.completion || props.value}{' '}