Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] add an accessible label to range slider #205308

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,42 @@ import React from 'react';
import { I18nProvider } from '@kbn/i18n-react';
import { ControlSlider } from '.';

const values = [
{
label: '.001%',
value: 0.00001,
accessibleLabel: 'Point zero zero one percent, most performant',
},
{
label: '.01%',
value: 0.0001,
},
{
label: '.1%',
value: 0.001,
},
{
label: '1%',
value: 0.01,
},
{
label: '10%',
value: 0.1,
},
{
label: '100%',
value: 1,
accessibleLabel: 'One hundred percent, most accurate',
},
];

describe('Slider Control', () => {
it('should basically work', () => {
render(
<I18nProvider>
<ControlSlider
values={[0.1, 1]}
currentValue={0.1}
values={values}
currentValue={0.00001}
onChange={jest.fn()}
data-test-subj="test-id"
/>
Expand All @@ -26,18 +55,35 @@ describe('Slider Control', () => {
expect(input.value).toBe('0'); // index 0 of the values array
});

it('should display accessible label when provided', () => {
render(
<I18nProvider>
<ControlSlider
values={values}
currentValue={0.00001}
onChange={jest.fn()}
data-test-subj="test-id"
/>
</I18nProvider>
);
const input = screen.getByTestId('test-id') as HTMLInputElement;
expect(input.getAttribute('aria-valuetext')).toBe(
'0, (Point zero zero one percent, most performant)'
);
});

it('should fallback to 1 when the provided value is not present within the values', () => {
render(
<I18nProvider>
<ControlSlider
values={[0.1, 0.5, 1]}
currentValue={2}
values={values}
currentValue={4}
onChange={jest.fn()}
data-test-subj="test-id"
/>
</I18nProvider>
);
const input = screen.getByTestId('test-id') as HTMLInputElement;
expect(input.value).toBe('2'); // index 2 of the values array
expect(input.value).toBe('5'); // index 5 of the values array
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiRange, EuiText, useEuiTheme } from '@elas
import React from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { TooltipWrapper } from '@kbn/visualization-utils';
import { i18n } from '@kbn/i18n';

export interface ControlSliderProps {
/** Allowed values to show on the Control Slider */
values: number[];
values: Array<{ label: string; value: number; accessibleLabel?: string }>;
/** Current value set */
currentValue: number | undefined;
/** When set will show the control in a disabled state */
Expand All @@ -34,8 +35,10 @@ export function ControlSlider({
'data-test-subj': dataTestSubj,
}: ControlSliderProps) {
const { euiTheme } = useEuiTheme();
const samplingIndex = values.findIndex((v) => v === currentValue);

const samplingIndex = values.findIndex((v) => v.value === currentValue);
const currentSamplingIndex = samplingIndex > -1 ? samplingIndex : values.length - 1;

return (
<TooltipWrapper
tooltipContent={disabledReason}
Expand All @@ -58,22 +61,28 @@ export function ControlSlider({
<EuiFlexItem>
<EuiRange
data-test-subj={dataTestSubj}
aria-label={i18n.translate('randomSampling.ui.sliderControl.ariaLabel', {
defaultMessage: 'Sampling percentages',
})}
aria-describedby={i18n.translate('randomSampling.ui.sliderControl.ariaDescribedby', {
defaultMessage:
'Lower sampling percentages increases the performance, but lowers the accuracy. Lower sampling percentages are best for large datasets.',
})}
value={currentSamplingIndex}
disabled={disabled}
fullWidth
onChange={(e) => {
onChange(values[Number(e.currentTarget.value)]);
onChange(values[Number(e.currentTarget.value)].value);
}}
showInput={false}
showRange={false}
showTicks
step={1}
min={0}
max={values.length - 1}
ticks={values.map((v, i) => ({
// Remove the initial 0 from values with decimal digits: 0.001 => .001
label: `${v * 100}%`.slice(Number.isInteger(v * 100) ? 0 : 1),
value: i,
ticks={values.map((tick, index) => ({
...tick,
value: index,
}))}
/>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"kbn_references": [
"@kbn/i18n-react",
"@kbn/visualization-utils",
"@kbn/i18n",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,38 @@ import { IgnoreGlobalFilterRowControl } from '../../shared_components/ignore_glo
import { trackUiCounterEvents } from '../../lens_ui_telemetry';
import { ExperimentalBadge } from '../../shared_components';

const samplingValues = [0.00001, 0.0001, 0.001, 0.01, 0.1, 1];
const samplingValues = [
{
label: '.001%',
value: 0.00001,
accessibleLabel: i18n.translate('randomSampling.ui.sliderControl.tickLabels.0.00001', {
defaultMessage: 'Point zero zero one percent, most performant',
}),
},
{
label: '.01%',
value: 0.0001,
},
{
label: '.1%',
value: 0.001,
},
{
label: '1%',
value: 0.01,
},
{
label: '10%',
value: 0.1,
},
{
label: '100%',
value: 1,
accessibleLabel: i18n.translate('randomSampling.ui.sliderControl.tickLabels.1', {
defaultMessage: 'One hundred percent, most accurate',
}),
},
];

export function LayerSettingsPanel({
state,
Expand All @@ -26,7 +57,7 @@ export function LayerSettingsPanel({
}: DatasourceLayerSettingsProps<FormBasedPrivateState>) {
const isSamplingValueDisabled = !isSamplingValueEnabled(state.layers[layerId]);
const currentValue = isSamplingValueDisabled
? samplingValues[samplingValues.length - 1]
? samplingValues[samplingValues.length - 1].value
: state.layers[layerId].sampling;

return (
Expand Down