Skip to content

Commit b744224

Browse files
committed
Use roles instead of invalid table HTML in the View list
This mostly undoes b837c63. Unfortunately it's *still* technically invalid (because of divs between the outer table & inner rows) but it's mildly less invalid than the actual table elements (which have tighter requirements than manually added roles), it doesn't generate annoying React warnings about DOM validation structure, and hopefully it's still useful metadata that some screen readers/etc will succesfully manage to interpret. I think this is still something of a work in progress, but unfortunately it seems that react-window (and maybe all virtual windowing unavoidably) requires intermediate divs that are incompatible with the correct HTML structure for a table.
1 parent ecd4006 commit b744224

File tree

1 file changed

+32
-27
lines changed

1 file changed

+32
-27
lines changed

src/components/view/view-event-list.tsx

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ interface ViewEventListProps {
5959
onSelected: (event: CollectedEvent | undefined) => void;
6060
}
6161

62-
const ListContainer = styled.table`
62+
const ListContainer = styled.div<{ role: 'table' }>`
6363
display: block;
6464
flex-grow: 1;
6565
position: relative;
@@ -80,7 +80,7 @@ const ListContainer = styled.table`
8080
}
8181
`;
8282

83-
const Column = styled.td`
83+
const Column = styled.div<{ role: 'cell' | 'columnheader' }>`
8484
display: block;
8585
overflow: hidden;
8686
text-overflow: ellipsis;
@@ -136,7 +136,7 @@ const RowMarker = styled(Column)`
136136
border-left: 5px solid ${p => p.theme.containerBackground};
137137
`;
138138

