- {props.title}
-
-
- }
- />
- );
+ return ;
}
const HtmlTooltip = withStyles((theme: Theme) => ({
@@ -187,9 +44,6 @@ export default function CustomizedTooltips() {
Light
-
- Arrow
-
Bootstrap
diff --git a/docs/src/pages/components/tooltips/InteractiveTooltips.js b/docs/src/pages/components/tooltips/InteractiveTooltips.js
index 1b7ff5269877ca..aea7fbef116666 100644
--- a/docs/src/pages/components/tooltips/InteractiveTooltips.js
+++ b/docs/src/pages/components/tooltips/InteractiveTooltips.js
@@ -1,25 +1,11 @@
import React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
-const useStyles = makeStyles(theme => ({
- button: {
- margin: theme.spacing(1),
- },
-}));
-
export default function InteractiveTooltips() {
- const classes = useStyles();
-
return (
-
-
- Interactive
-
-
- Non Interactive
-
-
+
+ Interactive
+
);
}
diff --git a/docs/src/pages/components/tooltips/InteractiveTooltips.tsx b/docs/src/pages/components/tooltips/InteractiveTooltips.tsx
index 428efbf477be3e..aea7fbef116666 100644
--- a/docs/src/pages/components/tooltips/InteractiveTooltips.tsx
+++ b/docs/src/pages/components/tooltips/InteractiveTooltips.tsx
@@ -1,27 +1,11 @@
import React from 'react';
-import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
-const useStyles = makeStyles((theme: Theme) =>
- createStyles({
- button: {
- margin: theme.spacing(1),
- },
- }),
-);
-
export default function InteractiveTooltips() {
- const classes = useStyles();
-
return (
-
-
- Interactive
-
-
- Non Interactive
-
-
+
+ Interactive
+
);
}
diff --git a/docs/src/pages/components/tooltips/tooltips.md b/docs/src/pages/components/tooltips/tooltips.md
index 529ff1e4a42b36..16b5b4e6d3e566 100644
--- a/docs/src/pages/components/tooltips/tooltips.md
+++ b/docs/src/pages/components/tooltips/tooltips.md
@@ -27,16 +27,22 @@ Here are some examples of customizing the component. You can learn more about th
{{"demo": "pages/components/tooltips/CustomizedTooltips.js"}}
+## Arrow Tooltips
+
+You can use the `arrow` prop to give your tooltip an arrow indicating which element it refers to.
+
+{{"demo": "pages/components/tooltips/ArrowTooltips.js"}}
+
## Custom child element
The tooltip needs to apply DOM event listeners to its child element.
If the child is a custom React element, you need to make sure that it spreads its properties to the underlying DOM element.
```jsx
-function MyComponent(props) {
- // Spread the properties to the underlying DOM element.
- return Bin
-}
+const MyComponent = React.forwardRef(function MyComponent(props, ref) {
+ // Spread the props to the underlying DOM element.
+ return Bin
+});
// ...
diff --git a/packages/material-ui/src/Tooltip/Tooltip.d.ts b/packages/material-ui/src/Tooltip/Tooltip.d.ts
index b405267eb110fc..4347a73c24fa87 100644
--- a/packages/material-ui/src/Tooltip/Tooltip.d.ts
+++ b/packages/material-ui/src/Tooltip/Tooltip.d.ts
@@ -5,6 +5,7 @@ import { PopperProps } from '../Popper/Popper';
export interface TooltipProps
extends StandardProps, TooltipClassKey, 'title'> {
+ arrow?: boolean;
children: React.ReactElement;
disableFocusListener?: boolean;
disableHoverListener?: boolean;
diff --git a/packages/material-ui/src/Tooltip/Tooltip.js b/packages/material-ui/src/Tooltip/Tooltip.js
index 54ec52c68a07c7..d7e7ee85e9aa41 100644
--- a/packages/material-ui/src/Tooltip/Tooltip.js
+++ b/packages/material-ui/src/Tooltip/Tooltip.js
@@ -17,6 +17,53 @@ function round(value) {
return Math.round(value * 1e5) / 1e5;
}
+function arrowGenerator() {
+ return {
+ '&[x-placement*="bottom"] $arrow': {
+ top: 0,
+ left: 0,
+ marginTop: '-0.95em',
+ width: '2em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '0 1em 1em 1em',
+ borderColor: 'transparent transparent currentcolor transparent',
+ },
+ },
+ '&[x-placement*="top"] $arrow': {
+ bottom: 0,
+ left: 0,
+ marginBottom: '-0.95em',
+ width: '2em',
+ height: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 0 1em',
+ borderColor: 'currentcolor transparent transparent transparent',
+ },
+ },
+ '&[x-placement*="right"] $arrow': {
+ left: 0,
+ marginLeft: '-0.95em',
+ height: '2em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 1em 1em 0',
+ borderColor: 'transparent currentcolor transparent transparent',
+ },
+ },
+ '&[x-placement*="left"] $arrow': {
+ right: 0,
+ marginRight: '-0.95em',
+ height: '2em',
+ width: '1em',
+ '&::before': {
+ borderWidth: '1em 0 1em 1em',
+ borderColor: 'transparent transparent transparent currentcolor',
+ },
+ },
+ };
+}
+
export const styles = theme => ({
/* Styles applied to the Popper component. */
popper: {
@@ -28,6 +75,8 @@ export const styles = theme => ({
popperInteractive: {
pointerEvents: 'auto',
},
+ /* Styles applied to the Popper component if `arrow={true}`. */
+ popperArrow: arrowGenerator(),
/* Styles applied to the tooltip (label wrapper) element. */
tooltip: {
backgroundColor: fade(theme.palette.grey[700], 0.9),
@@ -41,6 +90,25 @@ export const styles = theme => ({
wordWrap: 'break-word',
fontWeight: theme.typography.fontWeightMedium,
},
+ /* Styles applied to the tooltip (label wrapper) element if `arrow={true}`. */
+ tooltipArrow: {
+ position: 'relative',
+ margin: '0',
+ },
+ /* Styles applied to the arrow element. */
+ arrow: {
+ position: 'absolute',
+ fontSize: 6,
+ color: fade(theme.palette.grey[700], 0.9),
+ '&::before': {
+ content: '""',
+ margin: 'auto',
+ display: 'block',
+ width: 0,
+ height: 0,
+ borderStyle: 'solid',
+ },
+ },
/* Styles applied to the tooltip (label wrapper) element if the tooltip is opened by touch. */
touch: {
padding: '8px 16px',
@@ -84,6 +152,7 @@ export const styles = theme => ({
const Tooltip = React.forwardRef(function Tooltip(props, ref) {
const {
+ arrow = false,
children,
classes,
disableFocusListener = false,
@@ -110,6 +179,7 @@ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
const [openState, setOpenState] = React.useState(false);
const [, forceUpdate] = React.useState(0);
const [childNode, setChildNode] = React.useState();
+ const [arrowRef, setArrowRef] = React.useState(null);
const ignoreNonTouchEvents = React.useRef(false);
const { current: isControlled } = React.useRef(openProp != null);
const defaultId = React.useRef();
@@ -395,12 +465,21 @@ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
@@ -415,11 +494,13 @@ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
classes.tooltip,
{
[classes.touch]: ignoreNonTouchEvents.current,
+ [classes.tooltipArrow]: arrow,
},
classes[`tooltipPlacement${capitalize(placementInner.split('-')[0])}`],
)}
>
{title}
+ {arrow ? : null}
)}
@@ -429,6 +510,10 @@ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
});
Tooltip.propTypes = {
+ /**
+ * If `true`, adds an arrow to the tooltip.
+ */
+ arrow: PropTypes.bool,
/**
* Tooltip reference element.
*/