Skip to content

Commit 296223f

Browse files
committed
fix: arrow styles when bigger border and bigger size
1 parent 015b900 commit 296223f

7 files changed

Lines changed: 100 additions & 346 deletions

File tree

src/components/Tooltip/Tooltip.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
computeTooltipPosition,
1010
cssTimeToMs,
1111
clearTimeoutRef,
12+
getBorderWidth,
13+
getBorderColor,
1214
} from 'utils'
1315
import type { IComputedPosition } from 'utils'
1416
import { useTooltip } from 'components/TooltipProvider'
@@ -96,6 +98,10 @@ const Tooltip = ({
9698
const hoveringTooltip = useRef(false)
9799
const [anchorsBySelect, setAnchorsBySelect] = useState<HTMLElement[]>([])
98100
const mounted = useRef(false)
101+
const arrowBorderWidth = getBorderWidth(border)
102+
const arrowBorderColor = getBorderColor(border)
103+
const arrowBackground =
104+
border && arrowBorderColor ? arrowBorderColor : (arrowColor ?? 'var(--rt-tooltip-background)')
99105

100106
/**
101107
* @todo Update when deprecated stuff gets removed.
@@ -937,13 +943,15 @@ const Tooltip = ({
937943
)}
938944
style={{
939945
...computedPosition.tooltipArrowStyles,
940-
background: arrowColor
941-
? `linear-gradient(to right bottom, transparent 50%, ${arrowColor} 50%)`
942-
: undefined,
943946
'--rt-arrow-size': `${arrowSize}px`,
947+
'--rt-arrow-background': arrowBackground,
948+
'--rt-arrow-border-width': arrowBorderColor ? arrowBorderWidth : '0px',
949+
'--rt-arrow-border-color': arrowBorderColor,
944950
}}
945951
ref={tooltipArrowRef}
946-
/>
952+
>
953+
<WrapperElement className={coreStyles['arrowInner']} />
954+
</WrapperElement>
947955
</WrapperElement>
948956
) : null
949957
}

src/components/Tooltip/core-styles.module.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@
1313

1414
.arrow {
1515
position: absolute;
16-
background: inherit;
1716
z-index: -1;
1817
clip-path: polygon(0% 100%, 100% 0%, 100% 100%);
18+
background: var(--rt-arrow-border-color, var(--rt-arrow-background));
19+
overflow: hidden;
20+
}
21+
22+
.arrowInner {
23+
position: absolute;
24+
inset: var(--rt-arrow-border-width, 0px);
25+
background: var(--rt-arrow-background);
1926
}
2027

2128
.noArrow {

src/components/Tooltip/styles.module.css

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,37 @@
2828

2929
/** Types variant **/
3030
.dark {
31-
background: var(--rt-color-dark);
31+
--rt-tooltip-background: var(--rt-color-dark);
32+
background: var(--rt-tooltip-background);
3233
color: var(--rt-color-white);
3334
}
3435

3536
.light {
36-
background-color: var(--rt-color-white);
37+
--rt-tooltip-background: var(--rt-color-white);
38+
background-color: var(--rt-tooltip-background);
3739
color: var(--rt-color-dark);
3840
}
3941

4042
.success {
41-
background-color: var(--rt-color-success);
43+
--rt-tooltip-background: var(--rt-color-success);
44+
background-color: var(--rt-tooltip-background);
4245
color: var(--rt-color-white);
4346
}
4447

4548
.warning {
46-
background-color: var(--rt-color-warning);
49+
--rt-tooltip-background: var(--rt-color-warning);
50+
background-color: var(--rt-tooltip-background);
4751
color: var(--rt-color-white);
4852
}
4953

5054
.error {
51-
background-color: var(--rt-color-error);
55+
--rt-tooltip-background: var(--rt-color-error);
56+
background-color: var(--rt-tooltip-background);
5257
color: var(--rt-color-white);
5358
}
5459

5560
.info {
56-
background-color: var(--rt-color-info);
61+
--rt-tooltip-background: var(--rt-color-info);
62+
background-color: var(--rt-tooltip-background);
5763
color: var(--rt-color-white);
5864
}

src/utils/border-style.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { CSSProperties } from 'react'
2+
3+
/**
4+
* Extract the width token from a CSS border shorthand so arrow styles can
5+
* reuse the same thickness as the tooltip border.
6+
*/
7+
const getBorderWidth = (border?: CSSProperties['border']) => {
8+
if (!border) {
9+
return '0px'
10+
}
11+
12+
const match = `${border}`.match(/(\d+px)/)
13+
return match?.[1] ?? '1px'
14+
}
15+
16+
/**
17+
* Extract the color token from a CSS border shorthand so the arrow border/fill
18+
* can stay visually aligned with the tooltip border.
19+
*/
20+
const getBorderColor = (border?: CSSProperties['border']) => {
21+
if (!border) {
22+
return undefined
23+
}
24+
25+
const parts = `${border}`.trim().split(/\s+/)
26+
if (parts.length >= 3) {
27+
return parts.slice(2).join(' ')
28+
}
29+
if (parts.length === 2) {
30+
return parts[1]
31+
}
32+
return parts[0]
33+
}
34+
35+
export { getBorderWidth, getBorderColor }

src/utils/compute-tooltip-position.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ const computeTooltipPosition = async ({
5353
}[placement.split('-')[0]] ?? 'bottom'
5454
/* c8 ignore end */
5555

56-
const borderSide = border && {
57-
borderBottom: border,
58-
borderRight: border,
59-
}
60-
6156
let borderWidth = 0
6257
if (border) {
6358
const match = `${border}`.match(/(\d+)px/)
@@ -78,8 +73,10 @@ const computeTooltipPosition = async ({
7873
top: arrowY != null ? `${arrowY}px` : '',
7974
right: '',
8075
bottom: '',
81-
...borderSide,
82-
[staticSide]: `-${arrowSize / 2 + borderWidth}px`,
76+
// Keep the arrow tucked under the tooltip body. When the tooltip has a
77+
// border, offset by that width, but do not draw a separate arrow border:
78+
// the rotated/clipped element cannot render that seam cleanly.
79+
[staticSide]: `-${arrowSize * 0.5 + borderWidth}px`,
8380
}
8481
/* c8 ignore end */
8582

src/utils/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import deepEqual from './deep-equal'
77
import getScrollParent from './get-scroll-parent'
88
import useIsomorphicLayoutEffect from './use-isomorphic-layout-effect'
99
import clearTimeoutRef from './clear-timeout-ref'
10+
import { getBorderWidth, getBorderColor } from './border-style'
1011

1112
export type { IComputedPosition }
1213
export {
@@ -18,4 +19,6 @@ export {
1819
getScrollParent,
1920
useIsomorphicLayoutEffect,
2021
clearTimeoutRef,
22+
getBorderWidth,
23+
getBorderColor,
2124
}

0 commit comments

Comments
 (0)