Skip to content

Commit

Permalink
feat(Tooltip): 8pt Tooltips: Hover behavior
Browse files Browse the repository at this point in the history
8pt Tooltips: Hover now has the option to be sticky as to offer a wider
hover area for the user.

[Finishes #138673781]

Signed-off-by: Anushka Makhija <amakhija@pivotal.io>
  • Loading branch information
sjolicoeur authored and pivotal committed May 16, 2017
1 parent c44f9b7 commit 73f46a7
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 15 deletions.
39 changes: 36 additions & 3 deletions library/spec/pivotal-ui-react/tooltip/tooltip_spec.js
@@ -1,9 +1,10 @@
import '../spec_helper'
;
;
import {Tooltip} from 'pui-react-tooltip';

describe('Tooltip Component', () => {
const renderComponent = props => ReactTestUtils.renderIntoDocument(<Tooltip {...props}>Some default tooltip</Tooltip>);
const renderComponent = props => ReactTestUtils.renderIntoDocument(<Tooltip {...props}>Some default
tooltip</Tooltip>);

it('renders', () => {
const result = renderComponent();
Expand Down Expand Up @@ -70,4 +71,36 @@ describe('Tooltip Component', () => {
expect(content).toHaveClass('tooltip-lg');
});
});
});

describe('sticky', () => {
let renderComponent;
beforeEach(() => {
renderComponent = props => ReactTestUtils.renderIntoDocument(<Tooltip {...props}>Some default tooltip</Tooltip>);
});

describe('is not set', () => {
it('does not render with the hoverable class', () => {
const result = renderComponent({isSticky: false});
const content = ReactTestUtils.findRenderedDOMComponentWithClass(result, 'tooltip-container');
expect(content).not.toHaveClass('tooltip-hoverable');
});
});

describe('is set to false', () => {
it('does not render with the hoverable class', () => {
const result = renderComponent({isSticky: false});
const content = ReactTestUtils.findRenderedDOMComponentWithClass(result, 'tooltip-container');
expect(content).not.toHaveClass('tooltip-hoverable');
});
});

describe('is set to true', () => {
it('renders with the hoverable class', () => {
const result = renderComponent({isSticky: true});
const content = ReactTestUtils.findRenderedDOMComponentWithClass(result, 'tooltip-container');
expect(content).toHaveClass('tooltip-hoverable');
});
});
});
})
;
8 changes: 8 additions & 0 deletions library/spec/pivotal-ui-react/tooltip/tooltip_trigger_spec.js
Expand Up @@ -164,4 +164,12 @@ describe('TooltipTrigger Component', () => {
expect(tooltip).toHaveClass('tooltip-container-hidden');
});
});

