Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit b72e8b6

Browse files
authored
Slider tooltips (#564)
* Bump rc-slider minor version This is so we can use the `visible` prop in `tipProps`, introduced in `rc-slider` 8.6.1 (undocumented in the `rc-slider` repo's HISTORY.md) See react-component/slider#383 * Add tooltip (basic `tipProps` alias) to Slider and RangeSlider Adds support for hoverable and persistent (always visible) tooltips * Remove test css class + undo loading_state propTypes reshuffle * Add propTypes variations template * Put `createSliderWithTooltip` in constructor * Change 'visible' tooltip propType to bool * Fix Slider.react.js 🍝 from RangeSlider * Slider tooltip propTypes: `oneOfType[]` -> single `exact` * Move Slider instantiation from constructor to render method * Spacing * Add changelog entry for Slider/RangeSlider tooltips * Fix markdown syntax + parens * Prettier (comment + ternary formatting) * `visible` -> `always_visible`; `position` -> `placement` * Add DashSlider conditional in componentWillReceiveProps
1 parent 5bd6137 commit b72e8b6

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
6+
### Added
7+
- Ability to add tooltips to `Slider` and `RangeSlider`, which can be visible always or on hover. Tooltips also take a position argument. [#564](https://github.com/plotly/dash-core-components/pull/564)
8+
69
### Fixed
710
- Fixed `min_date_allowed` and `max_date_allowed` bug in `DatePickerRange` [#551]https://github.com/plotly/dash-core-components/issues/551)
811
- Fixed unwanted `resize()` calls on unmounted `Graph`s [#534](https://github.com/plotly/dash-core-components/issues/534)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"moment": "^2.20.1",
3737
"prop-types": "^15.6.0",
3838
"ramda": "^0.24.1",
39-
"rc-slider": "^8.3.1",
39+
"rc-slider": "^8.6.11",
4040
"react-addons-shallow-compare": "^15.6.0",
4141
"react-dates": "^20.1.0",
4242
"react-docgen": "^3.0.0",

src/components/RangeSlider.react.js

+52-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
33
import {omit} from 'ramda';
4-
import {Range} from 'rc-slider';
4+
import {Range, createSliderWithTooltip} from 'rc-slider';
55

66
/**
77
* A double slider with two handles.
@@ -11,13 +11,21 @@ export default class RangeSlider extends Component {
1111
constructor(props) {
1212
super(props);
1313
this.propsToState = this.propsToState.bind(this);
14+
this.DashSlider = props.tooltip
15+
? createSliderWithTooltip(Range)
16+
: Range;
1417
}
1518

1619
propsToState(newProps) {
1720
this.setState({value: newProps.value});
1821
}
1922

2023
componentWillReceiveProps(newProps) {
24+
if (newProps.tooltip !== this.props.tooltip) {
25+
this.DashSlider = newProps.tooltip
26+
? createSliderWithTooltip(Range)
27+
: Range;
28+
}
2129
this.propsToState(newProps);
2230
}
2331

@@ -31,11 +39,27 @@ export default class RangeSlider extends Component {
3139
id,
3240
loading_state,
3341
setProps,
42+
tooltip,
3443
updatemode,
3544
vertical,
3645
} = this.props;
3746
const value = this.state.value;
3847

48+
let tipProps;
49+
if (tooltip && tooltip.always_visible) {
50+
/**
51+
* clone `tooltip` but with renamed key `always_visible` -> `visible`
52+
* the rc-tooltip API uses `visible`, but `always_visible is more semantic
53+
* assigns the new (renamed) key to the old key and deletes the old key
54+
*/
55+
tipProps = Object.assign(tooltip, {
56+
visible: tooltip.always_visible,
57+
});
58+
delete tipProps.always_visible;
59+
} else {
60+
tipProps = tooltip;
61+
}
62+
3963
return (
4064
<div
4165
id={id}
@@ -45,7 +69,7 @@ export default class RangeSlider extends Component {
4569
className={className}
4670
style={vertical ? {height: '100%'} : {}}
4771
>
48-
<Range
72+
<this.DashSlider
4973
onChange={value => {
5074
if (updatemode === 'drag') {
5175
setProps({value});
@@ -58,6 +82,7 @@ export default class RangeSlider extends Component {
5882
setProps({value});
5983
}
6084
}}
85+
tipProps={tipProps}
6186
value={value}
6287
{...omit(
6388
['className', 'value', 'setProps', 'updatemode'],
@@ -152,6 +177,31 @@ RangeSlider.propTypes = {
152177
*/
153178
pushable: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
154179

180+
tooltip: PropTypes.exact({
181+
/**
182+
* Determines whether tooltips should always be visible
183+
* (as opposed to the default, visible on hover)
184+
*/
185+
always_visible: PropTypes.bool,
186+
187+
/**
188+
* Determines the placement of tooltips
189+
* See https://github.com/react-component/tooltip#api
190+
* top/bottom{*} sets the _origin_ of the tooltip, so e.g. `topLeft` will
191+
* in reality appear to be on the top right of the handle
192+
*/
193+
placement: PropTypes.oneOf([
194+
'left',
195+
'right',
196+
'top',
197+
'bottom',
198+
'topLeft',
199+
'topRight',
200+
'bottomLeft',
201+
'bottomRight',
202+
]),
203+
}),
204+
155205
/**
156206
* Value by which increments or decrements are made
157207
*/

src/components/Slider.react.js

+52-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, {Component} from 'react';
2-
import ReactSlider from 'rc-slider';
2+
import ReactSlider, {createSliderWithTooltip} from 'rc-slider';
33
import PropTypes from 'prop-types';
44
import {omit} from 'ramda';
55
import './css/[email protected]';
@@ -11,13 +11,21 @@ export default class Slider extends Component {
1111
constructor(props) {
1212
super(props);
1313
this.propsToState = this.propsToState.bind(this);
14+
this.DashSlider = props.tooltip
15+
? createSliderWithTooltip(ReactSlider)
16+
: ReactSlider;
1417
}
1518

1619
propsToState(newProps) {
1720
this.setState({value: newProps.value});
1821
}
1922

2023
componentWillReceiveProps(newProps) {
24+
if (newProps.tooltip !== this.props.tooltip) {
25+
this.DashSlider = newProps.tooltip
26+
? createSliderWithTooltip(ReactSlider)
27+
: ReactSlider;
28+
}
2129
this.propsToState(newProps);
2230
}
2331

@@ -31,11 +39,27 @@ export default class Slider extends Component {
3139
id,
3240
loading_state,
3341
setProps,
42+
tooltip,
3443
updatemode,
3544
vertical,
3645
} = this.props;
3746
const value = this.state.value;
3847

48+
let tipProps;
49+
if (tooltip && tooltip.always_visible) {
50+
/**
51+
* clone `tooltip` but with renamed key `always_visible` -> `visible`
52+
* the rc-tooltip API uses `visible`, but `always_visible is more semantic
53+
* assigns the new (renamed) key to the old key and deletes the old key
54+
*/
55+
tipProps = Object.assign(tooltip, {
56+
visible: tooltip.always_visible,
57+
});
58+
delete tipProps.always_visible;
59+
} else {
60+
tipProps = tooltip;
61+
}
62+
3963
return (
4064
<div
4165
id={id}
@@ -45,7 +69,7 @@ export default class Slider extends Component {
4569
className={className}
4670
style={vertical ? {height: '100%'} : {}}
4771
>
48-
<ReactSlider
72+
<this.DashSlider
4973
onChange={value => {
5074
if (updatemode === 'drag') {
5175
setProps({value});
@@ -58,6 +82,7 @@ export default class Slider extends Component {
5882
setProps({value});
5983
}
6084
}}
85+
tipProps={tooltip}
6186
value={value}
6287
{...omit(
6388
['className', 'setProps', 'updatemode', 'value'],
@@ -133,6 +158,31 @@ Slider.propTypes = {
133158
*/
134159
max: PropTypes.number,
135160

161+
tooltip: PropTypes.exact({
162+
/**
163+
* Determines whether tooltips should always be visible
164+
* (as opposed to the default, visible on hover)
165+
*/
166+
always_visible: PropTypes.bool,
167+
168+
/**
169+
* Determines the placement of tooltips
170+
* See https://github.com/react-component/tooltip#api
171+
* top/bottom{*} sets the _origin_ of the tooltip, so e.g. `topLeft` will
172+
* in reality appear to be on the top right of the handle
173+
*/
174+
placement: PropTypes.oneOf([
175+
'left',
176+
'right',
177+
'top',
178+
'bottom',
179+
'topLeft',
180+
'topRight',
181+
'bottomLeft',
182+
'bottomRight',
183+
]),
184+
}),
185+
136186
/**
137187
* Value by which increments or decrements are made
138188
*/

0 commit comments

Comments
 (0)