Skip to content

Commit

Permalink
feat(slider): expose formatLabel to value tooltip (#16616)
Browse files Browse the repository at this point in the history
* feat(slider): expose formatLabel to value tooltip

- expose formatLabel to thumbWrapper for twoHandles as well as single handle.
- add examples on storybooks on how it could be used

* test(slider): add unit, avt, and e2e tests on slider for new behavior

- Avt, using tab and getting the value to show as medium
- Snapshot test
- Unit test to check the behavior for both single and two thumb variants

* test(slider): add suggested changes to the slider test and stories

* test(slider): move two types of test separate to each other

* test(slider): fix avt e2e test
  • Loading branch information
dkaushik95 committed Jul 8, 2024
1 parent d9e9bae commit 44338b1
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 3 deletions.
47 changes: 47 additions & 0 deletions e2e/components/Slider/Slider-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,53 @@ test.describe('@avt Slider', () => {
await expect(page).toHaveNoACViolations('Slider-with-layer');
});

test('@avt-advanced-states slider with custom format', async ({ page }) => {
await visitStory(page, {
component: 'Slider',
id: 'components-slider--slider-with-custom-value-label',
globals: {
theme: 'white',
},
});

await expect(page).toHaveNoACViolations('Slider-with-custom-value-label');
});

test.slow('@avt-keyboard-nav slider with custom format', async ({ page }) => {
await visitStory(page, {
component: 'Slider',
id: 'components-slider--slider-with-custom-value-label',
globals: {
theme: 'white',
},
});

// Test for label changes
// Initial value
await page.keyboard.press('Tab');
await expect(page.getByRole('slider')).toBeVisible();
await page.keyboard.press('Tab');

await expect(page.getByRole('slider')).toHaveAttribute(
'aria-valuetext',
'Medium'
);
// Move to high
await page.keyboard.press('Shift+ArrowRight');
await expect(page.getByRole('slider')).toHaveAttribute(
'aria-valuetext',
'High'
);

// Move to Low
await page.keyboard.press('Shift+ArrowLeft');
await page.keyboard.press('Shift+ArrowLeft');
await expect(page.getByRole('slider')).toHaveAttribute(
'aria-valuetext',
'Low'
);
});

// Prevent timeout
test.slow('@avt-keyboard-nav', async ({ page }) => {
await visitStory(page, {
Expand Down
8 changes: 8 additions & 0 deletions e2e/components/Slider/Slider-test.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ test.describe('Slider', () => {
theme,
});
});

test('slider with formatLabel @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'Slider',
id: 'components-slider--slider-with-custom-value-label',
theme,
});
});
});
});
});
46 changes: 46 additions & 0 deletions packages/react/src/components/Slider/Slider-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,28 @@ describe('Slider', () => {
expect(rangeLabels[0]).toHaveTextContent('0-min');
expect(rangeLabels[1]).toHaveTextContent('100-max');
});

it('supports custom formatting on the tooltip when input is hidden', () => {
const { container } = renderSlider({
min: 0,
max: 100,
value: 50,
formatLabel: (value) => `${value}%`,
hideTextInput: true,
});

const rangeLabels = container.querySelectorAll(
`.${prefix}--slider__range-label`
);

const valueLabel = container.querySelector(
`.${prefix}--popover-content.${prefix}--tooltip-content`
);

expect(rangeLabels[0]).toHaveTextContent('0%');
expect(rangeLabels[1]).toHaveTextContent('100%');
expect(valueLabel).toHaveTextContent('50%');
});
});

describe('Key/mouse event processing', () => {
Expand Down Expand Up @@ -744,6 +766,30 @@ describe('Slider', () => {
expect(upperInput).toHaveAttribute('type', 'hidden');
});

it('supports custom formatting on the tooltip when input is hidden', () => {
const { container } = renderTwoHandleSlider({
min: 0,
max: 100,
value: 50,
unstable_valueUpper: 70,
formatLabel: (value) => `${value}%`,
hideTextInput: true,
});

const rangeLabels = container.querySelectorAll(
`.${prefix}--slider__range-label`
);

const valueLabels = container.querySelectorAll(
`.${prefix}--popover-content.${prefix}--tooltip-content`
);

expect(rangeLabels[0]).toHaveTextContent('0%');
expect(rangeLabels[1]).toHaveTextContent('100%');
expect(valueLabels[0]).toHaveTextContent('50%');
expect(valueLabels[1]).toHaveTextContent('70%');
});

it('allows user to set invalid value when typing in input field', async () => {
const { type } = userEvent;
renderTwoHandleSlider({
Expand Down
21 changes: 21 additions & 0 deletions packages/react/src/components/Slider/Slider.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ export const SliderWithHiddenInputs = () => (
/>
);

export const SliderWithCustomValueLabel = () => (
<Slider
labelText="Slider label with low/medium/high"
value={50}
min={0}
max={100}
stepMultiplier={50}
step={1}
noValidate
hideTextInput
formatLabel={(val) => {
if (val < 25) {
return 'Low';
} else if (val > 75) {
return 'High';
}
return 'Medium';
}}
/>
);

export const ControlledSlider = () => {
const [val, setVal] = useState(87);
return (
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export interface SliderProps
disabled?: boolean;

/**
* The callback to format the label associated with the minimum/maximum value.
* The callback to format the label associated with the minimum/maximum value and the value tooltip when hideTextInput is true.
*/
formatLabel?: (value: number, label: string | undefined) => string;

Expand Down Expand Up @@ -1521,14 +1521,15 @@ class Slider extends PureComponent<SliderProps> {
<ThumbWrapper
hasTooltip={hideTextInput}
className={lowerThumbWrapperClasses}
label={`${value}`}
label={`${formatLabel(value, '')}`}
align="top"
{...lowerThumbWrapperProps}>
<div
className={lowerThumbClasses}
role="slider"
id={twoHandles ? undefined : id}
tabIndex={!readOnly ? 0 : -1}
aria-valuetext={`${formatLabel(value, '')}`}
aria-valuemax={twoHandles ? valueUpper : max}
aria-valuemin={min}
aria-valuenow={value}
Expand All @@ -1555,7 +1556,7 @@ class Slider extends PureComponent<SliderProps> {
<ThumbWrapper
hasTooltip={hideTextInput}
className={upperThumbWrapperClasses}
label={`${valueUpper}`}
label={`${formatLabel(valueUpper || 0, '')}`}
align="top"
{...upperThumbWrapperProps}>
<div
Expand Down

0 comments on commit 44338b1

Please sign in to comment.