@@ -15,6 +15,11 @@ import useActivityAccessibleName from './useActivityAccessibleName';
1515import type { WebChatActivity } from 'botframework-webchat-core' ;
1616import type { MouseEventHandler , PropsWithChildren } from 'react' ;
1717import { useRefFrom } from 'use-ref-from' ;
18+ import {
19+ TranscriptFocusContent ,
20+ TranscriptFocusContentActiveDescendant ,
21+ TranscriptFocusContentBody ,
22+ } from './TranscriptFocus' ;
1823
1924const { useActivityKeysByRead, useGetHasAcknowledgedByActivityKey, useGetKeyByActivity } = hooks ;
2025
@@ -58,9 +63,9 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
5863
5964 const focusTrapChildren = useMemo (
6065 ( ) => (
61- < div className = "webchat__basic-transcript__activity-body" ref = { bodyRef } >
66+ < TranscriptFocusContentBody className = "webchat__basic-transcript__activity-body" ref = { bodyRef } >
6267 { children }
63- </ div >
68+ </ TranscriptFocusContentBody >
6469 ) ,
6570 [ bodyRef , children ]
6671 ) ;
@@ -108,14 +113,16 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
108113
109114 return (
110115 // TODO: [P2] Add `aria-roledescription="message"` for better AX, need localization strings.
111- < article
116+ < TranscriptFocusContent
112117 className = { classNames ( 'webchat__basic-transcript__activity' , {
113118 'webchat__basic-transcript__activity--acknowledged' : acknowledged ,
114119 'webchat__basic-transcript__activity--read' : read
115120 } ) }
116- // When NVDA is in browse mode, using up/down arrow key to "browse" will dispatch "click" and "mousedown" events for <article> element (inside <LiveRegionActivity>).
121+ focused = { isActiveDescendant }
117122 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>).
118124 ref = { wrappedRef }
125+ tag = "article"
119126 >
120127 { /* TODO: [P1] File a crbug for TalkBack. It should not able to read the content twice when scanning. */ }
121128
@@ -127,7 +134,7 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
127134 As Android does not support active descendant, we are hiding the whole DOM element altogether. */ }
128135
129136 { ! android && (
130- < div
137+ < TranscriptFocusContentActiveDescendant
131138 aria-labelledby = { descendantLabelId }
132139 className = "webchat__basic-transcript__activity-active-descendant"
133140 // "id" is required for "aria-labelledby"
@@ -136,7 +143,7 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
136143 role = "article"
137144 >
138145 < ScreenReaderText aria-hidden = { true } id = { descendantLabelId } text = { accessibleName } />
139- </ div >
146+ </ TranscriptFocusContentActiveDescendant >
140147 ) }
141148 < FocusTrap
142149 onFocus = { handleDescendantFocus }
@@ -149,12 +156,7 @@ const ActivityRow = forwardRef<HTMLElement, ActivityRowProps>(({ activity, child
149156 // TODO: Should build `webChatActivitySchema`.
150157 < SpeakActivity activity = { activity as WebChatActivity & { channelData : { speechSynthesisUtterance ?: any } } } />
151158 ) }
152- < div
153- className = { classNames ( 'webchat__basic-transcript__activity-indicator' , {
154- 'webchat__basic-transcript__activity-indicator--focus' : isActiveDescendant
155- } ) }
156- />
157- </ article >
159+ </ TranscriptFocusContent >
158160 ) ;
159161} ) ;
160162
0 commit comments