Skip to content

Commit ed57283

Browse files
[Lens] add an accessible label to range slider (elastic#205308)
## Summary Fixes elastic#182765 (with the solution suggested by @1Copenut) --------- Co-authored-by: kibanamachine <[email protected]>
1 parent 235d5eb commit ed57283

File tree

4 files changed

+104
-14
lines changed

4 files changed

+104
-14
lines changed

x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.test.tsx

+51-5
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,42 @@ import React from 'react';
1010
import { I18nProvider } from '@kbn/i18n-react';
1111
import { ControlSlider } from '.';
1212

13+
const values = [
14+
{
15+
label: '.001%',
16+
value: 0.00001,
17+
accessibleLabel: 'Point zero zero one percent, most performant',
18+
},
19+
{
20+
label: '.01%',
21+
value: 0.0001,
22+
},
23+
{
24+
label: '.1%',
25+
value: 0.001,
26+
},
27+
{
28+
label: '1%',
29+
value: 0.01,
30+
},
31+
{
32+
label: '10%',
33+
value: 0.1,
34+
},
35+
{
36+
label: '100%',
37+
value: 1,
38+
accessibleLabel: 'One hundred percent, most accurate',
39+
},
40+
];
41+
1342
describe('Slider Control', () => {
1443
it('should basically work', () => {
1544
render(
1645
<I18nProvider>
1746
<ControlSlider
18-
values={[0.1, 1]}
19-
currentValue={0.1}
47+
values={values}
48+
currentValue={0.00001}
2049
onChange={jest.fn()}
2150
data-test-subj="test-id"
2251
/>
@@ -26,18 +55,35 @@ describe('Slider Control', () => {
2655
expect(input.value).toBe('0'); // index 0 of the values array
2756
});
2857

58+
it('should display accessible label when provided', () => {
59+
render(
60+
<I18nProvider>
61+
<ControlSlider
62+
values={values}
63+
currentValue={0.00001}
64+
onChange={jest.fn()}
65+
data-test-subj="test-id"
66+
/>
67+
</I18nProvider>
68+
);
69+
const input = screen.getByTestId('test-id') as HTMLInputElement;
70+
expect(input.getAttribute('aria-valuetext')).toBe(
71+
'0, (Point zero zero one percent, most performant)'
72+
);
73+
});
74+
2975
it('should fallback to 1 when the provided value is not present within the values', () => {
3076
render(
3177
<I18nProvider>
3278
<ControlSlider
33-
values={[0.1, 0.5, 1]}
34-
currentValue={2}
79+
values={values}
80+
currentValue={4}
3581
onChange={jest.fn()}
3682
data-test-subj="test-id"
3783
/>
3884
</I18nProvider>
3985
);
4086
const input = screen.getByTestId('test-id') as HTMLInputElement;
41-
expect(input.value).toBe('2'); // index 2 of the values array
87+
expect(input.value).toBe('5'); // index 5 of the values array
4288
});
4389
});

x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx

+16-7
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiRange, EuiText, useEuiTheme } from '@elas
99
import React from 'react';
1010
import { FormattedMessage } from '@kbn/i18n-react';
1111
import { TooltipWrapper } from '@kbn/visualization-utils';
12+
import { i18n } from '@kbn/i18n';
1213

1314
export interface ControlSliderProps {
1415
/** Allowed values to show on the Control Slider */
15-
values: number[];
16+
values: Array<{ label: string; value: number; accessibleLabel?: string }>;
1617
/** Current value set */
1718
currentValue: number | undefined;
1819
/** When set will show the control in a disabled state */
@@ -34,8 +35,10 @@ export function ControlSlider({
3435
'data-test-subj': dataTestSubj,
3536
}: ControlSliderProps) {
3637
const { euiTheme } = useEuiTheme();
37-
const samplingIndex = values.findIndex((v) => v === currentValue);
38+
39+
const samplingIndex = values.findIndex((v) => v.value === currentValue);
3840
const currentSamplingIndex = samplingIndex > -1 ? samplingIndex : values.length - 1;
41+
3942
return (
4043
<TooltipWrapper
4144
tooltipContent={disabledReason}
@@ -58,22 +61,28 @@ export function ControlSlider({
5861
<EuiFlexItem>
5962
<EuiRange
6063
data-test-subj={dataTestSubj}
64+
aria-label={i18n.translate('randomSampling.ui.sliderControl.ariaLabel', {
65+
defaultMessage: 'Sampling percentages',
66+
})}
67+
aria-describedby={i18n.translate('randomSampling.ui.sliderControl.ariaDescribedby', {
68+
defaultMessage:
69+
'Lower sampling percentages increases the performance, but lowers the accuracy. Lower sampling percentages are best for large datasets.',
70+
})}
6171
value={currentSamplingIndex}
6272
disabled={disabled}
6373
fullWidth
6474
onChange={(e) => {
65-
onChange(values[Number(e.currentTarget.value)]);
75+
onChange(values[Number(e.currentTarget.value)].value);
6676
}}
6777
showInput={false}
6878
showRange={false}
6979
showTicks
7080
step={1}
7181
min={0}
7282
max={values.length - 1}
73-
ticks={values.map((v, i) => ({
74-
// Remove the initial 0 from values with decimal digits: 0.001 => .001
75-
label: `${v * 100}%`.slice(Number.isInteger(v * 100) ? 0 : 1),
76-
value: i,
83+
ticks={values.map((tick, index) => ({
84+
...tick,
85+
value: index,
7786
}))}
7887
/>
7988
</EuiFlexItem>

x-pack/platform/packages/private/kbn-random-sampling/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"kbn_references": [
1515
"@kbn/i18n-react",
1616
"@kbn/visualization-utils",
17+
"@kbn/i18n",
1718
],
1819
"exclude": [
1920
"target/**/*",

x-pack/platform/plugins/shared/lens/public/datasources/form_based/layer_settings.tsx

+36-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,41 @@ import { IgnoreGlobalFilterRowControl } from '../../shared_components/ignore_glo
1717
import { trackUiCounterEvents } from '../../lens_ui_telemetry';
1818
import { ExperimentalBadge } from '../../shared_components';
1919

20-
const samplingValues = [0.00001, 0.0001, 0.001, 0.01, 0.1, 1];
20+
const samplingValues = [
21+
{
22+
label: '.001%',
23+
value: 0.00001,
24+
accessibleLabel: i18n.translate(
25+
'xpack.lens.randomSampling.ui.sliderControl.tickLabels.0.00001',
26+
{
27+
defaultMessage: 'Point zero zero one percent, most performant',
28+
}
29+
),
30+
},
31+
{
32+
label: '.01%',
33+
value: 0.0001,
34+
},
35+
{
36+
label: '.1%',
37+
value: 0.001,
38+
},
39+
{
40+
label: '1%',
41+
value: 0.01,
42+
},
43+
{
44+
label: '10%',
45+
value: 0.1,
46+
},
47+
{
48+
label: '100%',
49+
value: 1,
50+
accessibleLabel: i18n.translate('xpack.lens.randomSampling.ui.sliderControl.tickLabels.1', {
51+
defaultMessage: 'One hundred percent, most accurate',
52+
}),
53+
},
54+
];
2155

2256
export function LayerSettingsPanel({
2357
state,
@@ -26,7 +60,7 @@ export function LayerSettingsPanel({
2660
}: DatasourceLayerSettingsProps<FormBasedPrivateState>) {
2761
const isSamplingValueDisabled = !isSamplingValueEnabled(state.layers[layerId]);
2862
const currentValue = isSamplingValueDisabled
29-
? samplingValues[samplingValues.length - 1]
63+
? samplingValues[samplingValues.length - 1].value
3064
: state.layers[layerId].sampling;
3165

3266
return (

0 commit comments

Comments
 (0)