diff --git a/.changelog/5915-fix-ac-selectable-figure.md b/.changelog/5915-fix-ac-selectable-figure.md new file mode 100644 index 0000000000..471322e10b --- /dev/null +++ b/.changelog/5915-fix-ac-selectable-figure.md @@ -0,0 +1,4 @@ +### Fixed + +- Fixed [#5049](https://github.com/microsoft/BotFramework-WebChat/issues/5049), Adaptive Cards without a label being announced as an unnamed figure by screen readers, in PR [#5915](https://github.com/microsoft/BotFramework-WebChat/pull/5915), by [@OEvgeny](https://github.com/OEvgeny) +- Fixed [#5130](https://github.com/microsoft/BotFramework-WebChat/issues/5130), clickable containers and images in Adaptive Cards not showing a pointer cursor, in PR [#5915](https://github.com/microsoft/BotFramework-WebChat/pull/5915), by [@OEvgeny](https://github.com/OEvgeny) diff --git a/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html index e109cad126..bc5e1ff5be 100644 --- a/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html +++ b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html @@ -2,6 +2,8 @@
+ + @@ -12,7 +14,11 @@ run(async function () { const { directLine, store } = testHelpers.createDirectLineEmulator(); - WebChat.renderWebChat({ directLine, store }, document.getElementById('webchat')); + // GIVEN: Web Chat keeps the live region copy of new messages, so it can be seen in the snapshot. + WebChat.renderWebChat( + { directLine, store, styleOptions: { hideSendBox: true, internalLiveRegionFadeAfter: 60000 } }, + document.getElementById('webchat') + ); await pageConditions.uiConnected(); @@ -38,7 +44,7 @@ type: 'AdaptiveCard', $schema: 'http://adaptivecards.io/schemas/adaptive-card.json', version: '1.5', - speak: 'Hello, World!', + speak: 'Please enter your full name', body: [ { type: 'Input.Text', @@ -66,6 +72,11 @@ expect(secondAdaptiveCard.getAttribute('aria-label')).toBeTruthy(); expect(secondAdaptiveCard.getAttribute('role')).toBe('form'); + + await pageConditions.liveRegionStabilized(); + + // THEN: The live region shows what screen readers announce: "Bot said:", one line per card from its "speak" property ("A card: Hello, World!", "A card: Please enter your full name"), then the input of the second card. + await host.snapshot('local'); }); diff --git a/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html.snap-1.png b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html.snap-1.png new file mode 100644 index 0000000000..8faa5f0863 Binary files /dev/null and b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.html.snap-1.png differ diff --git a/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html new file mode 100644 index 0000000000..8f7c4e1af5 --- /dev/null +++ b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + diff --git a/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html.snap-1.png b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html.snap-1.png new file mode 100644 index 0000000000..5d9f9283d2 Binary files /dev/null and b/__tests__/html2/accessibility/adaptiveCard/hack.roleMod.unlabelled.html.snap-1.png differ diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardHacks/useRoleModEffect.ts b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardHacks/useRoleModEffect.ts index 2c84be189d..ccd4575e8e 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardHacks/useRoleModEffect.ts +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardHacks/useRoleModEffect.ts @@ -29,6 +29,9 @@ import type { AdaptiveCard } from 'adaptivecards'; * This violates WAI-ARIA because "aria-label" must not be set on an element without a "role". * * We need to set "role" attribute to "form" if the card has any input fields and is valid as a "form" role, otherwise, "figure". + * + * Without a label, the card gets no "role": "figure" and "form" take their names from the author only, + * so a nameless "figure" or "form" would be announced without its content. */ export default function useRoleModEffect( adaptiveCard: AdaptiveCard @@ -43,7 +46,9 @@ export default function useRoleModEffect( cardElement.getAttribute('aria-labelledby') || cardElement.getAttribute('title') ? 'form' - : 'figure' + : cardElement.getAttribute('aria-label') + ? 'figure' + : false ), [] ); diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css index 56de9e2419..818b4258f2 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css @@ -17,6 +17,11 @@ padding: var(--webchat__padding--regular); } + /* Elements with "selectAction", such as containers and images, are clickable. Push buttons keep the default cursor of buttons. */ + :global(.ac-selectable:not(.ac-pushButton)) { + cursor: pointer; + } + :global(.ac-pushButton) { appearance: none; background-color: white;