Skip to content
Merged
10 changes: 10 additions & 0 deletions common/changes/feature-overflowTooltip2_2017-04-11-19-55.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "office-ui-fabric-react",
"comment": "TooltipHost: Allow showing tooltip only if there's overflow",
"type": "minor"
}
],
"email": "cschleid@microsoft.com"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import '../../common/common';

// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.
//
// Office UI Fabric
Expand All @@ -21,9 +22,4 @@
font-size: $ms-font-size-s;
color: $ms-color-neutralPrimary;
word-break: break-all;
}

.host {
display: inline;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ export interface ITooltipHost {

}

export enum TooltipOverflowMode {
/** Only show tooltip if parent DOM element is overflowing */
Parent,

/** Only show tooltip if tooltip host's content is overflowing */
Self
}

/**
* Tooltip component props.
*/
Expand Down Expand Up @@ -39,4 +47,10 @@ export interface ITooltipHostProps extends React.HTMLProps<HTMLDivElement | Tool
* @default DirectionalHint.topCenter
*/
directionalHint?: DirectionalHint;

/**
* Only show if there is overflow. If set, the tooltip hosts observes and only shows the tooltip if this element has overflow.
* It also uses the parent as target element for the tooltip.
*/
overflowMode?: TooltipOverflowMode;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import '../../common/common';

// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.
//
// Office UI Fabric
// --------------------------------------------------
// TooltipHost styles

.host {
display: inline;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
css,
divProperties,
getNativeProps,
assign
assign,
hasOverflow
} from '../../Utilities';
import { ITooltipHostProps } from './TooltipHost.Props';
import { ITooltipHostProps, TooltipOverflowMode } from './TooltipHost.Props';
import { Tooltip } from './Tooltip';
import { TooltipDelay } from './Tooltip.Props';

import * as stylesImport from './Tooltip.scss';
const styles: any = stylesImport;

Expand All @@ -20,7 +22,6 @@ export interface ITooltipHostState {
}

export class TooltipHost extends BaseComponent<ITooltipHostProps, ITooltipHostState> {

public static defaultProps = {
delay: TooltipDelay.medium
};
Expand All @@ -33,14 +34,15 @@ export class TooltipHost extends BaseComponent<ITooltipHostProps, ITooltipHostSt
super(props);

this.state = {
isTooltipVisible: false,
isTooltipVisible: false
};
}

// Render
public render() {
let { calloutProps, content, children, directionalHint, delay } = this.props;
let { isTooltipVisible } = this.state;
const { calloutProps, content, children, directionalHint, delay } = this.props;
const { isTooltipVisible } = this.state;

return (
<div
className={ css('ms-TooltipHost', styles.host) }
Expand All @@ -55,7 +57,7 @@ export class TooltipHost extends BaseComponent<ITooltipHostProps, ITooltipHostSt
<Tooltip
delay={ delay }
content={ content }
targetElement={ this._tooltipHost }
targetElement={ this._getTargetElement() }
directionalHint={ directionalHint }
calloutProps={ assign(calloutProps, { onDismiss: this._onTooltipCallOutDismiss }) }
{ ...getNativeProps(this.props, divProperties) }
Expand All @@ -66,9 +68,36 @@ export class TooltipHost extends BaseComponent<ITooltipHostProps, ITooltipHostSt
);
}

private _getTargetElement(): HTMLElement {
const { overflowMode } = this.props;

// Select target element based on overflow mode. For parent mode, you want to position the tooltip relative
// to the parent element, otherwise it might look off.
if (overflowMode !== undefined) {
switch (overflowMode) {
case TooltipOverflowMode.Parent:
return this._tooltipHost.parentElement;

case TooltipOverflowMode.Self:
return this._tooltipHost;
}
}

return this._tooltipHost;
}

// Show Tooltip
@autobind
private _onTooltipMouseEnter(ev: any) {
const { overflowMode } = this.props;

if (overflowMode !== undefined) {
const overflowElement = this._getTargetElement();
if (overflowElement && !hasOverflow(overflowElement)) {
return;
}
}

this.setState({
isTooltipVisible: true
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
} from '@uifabric/example-app-base';
import { TooltipBottomExample } from './examples/Tooltip.Bottom.Example';
import { TooltipBasicExample } from './examples/Tooltip.Basic.Example';
import { TooltipOverflowExample } from './examples/Tooltip.Overflow.Example';

import './TooltipPage.scss';

const TooltipBasicExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/Tooltip/examples/Tooltip.Basic.Example.tsx') as string;
const TooltipBottomExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/Tooltip/examples/Tooltip.Bottom.Example.tsx') as string;
const TooltipOverflowExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/Tooltip/examples/Tooltip.Overflow.Example.tsx') as string;

export class TooltipPage extends React.Component<any, any> {
public render() {
Expand All @@ -29,6 +31,10 @@ export class TooltipPage extends React.Component<any, any> {
<ExampleCard title='Tooltip Bottom Direction. No delay' code={ TooltipBottomExampleCode }>
<TooltipBottomExample />
</ExampleCard>

<ExampleCard title='Tooltip only on overflow' code={ TooltipOverflowExampleCode }>
<TooltipOverflowExample />
</ExampleCard>
</LayerHost>
}
propertiesTables={
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* tslint:disable:no-unused-variable */
import * as React from 'react';
/* tslint:enable:no-unused-variable */
import { BaseComponent, css } from 'office-ui-fabric-react/lib/Utilities';
import { Button } from 'office-ui-fabric-react/lib/Button';
import {
TooltipHost,
TooltipOverflowMode
} from 'office-ui-fabric-react/lib/Tooltip';

export class TooltipOverflowExample extends BaseComponent<any, any> {
constructor(props: any) {
super(props);

this.state = {
overflow: false
};
}

public render() {
return (
<div>
<Button onClick={ () => this.setState({ overflow: !this.state.overflow }) }>Toggle showing overflow</Button>

<div style={ {
marginTop: '40px'
} }>
<div style={ {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: this.state.overflow && 'nowrap',
width: this.state.overflow && '200px',
border: '1px solid black'
} }>
<TooltipHost content='This is the tooltip' id='myID' overflowMode={ TooltipOverflowMode.Parent }>
<span aria-describedby='myID'>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec volutpat lectus ut magna sodales, sit amet accumsan arcu accumsan. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
</TooltipHost>
</div>
</div>
</div>
);
}
}