From e9d2d2f02ecbb94e01af7f85e98d10d059fef42a Mon Sep 17 00:00:00 2001 From: Katerina Koukiou Date: Thu, 18 Nov 2021 17:25:27 +0100 Subject: [PATCH] feat(Slider): add option to add Tooltip over thumb Fixes #5955 --- .../src/components/Slider/Slider.tsx | 54 +++++++++------ .../components/Slider/_tests_/Slider.test.tsx | 7 +- .../__snapshots__/Slider.test.tsx.snap | 66 +++++++++++++++++++ .../src/components/Slider/examples/Slider.md | 19 ++++-- 4 files changed, 122 insertions(+), 24 deletions(-) diff --git a/packages/react-core/src/components/Slider/Slider.tsx b/packages/react-core/src/components/Slider/Slider.tsx index 1afb4154b8e..d35d7c0b722 100644 --- a/packages/react-core/src/components/Slider/Slider.tsx +++ b/packages/react-core/src/components/Slider/Slider.tsx @@ -5,6 +5,7 @@ import { css } from '@patternfly/react-styles'; import { SliderStep } from './SliderStep'; import { InputGroup, InputGroupText } from '../InputGroup'; import { TextInput } from '../TextInput'; +import { Tooltip } from '../Tooltip'; export interface SliderStepObject { /** Value of the step. This value is a percentage of the slider where the tick is drawn. */ @@ -44,6 +45,8 @@ export interface SliderProps extends Omit, 'onCh inputAriaLabel?: string; /* Aria label for the thumb */ thumbAriaLabel?: string; + /* Adds a tooltip over the thumb containing the current value */ + hasTooltipOverThumb?: boolean; /** Label that is place after the input field */ inputLabel?: string | number; /** Position of the input */ @@ -73,6 +76,7 @@ export const Slider: React.FunctionComponent = ({ inputLabel, inputAriaLabel = 'Slider value input', thumbAriaLabel = 'Value', + hasTooltipOverThumb = false, inputPosition = 'right', onChange, leftActions, @@ -141,7 +145,9 @@ export const Slider: React.FunctionComponent = ({ return matchingStep.label; } } - return localValue.toString(); + // For continuous steps default to showing 2 decimals in tooltip + // Consider making it configurable via a property + return Number(Number(localValue).toFixed(2)).toString(); }; const handleThumbDragEnd = () => { @@ -209,12 +215,12 @@ export const Slider: React.FunctionComponent = ({ thumbRef.current.style.setProperty('--pf-c-slider--value', `${newPercentage}%`); // convert percentage to value - const newValue = (newPercentage * (max - min)) / 100 + min; + const newValue = Math.round(((newPercentage * (max - min)) / 100 + min) * 100) / 100; setValue(newValue); if (!customSteps) { // snap to new value if not custom steps - snapValue = Math.round((newValue - min) / step) * step + min; + snapValue = Math.round((Math.round((newValue - min) / step) * step + min) * 100) / 100; thumbRef.current.style.setProperty('--pf-c-slider--value', `${snapValue}%`); setValue(snapValue); } @@ -344,6 +350,25 @@ export const Slider: React.FunctionComponent = ({ return builtSteps; }; + const thumbComponent = ( +
+ ); + return (
= ({ {buildSteps()}
)} -
+ {hasTooltipOverThumb ? ( + + {thumbComponent} + + ) : ( + thumbComponent + )} {isInputVisible && inputPosition === 'aboveThumb' && (
{displayInput()}
)} diff --git a/packages/react-core/src/components/Slider/_tests_/Slider.test.tsx b/packages/react-core/src/components/Slider/_tests_/Slider.test.tsx index cd36927bfb2..c072e7617ae 100644 --- a/packages/react-core/src/components/Slider/_tests_/Slider.test.tsx +++ b/packages/react-core/src/components/Slider/_tests_/Slider.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import { Slider } from '../Slider'; import { Button } from '../../Button'; @@ -69,4 +69,9 @@ describe('slider', () => { const view = mount(); expect(view).toMatchSnapshot(); }); + + test('renders slider with tooltip on thumb', () => { + const view = shallow(); + expect(view).toMatchSnapshot(); + }); }); diff --git a/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap b/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap index 55d60a426fa..06673d387c7 100644 --- a/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap +++ b/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap @@ -1194,3 +1194,69 @@ exports[`slider renders slider with input actions 1`] = `
`; + +exports[`slider renders slider with tooltip on thumb 1`] = ` +
+
+
+
+
+ + +
+ +
+
+`; diff --git a/packages/react-core/src/components/Slider/examples/Slider.md b/packages/react-core/src/components/Slider/examples/Slider.md index 907a9500ad8..930bcbef80e 100644 --- a/packages/react-core/src/components/Slider/examples/Slider.md +++ b/packages/react-core/src/components/Slider/examples/Slider.md @@ -134,12 +134,13 @@ class DiscreteInput extends React.Component { ```js import React from 'react'; -import { Slider, Text, TextVariants } from '@patternfly/react-core'; +import { Checkbox, Slider, Text, TextVariants } from '@patternfly/react-core'; class ContinuousInput extends React.Component { constructor(props) { super(props); this.state = { + hasTooltipOverThumb: false, value: 50, valueCustom: 50 }; @@ -160,14 +161,24 @@ class ContinuousInput extends React.Component { render() { return ( <> - Slider value is: {this.state.value.toFixed(2)} - + this.setState({ hasTooltipOverThumb })} + style={{ marginBottom: 20 }} /> + Slider Value is: {this.state.value} +
- Slider value is: {this.state.valueCustom.toFixed(2)} + Slider value is: {this.state.valueCustom}