Skip to content

Commit

Permalink
a11y: improve a11y
Browse files Browse the repository at this point in the history
  • Loading branch information
markov00 committed Jun 6, 2022
1 parent c70c557 commit a0df3bc
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 20 deletions.
2 changes: 2 additions & 0 deletions packages/charts/api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,8 @@ export type MetricWTrend = MetricBase & {
x: number;
y: number;
}[];
trendA11yTitle?: string;
trendA11yDescription?: string;
};

// @public (undocumented)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
padding: 8px;
display: grid;
grid-template-columns: 100%;
grid-template-rows: min-content min-content auto min-content min-content;
grid-template-rows: min-content auto min-content min-content;
height: 100%;
z-index: 1;
&__title {
font-weight: 400;
@include lineClamp(3);
Expand Down
24 changes: 16 additions & 8 deletions packages/charts/src/chart_types/metric/renderer/dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { MetricText } from './text';

interface ReactiveChartStateProps {
initialized: boolean;
chartId: string;
size: {
width: number;
height: number;
Expand Down Expand Up @@ -66,6 +67,7 @@ class Component extends React.Component<Props> {

render() {
const {
chartId,
initialized,
size: { width, height },
a11y,
Expand Down Expand Up @@ -98,6 +100,7 @@ class Component extends React.Component<Props> {
.map((columns, ri) => {
return [
...columns.map((d, ci) => {
const metricHTMLId = `echMetric-${chartId}-${ri}-${ci}`;
// fill undefined with empty panels
const emptyMetricClassName = classNames('echMetric', {
'echMetric--rightBorder': ci < maxColumns - 1,
Expand All @@ -115,11 +118,21 @@ class Component extends React.Component<Props> {

return (
<div
role="figure"
aria-labelledby={d.title && metricHTMLId}
key={`${d.title}${d.subtitle}${d.color}${ci}`}
className={metricPanelClassName}
style={{ backgroundColor: style.background }}
>
{isMetricWTrend(d) && <SparkLine datum={d} curve="linear" />}
<MetricText
id={metricHTMLId}
datum={d}
panel={panel}
style={style}
progressBarMode={progressBarMode}
progressBarOrientation={progressBarOrientation}
/>
{isMetricWTrend(d) && <SparkLine id={metricHTMLId} datum={d} curve="linear" />}
{isMetricWProgress(d) && progressBarMode !== ProgressBarMode.None && (
<ProgressBar
mode={progressBarMode}
Expand All @@ -140,13 +153,6 @@ class Component extends React.Component<Props> {
}}
/>
)}
<MetricText
datum={d}
panel={panel}
style={style}
progressBarMode={progressBarMode}
progressBarOrientation={progressBarOrientation}
/>
</div>
);
}),
Expand Down Expand Up @@ -176,6 +182,7 @@ const mapDispatchToProps = (dispatch: Dispatch): ReactiveChartDispatchProps =>

const DEFAULT_PROPS: ReactiveChartStateProps = {
initialized: false,
chartId: '',
specs: [],
size: {
width: 0,
Expand All @@ -190,6 +197,7 @@ const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
}
return {
initialized: true,
chartId: state.chartId,
specs: getMetricSpecs(state),
size: chartSize(state),
a11y: getA11ySettingsSelector(state),
Expand Down
16 changes: 12 additions & 4 deletions packages/charts/src/chart_types/metric/renderer/dom/progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import { MetricWProgress, MetricSpec, ProgressBarMode } from '../../specs';

/** @internal */
export const ProgressBar: React.FunctionComponent<{
datum: Pick<MetricWProgress, 'domain' | 'value' | 'color'>;
datum: Pick<MetricWProgress, 'title' | 'domain' | 'value' | 'color'>;
mode: MetricSpec['progressBarMode'];
orientation: MetricSpec['progressBarOrientation'];
barBackground: Color;
}> = ({ datum: { domain, value, color }, mode, orientation, barBackground }) => {
}> = ({ datum: { title, domain, value, color }, mode, orientation, barBackground }) => {
const isVertical = orientation === LayoutDirection.Vertical;
const isSmall = mode === ProgressBarMode.Small;
const percent = clamp((domain ? value / (domain.max - domain.min) : 1) * 100, 0, 100);
const percent = Number(clamp((domain ? value / (domain.max - domain.min) : 1) * 100, 0, 100).toFixed(2));

const bgClassName = classNames('echSingleMetricProgress', {
'echSingleMetricProgress--vertical': isVertical,
Expand All @@ -37,7 +37,15 @@ export const ProgressBar: React.FunctionComponent<{
const percentProp = isVertical ? { height: `${percent}%` } : { width: `${percent}%` };
return (
<div className={bgClassName} style={{ background: isSmall ? barBackground : undefined }}>
<div className={barClassName} style={{ background: color, ...percentProp }} />
<div
className={barClassName}
style={{ background: color, ...percentProp }}
role="meter"
aria-label={title ? `Percentage of ${title}` : 'Percentage'}
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={percent}
/>
</div>
);
};
19 changes: 15 additions & 4 deletions packages/charts/src/chart_types/metric/renderer/dom/sparkline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { CurveType } from '../../../../utils/curves';
import { MetricWTrend } from '../../specs';

/** @internal */
export const SparkLine: FunctionComponent<{ datum: MetricWTrend; curve: 'linear' | 'step' }> = ({
datum: { color, trend },
curve,
}) => {
export const SparkLine: FunctionComponent<{
id: string;
datum: MetricWTrend;
curve: 'linear' | 'step';
}> = ({ id, datum: { color, trend, trendA11yTitle, trendA11yDescription }, curve }) => {
if (!trend) {
return null;
}
Expand All @@ -38,6 +39,8 @@ export const SparkLine: FunctionComponent<{ datum: MetricWTrend; curve: 'linear'

const [h, s, l] = colorToHsl(color);
const pathColor = hslToColor(h, s, l >= 0.8 ? l - 0.1 : l + 0.1);
const titleId = `${id}-trend-title`;
const descriptionId = `${id}-trend-description`;
return (
<div className="echSingleMetricSparkline">
<svg
Expand All @@ -46,7 +49,15 @@ export const SparkLine: FunctionComponent<{ datum: MetricWTrend; curve: 'linear'
height="100%"
viewBox="0 0 1 1"
preserveAspectRatio="none"
role="img"
aria-labelledby={`${titleId} ${descriptionId}`}
>
<title id={titleId} className="echScreenReaderOnly">
{trendA11yTitle}
</title>
<text id={descriptionId} className="echScreenReaderOnly">
{trendA11yDescription}
</text>
<rect x={0} y={0} width={1} height={1} fill={color} />
<path
d={path.area(trend)}
Expand Down
13 changes: 10 additions & 3 deletions packages/charts/src/chart_types/metric/renderer/dom/text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ function findRange(ranges: [number, number, string][], value: number) {

/** @internal */
export const MetricText: React.FunctionComponent<{
id: string;
datum: MetricBase | MetricWProgress | MetricWTrend;
progressBarMode: MetricSpec['progressBarMode'];
progressBarOrientation: MetricSpec['progressBarOrientation'];
panel: Size;
style: MetricStyle;
}> = ({ datum, panel, progressBarMode, progressBarOrientation, style }) => {
}> = ({ id, datum, panel, progressBarMode, progressBarOrientation, style }) => {
const isVertical = progressBarOrientation === LayoutDirection.Vertical;
const isSmall = progressBarMode === ProgressBarMode.Small;
const { title, subtitle, extra, value } = datum;
Expand Down Expand Up @@ -78,8 +79,14 @@ export const MetricText: React.FunctionComponent<{

return (
<div className={containerClassName} style={{ color: highContrastTextColor }}>
<div>{title && <h2 className={titleClassName}>{title}</h2>}</div>
<div>{showSubtitle && subtitle && <h3 className={subtitleClassName}>{subtitle}</h3>}</div>
<div>
{title && (
<h2 id={id} className={titleClassName}>
{title}
{showSubtitle && subtitle && <span className={subtitleClassName}> {subtitle}</span>}
</h2>
)}
</div>
<div className="echMetricText__gap"></div>
<div>{extra && <h5 className="echMetricText__extra">{extra}</h5>}</div>
<div>
Expand Down
2 changes: 2 additions & 0 deletions packages/charts/src/chart_types/metric/specs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export type MetricWProgress = MetricBase & {
/** @alpha */
export type MetricWTrend = MetricBase & {
trend: { x: number; y: number }[];
trendA11yTitle?: string;
trendA11yDescription?: string;
};

/** @alpha */
Expand Down
9 changes: 9 additions & 0 deletions storybook/stories/metric/1_basic.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const Example = () => {
title: 'CPU Usage',
subtitle: 'Overall percentage',
trend: KIBANA_METRICS.metrics.kibana_os_load[1].data.map(([x, y]) => ({ x, y })),
trendA11yTitle: 'Last hour CPU percentage trend',
trendA11yDescription:
'The trend shows the CPU Usage in percentage in the last hour. The trend shows a general flat behaviour with peaks every 10 minutes',
valueFormatter: defaultValueFormatter,
},
{
Expand All @@ -49,6 +52,9 @@ export const Example = () => {
title: 'Memory Usage',
subtitle: 'Overall percentage',
trend: KIBANA_METRICS.metrics.kibana_memory[1].data.map(([x, y]) => ({ x, y })),
trendA11yTitle: 'Last hour Memory usage trend',
trendA11yDescription:
'The trend shows the memory usage in the last hour. The trend shows a general flat behaviour across the entire time window',
valueFormatter: (d) => `${d} %`,
},
{
Expand All @@ -57,6 +63,9 @@ export const Example = () => {
title: 'Cloud Revenue',
subtitle: 'Quarterly',
trend: KIBANA_METRICS.metrics.kibana_os_load[1].data.map(([x, y]) => ({ x, y })),
trendA11yTitle: 'Last quarter, daily Cloud Revenue trend',
trendA11yDescription:
'The trend shows the daily Cloud revenue in the last quarter, showing peaks during weekends.',
extra: (
<span>
This Year <b>10M</b>
Expand Down

0 comments on commit a0df3bc

Please sign in to comment.