describe('isSticky', () => {
it('renders the tooltip with the "isSticky" prop', () => {
const result = renderComponent({isSticky: true, tooltip: 'Some tooltip content'});
const content = ReactTestUtils.findRenderedDOMComponentWithClass(result, 'tooltip-container');
expect(content).toHaveClass('tooltip-hoverable');
});
});
});
19 changes: 12 additions & 7 deletions library/src/pivotal-ui-react/tooltip/tooltip.js
Expand Up @@ -6,23 +6,26 @@ import classnames from 'classnames';
export class Tooltip extends React.Component {
static propTypes = {
visible: PropTypes.bool,
size: PropTypes.oneOf(['auto','sm', 'md', 'lg'])
size: PropTypes.oneOf(['auto','sm', 'md', 'lg']),
isSticky: PropTypes.bool
}

static defaultProps = {
visible: true,
size: 'auto'
size: 'auto',
isSticky: false
}

constructor(props) {
super(props);
}

render() {
let {visible, size, className, children, ...others} = this.props;
let {isSticky, visible, size, className, children, ...others} = this.props;

const newClasses = classnames('tooltip-container', visible ? 'tooltip-container-visible' : 'tooltip-container-hidden',
size === 'auto' ? null : `tooltip-${size}`,
isSticky? 'tooltip-hoverable': null,
className);

return (
Expand All @@ -42,7 +45,8 @@ export class TooltipTrigger extends React.Component {
onEntered: PropTypes.func,
onExited: PropTypes.func,
theme: PropTypes.oneOf(['dark', 'light']),
size: PropTypes.oneOf(['auto', 'sm', 'md', 'lg'])
size: PropTypes.oneOf(['auto', 'sm', 'md', 'lg']),
isSticky: PropTypes.bool
}

static defaultProps = {
Expand All @@ -52,7 +56,8 @@ export class TooltipTrigger extends React.Component {
onEntered: () => {},
onExited: () => {},
theme: 'dark',
size: 'auto'
size: 'auto',
isSticky: false
}

constructor(props) {
Expand Down Expand Up @@ -80,7 +85,7 @@ export class TooltipTrigger extends React.Component {
}

render() {
const {placement, tooltip, trigger, className, clickHideDelay, onEntered, onExited, theme, size, ...others} = this.props;
const {isSticky, placement, tooltip, trigger, className, clickHideDelay, onEntered, onExited, theme, size, ...others} = this.props;
const {visible} = this.state;

let placementClass;
Expand Down Expand Up @@ -108,7 +113,7 @@ export class TooltipTrigger extends React.Component {
return (
<div {...newProps}>
{this.props.children}
<Tooltip size={this.props.size} visible={visible}>{tooltip}</Tooltip>
<Tooltip {...{isSticky, size: this.props.size, visible}}>{tooltip}</Tooltip>
</div>
);
}
Expand Down
21 changes: 16 additions & 5 deletions library/src/pivotal-ui/components/tooltips/tooltips.scss
Expand Up @@ -9,11 +9,6 @@

.tooltip-container {
//Hover Effect for HTML & CSS ONLY

&.tooltip-container-visible {
visibility: visible;
}

visibility: hidden;
transition: opacity $tooltip-opacity-transition;
z-index: $tooltip-container-z;
Expand All @@ -24,6 +19,22 @@
margin: 0 0 $tooltip-margin 0; //space for the triangle indicator
text-align: left;

&.tooltip-container-visible {
visibility: visible;
}

&.tooltip-hoverable {
&:after {
content:"";
position: absolute;
width:calc(100% + 16px);
height:calc(100% + 16px);
top:50%;
left:50%;
transform: translateX(-50%) translateY(-50%);
}
}

.tooltip-content {
white-space: nowrap;
padding: $tooltip-padding;
Expand Down
9 changes: 9 additions & 0 deletions styleguide/docs/react/tooltip.js
Expand Up @@ -25,6 +25,7 @@ Property | Required | Type | Default
---------------|----------|-------------------------------------------|----------|----------------------------------
visible | no | Boolean | true | Whether the tooltip contents are visible
size | no | oneOf(['auto', 'sm', 'md', 'lg']) | auto | Size of the tooltip
isSticky | no | Boolean | false | Whether the tooltip hover is sticky or not
* See [React proptype definitions here](https://facebook.github.io/react/docs/typechecking-with-proptypes.html)
Expand Down Expand Up @@ -67,6 +68,7 @@ pin | no | Boolean | true |
placement | no | oneOf('top', 'bottom', 'left', 'right') | 'right' | Placement of overlay in relation to target
theme | no | oneOf(['light', 'dark']) | dark | Theme of tooltip background and text
trigger | no | oneOf('hover', 'click', 'focus', 'manual') | 'hover' | Action to trigger showing overlay
isSticky | no | Boolean | false | Whether the tooltip hover is sticky or not
## Basic usage
Expand Down Expand Up @@ -143,6 +145,8 @@ onEntered | no | Func | () => {}
onExited | no | Func | () => {} | Callback that is called after the tooltip is hidden
theme | no | oneOf(['light', 'dark']) | dark | Theme of tooltip background and text
size | no | oneOf(['auto', 'sm', 'md', 'lg']) | auto | Size of the tooltip
isSticky | no | Boolean | false | Whether the tooltip hover is sticky or not
* See [React proptype definitions here](https://facebook.github.io/react/docs/typechecking-with-proptypes.html)
Expand Down Expand Up @@ -170,6 +174,11 @@ the TooltipTrigger will add a lot of markup to the DOM if you are using it in a
<button className="btn btn-default">Click me</button>
</TooltipTrigger>
</div>
<div className="form-group form-inline">
<TooltipTrigger tooltip="Some tooltip" isSticky={true} placement="right">
<button className="btn btn-default">Hover over me too!</button>
</TooltipTrigger>
</div>
</div>
```
Expand Down

0 comments on commit 73f46a7

Please sign in to comment.