Skip to content

Commit

Permalink
add accessible text
Browse files Browse the repository at this point in the history
  • Loading branch information
dominiqueclarke committed Feb 4, 2021
1 parent b7246a0 commit 063d875
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useMemo, useState } from 'react';
import { EuiHealth, EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui';
import React, { useCallback, useMemo, useState } from 'react';
import { EuiHealth } from '@elastic/eui';
import { getSeriesAndDomain, getSidebarItems, getLegendItems } from './data_formatting';
import { SidebarItem, LegendItem, NetworkItems } from './types';
import {
WaterfallProvider,
WaterfallChart,
MiddleTruncatedText,
RenderItem,
} from '../../waterfall';
import { WaterfallProvider, WaterfallChart, RenderItem } from '../../waterfall';
import { WaterfallFilter } from './waterfall_filter';
import { SideBarItemHighlighter } from '../../waterfall/components/styles';

export const renderSidebarItem: RenderItem<SidebarItem> = (item) => {
const { status, offsetIndex } = item;

const isErrorStatusCode = (statusCode: number) => {
const is400 = statusCode >= 400 && statusCode <= 499;
const is500 = statusCode >= 500 && statusCode <= 599;
const isSpecific300 = statusCode === 301 || statusCode === 307 || statusCode === 308;
return is400 || is500 || isSpecific300;
};

return (
<SideBarItemHighlighter
isHighlighted={item.isHighlighted}
data-test-subj={item.isHighlighted ? 'sideBarHighlightedItem' : 'sideBarDimmedItem'}
>
{!status || !isErrorStatusCode(status) ? (
<MiddleTruncatedText text={`${offsetIndex}. ${item.url}`} />
) : (
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<MiddleTruncatedText text={`${offsetIndex}. ${item.url}`} />
</EuiFlexItem>
<EuiFlexItem component="span" grow={false}>
<EuiBadge color="danger">{status}</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
)}
</SideBarItemHighlighter>
);
};
import { WaterfallSidebarItem } from './waterfall_sidebar_item';

export const renderLegendItem: RenderItem<LegendItem> = (item) => {
return <EuiHealth color={item.colour}>{item.name}</EuiHealth>;
Expand All @@ -64,6 +28,8 @@ export const WaterfallChartWrapper: React.FC<Props> = ({ data, total }) => {

const [networkData] = useState<NetworkItems>(data);

const hasFilters = activeFilters.length > 0;

const { series, domain, totalHighlightedRequests } = useMemo(() => {
return getSeriesAndDomain(networkData, onlyHighlighted, query, activeFilters);
}, [networkData, query, activeFilters, onlyHighlighted]);
Expand All @@ -74,7 +40,7 @@ export const WaterfallChartWrapper: React.FC<Props> = ({ data, total }) => {

const legendItems = getLegendItems();

const renderFilter = () => {
const renderFilter = useCallback(() => {
return (
<WaterfallFilter
query={query}
Expand All @@ -85,7 +51,19 @@ export const WaterfallChartWrapper: React.FC<Props> = ({ data, total }) => {
setOnlyHighlighted={setOnlyHighlighted}
/>
);
};
}, [activeFilters, setActiveFilters, onlyHighlighted, setOnlyHighlighted, query, setQuery]);

const renderSidebarItem: RenderItem<SidebarItem> = useCallback(
(item) => {
return (
<WaterfallSidebarItem
item={item}
renderFilterScreenReaderText={hasFilters && !onlyHighlighted}
/>
);
},
[hasFilters, onlyHighlighted]
);

return (
<WaterfallProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import {
} from '@elastic/eui';
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
import useDebounce from 'react-use/lib/useDebounce';
import { FILTER_REQUESTS_LABEL } from '../../waterfall/components/translations';
import {
FILTER_REQUESTS_LABEL,
FILTER_SCREENREADER_LABEL,
FILTER_REMOVE_SCREENREADER_LABEL,
} from '../../waterfall/components/translations';
import { MimeType } from './types';
import { OPEN_FILTERS_POPOVER } from '../../translations';
import { METRIC_TYPE, useUiTracker } from '../../../../../../../observability/public';
Expand Down Expand Up @@ -146,6 +150,11 @@ export const WaterfallFilter = ({
onClick={() => toggleFilters(mimeType)}
key={label}
withNext={true}
aria-label={`${
activeFilters.includes(mimeType)
? FILTER_REMOVE_SCREENREADER_LABEL
: FILTER_SCREENREADER_LABEL
} ${label}`}
>
{label}
</EuiFilterButton>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui';
import { SidebarItem } from '../waterfall/types';
import { MiddleTruncatedText } from '../../waterfall';
import { SideBarItemHighlighter } from '../../waterfall/components/styles';
import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from '../../waterfall/components/translations';

interface SidebarItemProps {
item: SidebarItem;
renderFilterScreenReaderText?: boolean;
}

export const WaterfallSidebarItem = ({ item, renderFilterScreenReaderText }: SidebarItemProps) => {
const { status, offsetIndex } = item;

const isErrorStatusCode = (statusCode: number) => {
const is400 = statusCode >= 400 && statusCode <= 499;
const is500 = statusCode >= 500 && statusCode <= 599;
const isSpecific300 = statusCode === 301 || statusCode === 307 || statusCode === 308;
return is400 || is500 || isSpecific300;
};

const isHighlighted = item.isHighlighted;
const text = `${offsetIndex}. ${item.url}`;
const ariaLabel = `${
isHighlighted && renderFilterScreenReaderText
? `${SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL} `
: ''
}${text}`;

return (
<SideBarItemHighlighter
isHighlighted={isHighlighted}
data-test-subj={isHighlighted ? 'sideBarHighlightedItem' : 'sideBarDimmedItem'}
>
{!status || !isErrorStatusCode(status) ? (
<MiddleTruncatedText text={text} ariaLabel={ariaLabel} />
) : (
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<MiddleTruncatedText text={text} ariaLabel={ariaLabel} />
</EuiFlexItem>
<EuiFlexItem component="span" grow={false}>
<EuiBadge color="danger">{status}</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
)}
</SideBarItemHighlighter>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { SidebarItem } from '../waterfall/types';

import { render } from '../../../../../lib/helper/rtl_helpers';

import 'jest-canvas-mock';
import { WaterfallSidebarItem } from './waterfall_sidebar_item';
import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from '../../waterfall/components/translations';

describe('waterfall filter', () => {
const url = 'http://www.elastic.co';
const offsetIndex = 1;
const item: SidebarItem = {
url,
isHighlighted: true,
offsetIndex,
};

it('renders sidbar item', () => {
const { getByText } = render(<WaterfallSidebarItem item={item} />);

expect(getByText(`${offsetIndex}. ${url}`));
});

it('render screen reader text when renderFilterScreenReaderText is true', () => {
const { getByLabelText } = render(
<WaterfallSidebarItem item={item} renderFilterScreenReaderText={true} />
);

expect(
getByLabelText(`${SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL} ${offsetIndex}. ${url}`)
).toBeInTheDocument();
});

it('does not render screen reader text when renderFilterScreenReaderText is false', () => {
const { queryByLabelText } = render(
<WaterfallSidebarItem item={item} renderFilterScreenReaderText={false} />
);

expect(
queryByLabelText(`${SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL} ${offsetIndex}. ${url}`)
).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,21 @@ describe('getChunks', () => {
});

describe('Component', () => {
it('renders truncated text', () => {
const { getByText } = render(<MiddleTruncatedText text={longString} />);
it('renders truncated text and aria label', () => {
const { getByText, getByLabelText } = render(
<MiddleTruncatedText text={longString} ariaLabel={longString} />
);

expect(getByText(first)).toBeInTheDocument();
expect(getByText(last)).toBeInTheDocument();

expect(getByLabelText(longString)).toBeInTheDocument();
});

it('renders screen reader only text', () => {
const { getByTestId } = render(<MiddleTruncatedText text={longString} />);
const { getByTestId } = render(
<MiddleTruncatedText text={longString} ariaLabel={longString} />
);

const { getByText } = within(getByTestId('middleTruncatedTextSROnly'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import styled from 'styled-components';
import { EuiScreenReaderOnly, EuiToolTip } from '@elastic/eui';
import { FIXED_AXIS_HEIGHT } from './constants';

interface Props {
ariaLabel: string;
text: string;
}

const OuterContainer = styled.div`
width: 100%;
height: 100%;
Expand Down Expand Up @@ -49,14 +54,14 @@ export const getChunks = (text: string) => {
// Helper component for adding middle text truncation, e.g.
// really-really-really-long....ompressed.js
// Can be used to accomodate content in sidebar item rendering.
export const MiddleTruncatedText = ({ text }: { text: string }) => {
export const MiddleTruncatedText = ({ ariaLabel, text }: Props) => {
const chunks = useMemo(() => {
return getChunks(text);
}, [text]);

return (
<>
<OuterContainer>
<OuterContainer aria-label={ariaLabel} data-test-subj="middleTruncatedTextContainer">
<EuiScreenReaderOnly>
<span data-test-subj="middleTruncatedTextSROnly">{text}</span>
</EuiScreenReaderOnly>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,24 @@ export const FILTER_REQUESTS_LABEL = i18n.translate(
defaultMessage: 'Filter network requests',
}
);

export const FILTER_SCREENREADER_LABEL = i18n.translate(
'xpack.uptime.synthetics.waterfall.filterGroup.filterScreenreaderLabel',
{
defaultMessage: 'Filter by',
}
);

export const FILTER_REMOVE_SCREENREADER_LABEL = i18n.translate(
'xpack.uptime.synthetics.waterfall.filterGroup.removeFilterScreenReaderLabel',
{
defaultMessage: 'Remove filter by',
}
);

export const SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL = i18n.translate(
'xpack.uptime.synthetics.waterfall.sidebar.filterMatchesScreenReaderLabel',
{
defaultMessage: 'Resource matches filter',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@

import React from 'react';
import { WaterfallChart } from './waterfall_chart';
import {
renderLegendItem,
renderSidebarItem,
} from '../../step_detail/waterfall/waterfall_chart_wrapper';
import { renderLegendItem } from '../../step_detail/waterfall/waterfall_chart_wrapper';
import { render } from '../../../../../lib/helper/rtl_helpers';

import 'jest-canvas-mock';
Expand All @@ -28,7 +25,7 @@ describe('waterfall', () => {
barStyleAccessor={(datum) => {
return datum.datum.config.colour;
}}
renderSidebarItem={renderSidebarItem}
renderSidebarItem={undefined}
renderLegendItem={renderLegendItem}
fullHeight={true}
/>
Expand Down

0 comments on commit 063d875

Please sign in to comment.