[Monitoring] Address multiple accessibility issues (#20619)

* Add screen reader only text for monitoring charts

* Add aria label for completed recoveries

* Ensure we have aria label coverage for monitoring chart tooltips

* Ensure table rows are tabbable and include the number of results at the top

* Use EuiScreenReaderOnly

* Updated copy

* Use EUI

* Remove kui usage

* Use an id instead of aria-label

* Show results in the table footer

* Revert "Show results in the table footer"

This reverts commit d622eb7eb4.

* Show total row count within the monitoring table

* PR feedback

* PR feedback

* Ensure all charts show an interval in the tooltip

* Fix padding issue with the cluster status
This commit is contained in:
Chris Roberson 2018-08-08 10:35:10 -04:00 committed by GitHub
parent cdc4ab6f67
commit dd40ac3dc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 44 deletions

View file

@ -5,11 +5,8 @@
*/
import React from 'react';
import { first, get } from 'lodash';
export function InfoTooltip({ series }) {
const bucketSize = get(first(series), 'bucket_size'); // bucket size will be the same for all metrics in all series
export function InfoTooltip({ series, bucketSize }) {
const tableRows = series.map((item, index) => {
return (
<tr

View file

@ -4,14 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import React, { Fragment } from 'react';
import { get, first } from 'lodash';
import { getTitle } from './get_title';
import { getUnits } from './get_units';
import { MonitoringTimeseries } from './monitoring_timeseries';
import { InfoTooltip } from './info_tooltip';
import {
EuiIconTip, EuiFlexGroup, EuiFlexItem, EuiTitle
EuiIconTip, EuiFlexGroup, EuiFlexItem, EuiTitle, EuiScreenReaderOnly
} from '@elastic/eui';
export function MonitoringTimeseriesContainer({ series, onBrush }) {
@ -19,27 +20,43 @@ export function MonitoringTimeseriesContainer({ series, onBrush }) {
return null; // still loading
}
const title = getTitle(series);
const titleForAriaIds = title.replace(/\s+/, '--');
const units = getUnits(series);
const bucketSize = get(first(series), 'bucket_size'); // bucket size will be the same for all metrics in all series
const seriesScreenReaderTextList = [`Interval: ${bucketSize}`]
.concat(series.map(item => `${item.metric.label}: ${item.metric.description}`));
return (
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" style={{ flexGrow: 0 }}>
<EuiFlexItem>
<EuiTitle>
<h2>
{ getTitle(series) }{ units ? ` (${units})` : '' }
</h2>
<EuiTitle tabIndex="0">
<Fragment>
<EuiScreenReaderOnly><span>This chart is not screen reader accessible</span></EuiScreenReaderOnly>
<h2>
{ getTitle(series) }{ units ? ` (${units})` : '' }
</h2>
</Fragment>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIconTip
anchorClassName="eui-textRight eui-alignMiddle monitoring-chart-tooltip__trigger"
className="monitoring-chart-tooltip__wrapper"
type="iInCircle"
position="right"
content={<InfoTooltip series={series}/>}
/>
<Fragment>
<EuiIconTip
anchorClassName="eui-textRight eui-alignMiddle monitoring-chart-tooltip__trigger"
className="monitoring-chart-tooltip__wrapper"
type="iInCircle"
position="right"
content={<InfoTooltip series={series} bucketSize={bucketSize}/>}
/>
<EuiScreenReaderOnly>
<span id={`monitoringChart${titleForAriaIds}`}>
{seriesScreenReaderTextList.join('. ')}
</span>
</EuiScreenReaderOnly>
</Fragment>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import React, { Fragment } from 'react';
import { ClusterStatus } from '../cluster_status';
import { ShardActivity } from '../shard_activity';
import { MonitoringTimeseriesContainer } from '../../chart';
@ -24,24 +24,24 @@ export function ElasticsearchOverview({
];
return (
<EuiPage style={{ backgroundColor: 'white' }}>
<EuiPageBody>
<ClusterStatus stats={clusterStatus} />
<EuiFlexGrid columns={2} gutterSize="none">
{metricsToShow.map((metric, index) => (
<EuiFlexItem key={index} style={{ width: '50%' }}>
<MonitoringTimeseriesContainer
series={metric}
{...props}
/>
<EuiSpacer size="m"/>
</EuiFlexItem>
))}
</EuiFlexGrid>
<ShardActivity data={shardActivity} {...props} />
</EuiPageBody>
</EuiPage>
<Fragment>
<ClusterStatus stats={clusterStatus} />
<EuiPage style={{ backgroundColor: 'white' }}>
<EuiPageBody>
<EuiFlexGrid columns={2} gutterSize="none">
{metricsToShow.map((metric, index) => (
<EuiFlexItem key={index} style={{ width: '50%' }}>
<MonitoringTimeseriesContainer
series={metric}
{...props}
/>
<EuiSpacer size="m"/>
</EuiFlexItem>
))}
</EuiFlexGrid>
<ShardActivity data={shardActivity} {...props} />
</EuiPageBody>
</EuiPage>
</Fragment>
);
}

View file

@ -56,6 +56,7 @@ const ToggleCompletedSwitch = ({ toggleHistory, showHistory }) => (
<KuiToolBarSection>
<KuiToolBarText>
<EuiSwitch
id="monitoring_completed_recoveries"
label="Completed recoveries"
onChange={toggleHistory}
checked={showHistory}

View file

@ -256,6 +256,7 @@ export class MonitoringTable extends React.Component {
pageIndexFirstRow={numVisibleRows ? firstRow + 1 : 0}
pageIndexLastRow={numVisibleRows ? numVisibleRows + firstRow : 0}
rowsFiltered={numAvailableRows}
totalRows={this.state.rows.length}
filterText={this.state.filterText}
paginationControls={this.getPaginationControls(numAvailableRows, this.props.alwaysShowPageControls)}
onFilterChange={this.onFilterChange}

View file

@ -37,9 +37,18 @@ export function MonitoringTableToolBar(props) {
)
: null;
const totalRows = Boolean(props.showTotalRows)
? (
<p tabIndex="0" className="monitoringTableToolbarTotalRows">
{props.totalRows} in total
</p>
)
: null;
return (
<KuiToolBar>
{ searchBox }
{ totalRows }
{ props.renderToolBarSections(props) }
{ paginationSection }
</KuiToolBar>
@ -47,5 +56,6 @@ export function MonitoringTableToolBar(props) {
}
MonitoringTableToolBar.defaultProps = {
renderToolBarSections: noop,
showSearchBox: true
showSearchBox: true,
showTotalRows: true
};

View file

@ -54,17 +54,17 @@ const alertRowFactory = (scope, kbnUrl) => {
return (
<KuiTableRow>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
<Tooltip text={severityIcon.title} placement="bottom" trigger="hover">
<EuiHealth color={severityIcon.color} data-test-subj="alertIcon" aria-label={severityIcon.title}>
{ capitalize(severityIcon.value) }
</EuiHealth>
</Tooltip>
</KuiTableRowCell>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
{ resolution.icon } { resolution.text }
</KuiTableRowCell>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
<FormattedMessage
prefix={props.prefix}
suffix={props.suffix}
@ -73,13 +73,13 @@ const alertRowFactory = (scope, kbnUrl) => {
changeUrl={changeUrl}
/>
</KuiTableRowCell>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
{ linkToCategories[props.metadata.link] ? linkToCategories[props.metadata.link] : 'General' }
</KuiTableRowCell>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
{ formatDateTimeLocal(props.update_timestamp) }
</KuiTableRowCell>
<KuiTableRowCell>
<KuiTableRowCell tabIndex="0">
{ formatTimestampToDuration(props.timestamp, CALCULATE_DURATION_SINCE) } ago
</KuiTableRowCell>
</KuiTableRow>

View file

@ -60,3 +60,7 @@
color: #666977;
font-size: 12px;
}
.monitoringTableToolbarTotalRows {
flex: 2; /* This is to ensure this shows directly next to the search bar in the table toolbar */
}