diff --git a/packages/react/src/popover/styles.js b/packages/react/src/popover/styles.js
index e9ff23a41d..d4fd7e8db5 100644
--- a/packages/react/src/popover/styles.js
+++ b/packages/react/src/popover/styles.js
@@ -1,4 +1,4 @@
-import { ensureNumber, ensureString } from 'ensure-type';
+import { ensureNumber } from 'ensure-type';
import { useColorMode } from '../color-mode';
import { useColorStyle } from '../color-style';
import { useTheme } from '../theme';
@@ -14,23 +14,22 @@ const pixelize = (value) => {
const usePopoverArrowStyle = ({
arrowHeight: arrowHeightProp,
arrowWidth: arrowWidthProp,
- placement: placementProp,
}) => {
const [colorMode] = useColorMode();
const { sizes } = useTheme();
const arrowHeight = sizes[arrowHeightProp] ?? pixelize(arrowHeightProp);
const arrowWidth = sizes[arrowWidthProp] ?? pixelize(arrowWidthProp);
- const placement = ensureString(placementProp);
const dropShadowColor = {
dark: 'rgba(0, 0, 0, 0.16)',
light: 'rgba(0, 0, 0, 0.08)',
}[colorMode];
- if (placement.startsWith('top')) {
- return {
+ return {
+ // https://popper.js.org/docs/v2/tutorial/#arrow
+ '&[data-popper-placement^="top"]': {
position: 'absolute',
bottom: 0,
- __before: {
+ '::before': {
content: '""',
borderTop: `${arrowHeight} solid`,
borderLeft: `calc(${arrowWidth}/2) solid transparent`,
@@ -40,14 +39,11 @@ const usePopoverArrowStyle = ({
bottom: `-${arrowHeight}`,
transform: 'translateX(-50%)',
},
- };
- }
-
- if (placement.startsWith('bottom')) {
- return {
+ },
+ '&[data-popper-placement^="bottom"]': {
position: 'absolute',
top: 0,
- __before: {
+ '::before': {
content: '""',
borderBottom: `${arrowHeight} solid`,
borderLeft: `calc(${arrowWidth}/2) solid transparent`,
@@ -57,14 +53,11 @@ const usePopoverArrowStyle = ({
top: `-${arrowHeight}`,
transform: 'translateX(-50%)',
},
- };
- }
-
- if (placement.startsWith('left')) {
- return {
+ },
+ '&[data-popper-placement^="left"]': {
position: 'absolute',
right: 0,
- __before: {
+ '::before': {
content: '""',
borderLeft: `${arrowHeight} solid`,
borderTop: `calc(${arrowWidth}/2) solid transparent`,
@@ -74,14 +67,11 @@ const usePopoverArrowStyle = ({
right: `-${arrowHeight}`,
transform: 'translateY(-50%)',
},
- };
- }
-
- if (placement.startsWith('right')) {
- return {
+ },
+ '&[data-popper-placement^="right"]': {
position: 'absolute',
left: 0,
- __before: {
+ '::before': {
content: '""',
borderRight: `${arrowHeight} solid`,
borderTop: `calc(${arrowWidth}/2) solid transparent`,
@@ -91,10 +81,8 @@ const usePopoverArrowStyle = ({
left: `-${arrowHeight}`,
transform: 'translateY(-50%)',
},
- };
- }
-
- return {};
+ },
+ };
};
const usePopoverTriggerStyle = () => {
diff --git a/packages/react/src/popper/Popper.js b/packages/react/src/popper/Popper.js
index afa938b5c7..39d7eccd31 100644
--- a/packages/react/src/popper/Popper.js
+++ b/packages/react/src/popper/Popper.js
@@ -72,21 +72,25 @@ const Popper = forwardRef((
padding: 12, // 12px from the edges of the popper
},
},
- { // https://popper.js.org/docs/v2/modifiers/flip/
- name: 'flip',
- enabled: false, // No flip
- },
{
name: 'handlePopperUpdate',
enabled: true,
phase: 'afterWrite',
fn: ({ state }) => {
+ const arrowEl = state?.elements?.arrow;
+ const nextPlacement = state?.placement;
+
+ // Update the arrow element's `data-popper-placement` attribute based on the desired placement
+ // @see https://popper.js.org/docs/v2/tutorial/
+ if (arrowEl && arrowEl.getAttribute('data-popper-placement') !== nextPlacement) {
+ arrowEl.setAttribute('data-popper-placement', nextPlacement);
+ }
+
const isControlled = (placementProp !== undefined);
if (isControlled) {
return;
}
- const nextPlacement = state?.placement;
if (nextPlacement && (nextPlacement !== placement)) {
setPlacement(nextPlacement);
}
diff --git a/packages/react/src/tooltip/TooltipArrow.js b/packages/react/src/tooltip/TooltipArrow.js
index 6cb07e42ec..bd0295dc92 100644
--- a/packages/react/src/tooltip/TooltipArrow.js
+++ b/packages/react/src/tooltip/TooltipArrow.js
@@ -8,6 +8,7 @@ const TooltipArrow = forwardRef((
{
arrowHeight = 4,
arrowWidth = 8,
+ sx,
...rest
},
ref,
@@ -16,26 +17,27 @@ const TooltipArrow = forwardRef((
placement,
tooltipContentRef,
} = useTooltip();
- const styleProps = useTooltipArrowStyle({ arrowHeight, arrowWidth, placement });
- const colorStyleProps = (() => {
- const tooltipContentEl = tooltipContentRef?.current;
- if (isHTMLElement(tooltipContentEl)) {
- // Compute the background color of the first direct child of the tooltip content and apply it to the tooltip arrow
- const computedStyle = getComputedStyle(tooltipContentEl.firstChild);
- return {
- color: computedStyle?.backgroundColor,
- };
- }
- return {};
- })();
+ const tooltipContentEl = tooltipContentRef?.current;
+ const styleProps = useTooltipArrowStyle({ arrowHeight, arrowWidth });
+
+ if (isHTMLElement(tooltipContentEl)) {
+ // Compute the background color of the first direct child of the tooltip content and apply it to the tooltip arrow
+ const computedStyle = getComputedStyle(tooltipContentEl.firstChild);
+ styleProps.color = computedStyle?.backgroundColor;
+ }
return (
);
diff --git a/packages/react/src/tooltip/TooltipContent.js b/packages/react/src/tooltip/TooltipContent.js
index d9c84807ad..22950a9424 100644
--- a/packages/react/src/tooltip/TooltipContent.js
+++ b/packages/react/src/tooltip/TooltipContent.js
@@ -146,7 +146,6 @@ const TooltipContent = forwardRef((
anchorEl={tooltipTriggerRef.current}
id={tooltipId}
isOpen={isOpen}
- modifiers={popperModifiers}
placement={placement}
pointerEvents="none"
ref={tooltipContentRef}
@@ -156,6 +155,12 @@ const TooltipContent = forwardRef((
willUseTransition={true}
zIndex="tooltip"
{...PopperProps}
+ modifiers={[
+ // Default modifiers
+ ...popperModifiers,
+ // User-defined modifiers
+ ...ensureArray(PopperProps?.modifiers),
+ ]}
>
{({ placement, transition }) => {
const { in: inProp, onEnter, onExited } = { ...transition };
diff --git a/packages/react/src/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap b/packages/react/src/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap
index 0329b7073e..1de92de9cf 100644
--- a/packages/react/src/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap
+++ b/packages/react/src/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap
@@ -110,12 +110,32 @@ exports[`Tooltip should render correctly 1`] = `
transform-origin: top center;
}
-.emotion-6 {
+.emotion-6[data-popper-placement^="top"] {
+ position: absolute;
+ bottom: 0;
+}
+
+.emotion-6[data-popper-placement^="top"]::before {
+ content: "";
+ border-top: 4px solid;
+ border-left: calc(8px/2) solid transparent;
+ border-right: calc(8px/2) solid transparent;
+ -webkit-filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.08));
+ filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.08));
+ position: absolute;
+ bottom: calc(4px * -1);
+ -webkit-transform: translateX(-50%);
+ -moz-transform: translateX(-50%);
+ -ms-transform: translateX(-50%);
+ transform: translateX(-50%);
+}
+
+.emotion-6[data-popper-placement^="bottom"] {
position: absolute;
top: 0;
}
-.emotion-6::before {
+.emotion-6[data-popper-placement^="bottom"]::before {
content: "";
border-bottom: 4px solid;
border-left: calc(8px/2) solid transparent;
@@ -130,6 +150,46 @@ exports[`Tooltip should render correctly 1`] = `
transform: translateX(-50%);
}
+.emotion-6[data-popper-placement^="left"] {
+ position: absolute;
+ right: 0;
+}
+
+.emotion-6[data-popper-placement^="left"]::before {
+ content: "";
+ border-left: 4px solid;
+ border-top: calc(8px/2) solid transparent;
+ border-bottom: calc(8px/2) solid transparent;
+ -webkit-filter: drop-shadow(1px 0px 1px rgba(0, 0, 0, 0.08));
+ filter: drop-shadow(1px 0px 1px rgba(0, 0, 0, 0.08));
+ position: absolute;
+ right: calc(4px * -1);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+
+.emotion-6[data-popper-placement^="right"] {
+ position: absolute;
+ left: 0;
+}
+
+.emotion-6[data-popper-placement^="right"]::before {
+ content: "";
+ border-right: 4px solid;
+ border-top: calc(8px/2) solid transparent;
+ border-bottom: calc(8px/2) solid transparent;
+ -webkit-filter: drop-shadow(-1px 0px 1px rgba(0, 0, 0, 0.08));
+ filter: drop-shadow(-1px 0px 1px rgba(0, 0, 0, 0.08));
+ position: absolute;
+ left: calc(4px * -1);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+
diff --git a/packages/react/src/tooltip/styles.js b/packages/react/src/tooltip/styles.js
index a156c8ef74..d647053765 100644
--- a/packages/react/src/tooltip/styles.js
+++ b/packages/react/src/tooltip/styles.js
@@ -1,4 +1,4 @@
-import { ensureNumber, ensureString } from 'ensure-type';
+import { ensureNumber } from 'ensure-type';
import { useColorMode } from '../color-mode';
import { useColorStyle } from '../color-style';
import { useTheme } from '../theme';
@@ -14,23 +14,22 @@ const pixelize = (value) => {
const useTooltipArrowStyle = ({
arrowHeight: arrowHeightProp,
arrowWidth: arrowWidthProp,
- placement: placementProp,
}) => {
const [colorMode] = useColorMode();
const { sizes } = useTheme();
const arrowHeight = sizes[arrowHeightProp] ?? pixelize(arrowHeightProp);
const arrowWidth = sizes[arrowWidthProp] ?? pixelize(arrowWidthProp);
- const placement = ensureString(placementProp);
const dropShadowColor = {
dark: 'rgba(0, 0, 0, 0.16)',
light: 'rgba(0, 0, 0, 0.08)',
}[colorMode];
- if (placement.startsWith('top')) {
- return {
+ return {
+ // https://popper.js.org/docs/v2/tutorial/#arrow
+ '&[data-popper-placement^="top"]': {
position: 'absolute',
bottom: 0,
- __before: {
+ '::before': {
content: '""',
borderTop: `${arrowHeight} solid`,
borderLeft: `calc(${arrowWidth}/2) solid transparent`,
@@ -40,14 +39,11 @@ const useTooltipArrowStyle = ({
bottom: `-${arrowHeight}`,
transform: 'translateX(-50%)',
},
- };
- }
-
- if (placement.startsWith('bottom')) {
- return {
+ },
+ '&[data-popper-placement^="bottom"]': {
position: 'absolute',
top: 0,
- __before: {
+ '::before': {
content: '""',
borderBottom: `${arrowHeight} solid`,
borderLeft: `calc(${arrowWidth}/2) solid transparent`,
@@ -57,14 +53,11 @@ const useTooltipArrowStyle = ({
top: `-${arrowHeight}`,
transform: 'translateX(-50%)',
},
- };
- }
-
- if (placement.startsWith('left')) {
- return {
+ },
+ '&[data-popper-placement^="left"]': {
position: 'absolute',
right: 0,
- __before: {
+ '::before': {
content: '""',
borderLeft: `${arrowHeight} solid`,
borderTop: `calc(${arrowWidth}/2) solid transparent`,
@@ -74,14 +67,11 @@ const useTooltipArrowStyle = ({
right: `-${arrowHeight}`,
transform: 'translateY(-50%)',
},
- };
- }
-
- if (placement.startsWith('right')) {
- return {
+ },
+ '&[data-popper-placement^="right"]': {
position: 'absolute',
left: 0,
- __before: {
+ '::before': {
content: '""',
borderRight: `${arrowHeight} solid`,
borderTop: `calc(${arrowWidth}/2) solid transparent`,
@@ -91,10 +81,8 @@ const useTooltipArrowStyle = ({
left: `-${arrowHeight}`,
transform: 'translateY(-50%)',
},
- };
- }
-
- return {};
+ },
+ };
};
const useTooltipTriggerStyle = () => {