@@ -6,10 +6,15 @@ import {invariant} from '../utils/invariant'
6
6
import { warning } from '../utils/warning'
7
7
import styled from 'styled-components'
8
8
import { get } from '../constants'
9
- import type { ComponentProps } from '../utils/types'
10
9
import { getAnchoredPosition } from '@primer/behaviors'
11
10
import type { AnchorSide , AnchorAlignment } from '@primer/behaviors'
12
11
import { isSupported , apply } from '@oddbird/popover-polyfill/fn'
12
+ import { toggleStyledComponent } from '../internal/utils/toggleStyledComponent'
13
+ import { clsx } from 'clsx'
14
+ import classes from './Tooltip.module.css'
15
+ import { useFeatureFlag } from '../FeatureFlags'
16
+
17
+ const CSS_MODULE_FEATURE_FLAG = 'primer_react_css_modules_team'
13
18
14
19
const animationStyles = `
15
20
animation-name: tooltip-appear;
@@ -19,119 +24,123 @@ const animationStyles = `
19
24
animation-delay: 0s;
20
25
`
21
26
22
- const StyledTooltip = styled . span `
23
- /* Overriding the default popover styles */
24
- display: none;
25
- &[popover] {
26
- position: absolute;
27
- padding: 0.5em 0.75em;
28
- width: max-content;
29
- margin: auto;
30
- clip: auto;
31
- white-space: normal;
32
- font: normal normal 11px/1.5 ${ get ( 'fonts.normal' ) } ;
33
- -webkit-font-smoothing: subpixel-antialiased;
34
- color: var(--tooltip-fgColor, ${ get ( 'colors.fg.onEmphasis' ) } );
35
- text-align: center;
36
- word-wrap: break-word;
37
- background: var(--tooltip-bgColor, ${ get ( 'colors.neutral.emphasisPlus' ) } );
38
- border-radius: ${ get ( 'radii.2' ) } ;
39
- border: 0;
40
- opacity: 0;
41
- max-width: 250px;
42
- inset: auto;
43
- /* for scrollbar */
44
- overflow: visible;
45
- }
46
- /* class name in chrome is :popover-open */
47
- &[popover]:popover-open {
48
- display: block;
49
- }
50
- /* class name in firefox and safari is \:popover-open */
51
- &[popover].\\:popover-open {
52
- display: block;
53
- }
27
+ const StyledTooltip = toggleStyledComponent (
28
+ CSS_MODULE_FEATURE_FLAG ,
29
+ 'span' ,
30
+ styled . span `
31
+ /* Overriding the default popover styles */
32
+ display: none;
33
+ &[popover] {
34
+ position: absolute;
35
+ padding: 0.5em 0.75em;
36
+ width: max-content;
37
+ margin: auto;
38
+ clip: auto;
39
+ white-space: normal;
40
+ font: normal normal 11px/1.5 ${ get ( 'fonts.normal' ) } ;
41
+ -webkit-font-smoothing: subpixel-antialiased;
42
+ color: var(--tooltip-fgColor, ${ get ( 'colors.fg.onEmphasis' ) } );
43
+ text-align: center;
44
+ word-wrap: break-word;
45
+ background: var(--tooltip-bgColor, ${ get ( 'colors.neutral.emphasisPlus' ) } );
46
+ border-radius: ${ get ( 'radii.2' ) } ;
47
+ border: 0;
48
+ opacity: 0;
49
+ max-width: 250px;
50
+ inset: auto;
51
+ /* for scrollbar */
52
+ overflow: visible;
53
+ }
54
+ /* class name in chrome is :popover-open */
55
+ &[popover]:popover-open {
56
+ display: block;
57
+ }
58
+ /* class name in firefox and safari is \:popover-open */
59
+ &[popover].\\:popover-open {
60
+ display: block;
61
+ }
54
62
55
- @media (forced-colors: active) {
56
- outline: 1px solid transparent;
57
- }
63
+ @media (forced-colors: active) {
64
+ outline: 1px solid transparent;
65
+ }
58
66
59
- // This is needed to keep the tooltip open when the user leaves the trigger element to hover tooltip
60
- &::after {
61
- position: absolute;
62
- display: block;
63
- right: 0;
64
- left: 0;
65
- height: var(--overlay-offset, 0.25rem);
66
- content: '';
67
- }
67
+ // This is needed to keep the tooltip open when the user leaves the trigger element to hover tooltip
68
+ &::after {
69
+ position: absolute;
70
+ display: block;
71
+ right: 0;
72
+ left: 0;
73
+ height: var(--overlay-offset, 0.25rem);
74
+ content: '';
75
+ }
68
76
69
- /* South, East, Southeast, Southwest after */
70
- &[data-direction='n']::after,
71
- &[data-direction='ne']::after,
72
- &[data-direction='nw']::after {
73
- top: 100%;
74
- }
75
- &[data-direction='s']::after,
76
- &[data-direction='se']::after,
77
- &[data-direction='sw']::after {
78
- bottom: 100%;
79
- }
77
+ /* South, East, Southeast, Southwest after */
78
+ &[data-direction='n']::after,
79
+ &[data-direction='ne']::after,
80
+ &[data-direction='nw']::after {
81
+ top: 100%;
82
+ }
83
+ &[data-direction='s']::after,
84
+ &[data-direction='se']::after,
85
+ &[data-direction='sw']::after {
86
+ bottom: 100%;
87
+ }
80
88
81
- &[data-direction='w']::after {
82
- position: absolute;
83
- display: block;
84
- height: 100%;
85
- width: 8px;
86
- content: '';
87
- bottom: 0;
88
- left: 100%;
89
- }
90
- /* East before and after */
91
- &[data-direction='e']::after {
92
- position: absolute;
93
- display: block;
94
- height: 100%;
95
- width: 8px;
96
- content: '';
97
- bottom: 0;
98
- right: 100%;
99
- margin-left: -8px;
100
- }
89
+ &[data-direction='w']::after {
90
+ position: absolute;
91
+ display: block;
92
+ height: 100%;
93
+ width: 8px;
94
+ content: '';
95
+ bottom: 0;
96
+ left: 100%;
97
+ }
98
+ /* East before and after */
99
+ &[data-direction='e']::after {
100
+ position: absolute;
101
+ display: block;
102
+ height: 100%;
103
+ width: 8px;
104
+ content: '';
105
+ bottom: 0;
106
+ right: 100%;
107
+ margin-left: -8px;
108
+ }
101
109
102
- /* Animation definition */
103
- @keyframes tooltip-appear {
104
- from {
105
- opacity: 0;
110
+ /* Animation definition */
111
+ @keyframes tooltip-appear {
112
+ from {
113
+ opacity: 0;
114
+ }
115
+ to {
116
+ opacity: 1;
117
+ }
106
118
}
107
- to {
108
- opacity: 1;
119
+ /* Animation styles */
120
+ &:popover-open,
121
+ &:popover-open::before {
122
+ ${ animationStyles }
109
123
}
110
- }
111
- /* Animation styles */
112
- &:popover-open,
113
- &:popover-open::before {
114
- ${ animationStyles }
115
- }
116
124
117
- /* Animation styles */
118
- &.\\:popover-open,
119
- &.\\:popover-open::before {
120
- ${ animationStyles }
121
- }
125
+ /* Animation styles */
126
+ &.\\:popover-open,
127
+ &.\\:popover-open::before {
128
+ ${ animationStyles }
129
+ }
122
130
123
- ${ sx } ;
124
- `
131
+ ${ sx } ;
132
+ ` ,
133
+ )
125
134
126
135
export type TooltipDirection = 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w'
127
136
export type TooltipProps = React . PropsWithChildren <
128
137
{
129
138
direction ?: TooltipDirection
130
139
text : string
131
140
type ?: 'label' | 'description'
132
- } & SxProp &
133
- ComponentProps < typeof StyledTooltip >
134
- >
141
+ } & SxProp
142
+ > &
143
+ React . HTMLAttributes < HTMLElement >
135
144
136
145
type TriggerPropsType = {
137
146
'aria-describedby' ?: string
@@ -187,11 +196,12 @@ const isInteractive = (element: HTMLElement) => {
187
196
export const TooltipContext = React . createContext < { tooltipId ?: string } > ( { } )
188
197
189
198
export const Tooltip = React . forwardRef (
190
- ( { direction = 's' , text, type = 'description' , children, id, ...rest } : TooltipProps , forwardedRef ) => {
199
+ ( { direction = 's' , text, type = 'description' , children, id, className , ...rest } : TooltipProps , forwardedRef ) => {
191
200
const tooltipId = useId ( id )
192
201
const child = Children . only ( children )
193
202
const triggerRef = useProvidedRefOrCreate ( forwardedRef as React . RefObject < HTMLElement > )
194
203
const tooltipElRef = useRef < HTMLDivElement > ( null )
204
+ const enabled = useFeatureFlag ( CSS_MODULE_FEATURE_FLAG )
195
205
196
206
const [ calculatedDirection , setCalculatedDirection ] = useState < TooltipDirection > ( direction )
197
207
@@ -355,6 +365,7 @@ export const Tooltip = React.forwardRef(
355
365
} ,
356
366
} ) }
357
367
< StyledTooltip
368
+ className = { clsx ( className , { [ classes . Tooltip ] : enabled } ) }
358
369
ref = { tooltipElRef }
359
370
data-direction = { calculatedDirection }
360
371
{ ...rest }
0 commit comments