139-
const MarkerHeader = styled.td`
139+
const MarkerHeader = styled.div<{ role: 'columnheader' }>`
140140
flex-basis: 10px;
141141
flex-shrink: 0;
142142
`;
@@ -223,7 +223,7 @@ const BuiltInApiRequestDetails = styled(Column)`
223223
flex-basis: 1000px;
224224
`;
225225

226-
const EventListRow = styled.tr`
226+
const EventListRow = styled.div<{ role: 'row' }>`
227227
display: flex;
228228
flex-direction: row;
229229
align-items: center;
@@ -289,7 +289,7 @@ const TlsListRow = styled(EventListRow)`
289289
}
290290
`;
291291

292-
export const TableHeaderRow = styled.tr`
292+
export const TableHeaderRow = styled.div<{ role: 'row' }>`
293293
height: 38px;
294294
overflow: hidden;
295295
width: 100%;
@@ -308,7 +308,7 @@ export const TableHeaderRow = styled.tr`
308308
padding-right: 18px;
309309
box-sizing: border-box;
310310
311-
> td {
311+
> div[role=columnheader] {
312312
padding: 5px 0;
313313
margin-right: 10px;
314314
min-width: 0px;
@@ -399,6 +399,7 @@ const ExchangeRow = inject('uiStore')(observer(({
399399
} = exchange;
400400

401401
return <TrafficEventListRow
402+
role="row"
402403
aria-label={
403404
`${_.startCase(exchange.category)} ${
404405
request.method
@@ -426,9 +427,9 @@ const ExchangeRow = inject('uiStore')(observer(({
426427
style={style}
427428
>
428429
<RowPin aria-label={pinned ? 'Pinned' : undefined} pinned={pinned}/>
429-
<RowMarker category={category} title={describeEventCategory(category)} />
430-
<Method pinned={pinned}>{ request.method }</Method>
431-
<Status>
430+
<RowMarker role='cell' category={category} title={describeEventCategory(category)} />
431+
<Method role='cell' pinned={pinned}>{ request.method }</Method>
432+
<Status role='cell'>
432433
{
433434
response === 'aborted'
434435
? <StatusCode status={'aborted'} />
@@ -451,7 +452,7 @@ const ExchangeRow = inject('uiStore')(observer(({
451452
/>
452453
}
453454
</Status>
454-
<Source>
455+
<Source role='cell'>
455456
<Icon
456457
title={request.source.summary}
457458
{...request.source.icon}
@@ -474,10 +475,10 @@ const ExchangeRow = inject('uiStore')(observer(({
474475
/>
475476
}
476477
</Source>
477-
<Host title={ request.parsedUrl.host }>
478+
<Host role='cell' title={ request.parsedUrl.host }>
478479
{ request.parsedUrl.host }
479480
</Host>
480-
<PathAndQuery title={ request.parsedUrl.pathname + request.parsedUrl.search }>
481+
<PathAndQuery role='cell' title={ request.parsedUrl.pathname + request.parsedUrl.search }>
481482
{ request.parsedUrl.pathname + request.parsedUrl.search }
482483
</PathAndQuery>
483484
</TrafficEventListRow>;
@@ -505,6 +506,7 @@ const RTCConnectionRow = observer(({
505506
const { category, pinned } = event;
506507

507508
return <TrafficEventListRow
509+
role="row"
508510
aria-label={
509511
`${
510512
event.closeState ? 'Closed' : 'Open'
@@ -524,17 +526,17 @@ const RTCConnectionRow = observer(({
524526
style={style}
525527
>
526528
<RowPin pinned={pinned}/>
527-
<RowMarker category={category} title={describeEventCategory(category)} />
528-
<EventTypeColumn>
529+
<RowMarker role='cell' category={category} title={describeEventCategory(category)} />
530+
<EventTypeColumn role='cell'>
529531
{ !event.closeState && <ConnectedSpinnerIcon /> } WebRTC
530532
</EventTypeColumn>
531-
<Source title={event.source.summary}>
533+
<Source role='cell' title={event.source.summary}>
532534
<Icon
533535
{...event.source.icon}
534536
fixedWidth={true}
535537
/>
536538
</Source>
537-
<RTCConnectionDetails>
539+
<RTCConnectionDetails role='cell'>
538540
{
539541
event.clientURL
540542
} <ArrowIcon direction='right' /> {
@@ -558,6 +560,7 @@ const RTCStreamRow = observer(({
558560
const { category, pinned } = event;
559561

560562
return <TrafficEventListRow
563+
role="row"
561564
aria-label={
562565
`${
563566
event.closeState ? 'Closed' : 'Open'
@@ -591,25 +594,25 @@ const RTCStreamRow = observer(({
591594
style={style}
592595
>
593596
<RowPin pinned={pinned}/>
594-
<RowMarker category={category} title={describeEventCategory(category)} />
595-
<EventTypeColumn>
597+
<RowMarker role='cell' category={category} title={describeEventCategory(category)} />
598+
<EventTypeColumn role='cell'>
596599
{ !event.closeState && <ConnectedSpinnerIcon /> } WebRTC {
597600
event.isRTCDataChannel()
598601
? 'Data'
599602
: // RTCMediaTrack:
600603
'Media'
601604
}
602605
</EventTypeColumn>
603-
<Source title={event.rtcConnection.source.summary}>
606+
<Source role='cell' title={event.rtcConnection.source.summary}>
604607
<Icon
605608
{...event.rtcConnection.source.icon}
606609
fixedWidth={true}
607610
/>
608611
</Source>
609-
<RTCEventLabel>
612+
<RTCEventLabel role='cell'>
610613
<ArrowIcon direction='right' /> { event.rtcConnection.remoteURL }
611614
</RTCEventLabel>
612-
<RTCEventDetails>
615+
<RTCEventDetails role='cell'>
613616
{
614617
event.isRTCDataChannel()
615618
? <>
@@ -658,6 +661,7 @@ const BuiltInApiRow = observer((p: {
658661
.join(', ');
659662

660663
return <TrafficEventListRow
664+
role="row"
661665
aria-label={
662666
`${_.startCase(category)} ${
663667
api.service.shortName
@@ -680,17 +684,17 @@ const BuiltInApiRow = observer((p: {
680684
style={p.style}
681685
>
682686
<RowPin pinned={pinned}/>
683-
<RowMarker category={category} title={describeEventCategory(category)} />
684-
<EventTypeColumn>
687+
<RowMarker role='cell' category={category} title={describeEventCategory(category)} />
688+
<EventTypeColumn role='cell'>
685689
{ api.service.shortName }: { apiOperationName }
686690
</EventTypeColumn>
687-
<Source title={request.source.summary}>
691+
<Source role='cell' title={request.source.summary}>
688692
<Icon
689693
{...request.source.icon}
690694
fixedWidth={true}
691695
/>
692696
</Source>
693-
<BuiltInApiRequestDetails>
697+
<BuiltInApiRequestDetails role='cell'>
694698
{ apiRequestDescription }
695699
</BuiltInApiRequestDetails>
696700
</TrafficEventListRow>
@@ -717,6 +721,7 @@ const TlsRow = observer((p: {
717721
const connectionTarget = tlsEvent.upstreamHostname || 'unknown domain';
718722

719723
return <TlsListRow
724+
role="row"
720725
aria-label={`${description} connection to ${connectionTarget}`}
721726
aria-rowindex={p.index + 1}
722727
data-event-id={tlsEvent.id}
@@ -774,8 +779,8 @@ export class ViewEventList extends React.Component<ViewEventListProps> {
774779
render() {
775780
const { events, filteredEvents, isPaused } = this.props;
776781

777-
return <ListContainer>
778-
<TableHeaderRow>
782+
return <ListContainer role="table">
783+
<TableHeaderRow role="row">
779784
<MarkerHeader role="columnheader" aria-label="Category" />
780785
<Method role="columnheader">Method</Method>
781786
<Status role="columnheader">Status</Status>

0 commit comments

Comments
 (0)