Skip to content

Commit 34c4074

Browse files
committed
fix: active descendant positioning
1 parent ed6d68a commit 34c4074

2 files changed

Lines changed: 22 additions & 22 deletions

File tree

packages/component/src/Transcript/ActivityRow.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,27 +113,15 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
113113

114114
return (
115115
// TODO: [P2] Add `aria-roledescription="message"` for better AX, need localization strings.
116+
/* TODO: [P1] File a crbug for TalkBack. It should not able to read the content twice when scanning. */
117+
/* The following <div> is designed for active descendant only.
118+
We want to prevent screen reader from scanning the content that is authored only for active descendant.
119+
The specific content should only read when user press UP/DOWN arrow keys to change `aria-activedescendant`.
120+
However, Android TalkBack 12.1 is buggy when the there is an element with ID of one of the `aria-activedescendant` potential candidates,
121+
TalkBack will narrate the message content twice (i.e. content of `bodyRef`), regardless whether the ID is currently set as `aria-activedescendant` or not.
122+
As Android does not support active descendant, we are hiding the whole DOM element altogether. */
116123
<TranscriptFocusContent
117-
className={classNames('webchat__basic-transcript__activity', {
118-
'webchat__basic-transcript__activity--acknowledged': acknowledged,
119-
'webchat__basic-transcript__activity--read': read
120-
})}
121-
focused={isActiveDescendant}
122-
onMouseDownCapture={handleMouseDownCapture}
123-
// When NVDA is in browse mode, using up/down arrow key to "browse" will dispatch "click" and "mousedown" events for <article> element (inside <LiveRegionActivity>).
124-
ref={wrappedRef}
125-
tag="article"
126-
>
127-
{/* TODO: [P1] File a crbug for TalkBack. It should not able to read the content twice when scanning. */}
128-
129-
{/* The following <div> is designed for active descendant only.
130-
We want to prevent screen reader from scanning the content that is authored only for active descendant.
131-
The specific content should only read when user press UP/DOWN arrow keys to change `aria-activedescendant`.
132-
However, Android TalkBack 12.1 is buggy when the there is an element with ID of one of the `aria-activedescendant` potential candidates,
133-
TalkBack will narrate the message content twice (i.e. content of `bodyRef`), regardless whether the ID is currently set as `aria-activedescendant` or not.
134-
As Android does not support active descendant, we are hiding the whole DOM element altogether. */}
135-
136-
{!android && (
124+
activeDescendant={!android && (
137125
<TranscriptFocusContentActiveDescendant
138126
aria-labelledby={descendantLabelId}
139127
className="webchat__basic-transcript__activity-active-descendant"
@@ -144,6 +132,16 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
144132
<ScreenReaderText aria-hidden={true} id={descendantLabelId} text={accessibleName} />
145133
</TranscriptFocusContentActiveDescendant>
146134
)}
135+
className={classNames('webchat__basic-transcript__activity', {
136+
'webchat__basic-transcript__activity--acknowledged': acknowledged,
137+
'webchat__basic-transcript__activity--read': read
138+
})}
139+
focused={isActiveDescendant}
140+
onMouseDownCapture={handleMouseDownCapture}
141+
// When NVDA is in browse mode, using up/down arrow key to "browse" will dispatch "click" and "mousedown" events for <article> element (inside <LiveRegionActivity>).
142+
ref={wrappedRef}
143+
tag="article"
144+
>
147145
<FocusTrap
148146
onFocus={handleDescendantFocus}
149147
onLeave={handleLeaveFocusTrap}

packages/component/src/Transcript/TranscriptFocus/TranscriptFocusContent.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { useStyles } from '@msinternal/botframework-webchat-styles/react';
22
import cx from 'classnames';
3-
import React, { forwardRef, type HTMLAttributes } from 'react';
3+
import React, { forwardRef, ReactNode, type HTMLAttributes } from 'react';
44

55
import styles from './TranscriptFocus.module.css';
66
import TranscriptFocusIndicator from './TranscriptFocusIndicator';
77

88
type TranscriptFocusContentProps = HTMLAttributes<HTMLDivElement> &
99
Readonly<{
10+
activeDescendant?: ReactNode | undefined;
1011
tag?: React.ElementType;
1112
focused?: boolean;
1213
}>;
1314

1415
const TranscriptFocusContent = forwardRef<HTMLDivElement, TranscriptFocusContentProps>(
15-
({ className, children, tag: Tag = 'div', focused = false, ...props }, ref) => {
16+
({ activeDescendant, className, children, tag: Tag = 'div', focused = false, ...props }, ref) => {
1617
const classNames = useStyles(styles);
1718

1819
return (
@@ -25,6 +26,7 @@ const TranscriptFocusContent = forwardRef<HTMLDivElement, TranscriptFocusContent
2526
)}
2627
ref={ref}
2728
>
29+
{activeDescendant}
2830
<div className={classNames['transcript-focus-area__content-root']}>{children}</div>
2931
<TranscriptFocusIndicator />
3032
</Tag>

0 commit comments

Comments
 (0)