Skip to content

Commit 3816d14

Browse files
gabrieljablonskidanielbarion
authored andcommitted
add provider context data wrapper
1 parent 1faedc8 commit 3816d14

File tree

2 files changed

+72
-26
lines changed

2 files changed

+72
-26
lines changed

src/App.tsx

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import { useEffect, useRef, useState } from 'react'
44
import styles from './styles.module.css'
55

66
function WithProvider() {
7-
const tooltipper = useTooltip()
8-
const { attach, detach } = tooltipper()
9-
const { attach: attach1, detach: detach1 } = tooltipper('tooltip-1')
10-
const { attach: attach2, detach: detach2 } = tooltipper('tooltip-2')
7+
const { attach, detach } = useTooltip()
8+
const { attach: attach1, detach: detach1 } = useTooltip()('tooltip-1')
9+
const { attach: attach2, detach: detach2 } = useTooltip()('tooltip-2')
1110
const buttonRef1 = useRef<HTMLButtonElement>(null)
1211
const buttonRef2 = useRef<HTMLButtonElement>(null)
1312
const buttonRef3 = useRef<HTMLButtonElement>(null)
@@ -29,40 +28,62 @@ function WithProvider() {
2928
return (
3029
<section style={{ marginTop: '100px' }}>
3130
<p>
32-
<button
33-
ref={buttonRef1}
34-
data-tooltip-place="right"
35-
data-tooltip-content="Hello World from a Shared Global Tooltip"
36-
>
37-
Hover or focus me 5
31+
<button ref={buttonRef1} data-tooltip-content="Shared Global Tooltip">
32+
Provider 1
3833
</button>
39-
<button ref={buttonRef2} data-tooltip-content="Hello World from a Shared Global Tooltip">
40-
Hover or focus me 6
34+
<button ref={buttonRef2} data-tooltip-content="Shared Global Tooltip">
35+
Provider 2
4136
</button>
4237
</p>
4338
<p>
44-
<button ref={buttonRef3} data-tooltip-content="Hello World from Shared Tooltip 1">
45-
Hover or focus me 7
39+
<button ref={buttonRef3} data-tooltip-content="Shared Tooltip 1">
40+
Provider 3
4641
</button>
47-
<button ref={buttonRef4} data-tooltip-content="Hello World from Shared Tooltip 1">
48-
Hover or focus me 8
42+
<button ref={buttonRef4} data-tooltip-content="Shared Tooltip 1">
43+
Provider 4
4944
</button>
5045
</p>
5146
<p>
52-
<button ref={buttonRef5} data-tooltip-content="Hello World from Shared Tooltip 2">
53-
Hover or focus me 9
47+
<button ref={buttonRef5} data-tooltip-content="Shared Tooltip 2">
48+
Provider 5
5449
</button>
55-
<button ref={buttonRef6} data-tooltip-content="Hello World from Shared Tooltip 2">
56-
Hover or focus me 10
50+
<button ref={buttonRef6} data-tooltip-content="Shared Tooltip 2">
51+
Provider 6
5752
</button>
5853
</p>
59-
<Tooltip />
6054
<Tooltip id="tooltip-1" />
6155
<Tooltip id="tooltip-2" />
6256
</section>
6357
)
6458
}
6559

60+
function WithProviderMinimal() {
61+
const { attach, detach } = useTooltip()
62+
const buttonRef1 = useRef<HTMLButtonElement>(null)
63+
const buttonRef2 = useRef<HTMLButtonElement>(null)
64+
65+
useEffect(() => {
66+
attach(buttonRef1, buttonRef2)
67+
return () => {
68+
detach(buttonRef1, buttonRef2)
69+
}
70+
}, [])
71+
72+
return (
73+
<section style={{ marginTop: '100px' }}>
74+
<p>
75+
<button ref={buttonRef1} data-tooltip-content="Shared Global Tooltip">
76+
Minimal 1
77+
</button>
78+
<button ref={buttonRef2} data-tooltip-content="Shared Global Tooltip">
79+
Minimal 2
80+
</button>
81+
</p>
82+
<Tooltip />
83+
</section>
84+
)
85+
}
86+
6687
function App() {
6788
const [anchorId, setAnchorId] = useState('button')
6889
const [isDarkOpen, setIsDarkOpen] = useState(false)
@@ -136,6 +157,9 @@ function App() {
136157
<TooltipProvider>
137158
<WithProvider />
138159
</TooltipProvider>
160+
<TooltipProvider>
161+
<WithProviderMinimal />
162+
</TooltipProvider>
139163
</main>
140164
)
141165
}

src/components/TooltipProvider/TooltipProvider.tsx

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,26 @@ import React, {
44
useCallback,
55
useContext,
66
useId,
7+
useMemo,
78
useState,
89
} from 'react'
910

1011
type AnchorRef = React.RefObject<HTMLElement>
1112

1213
interface TooltipContextData {
13-
// when using one tooltip
1414
anchorRefs: Set<AnchorRef>
1515
activeAnchor: AnchorRef
1616
attach: (...refs: AnchorRef[]) => void
1717
detach: (...refs: AnchorRef[]) => void
1818
setActiveAnchor: (ref: AnchorRef) => void
1919
}
2020

21-
type TooltipContextDataBuilder = (tooltipId?: string) => TooltipContextData
21+
type TooltipContextDataWrapper = TooltipContextData & {
22+
// This means the context is a callable object
23+
(tooltipId?: string): TooltipContextData
24+
}
2225

23-
const TooltipContext = createContext<TooltipContextDataBuilder>(() => ({
26+
const defaultContextData: TooltipContextData = {
2427
anchorRefs: new Set(),
2528
activeAnchor: { current: null },
2629
attach: () => {
@@ -32,7 +35,10 @@ const TooltipContext = createContext<TooltipContextDataBuilder>(() => ({
3235
setActiveAnchor: () => {
3336
/* set active anchor */
3437
},
35-
}))
38+
}
39+
40+
const defaultContextWrapper = Object.assign(() => defaultContextData, defaultContextData)
41+
const TooltipContext = createContext<TooltipContextDataWrapper>(defaultContextWrapper)
3642

3743
const TooltipProvider: React.FC<PropsWithChildren> = ({ children }) => {
3844
const defaultTooltipId = useId()
@@ -73,7 +79,7 @@ const TooltipProvider: React.FC<PropsWithChildren> = ({ children }) => {
7379
})
7480
}
7581

76-
const context = useCallback(
82+
const getTooltipData = useCallback(
7783
(tooltipId?: string) => ({
7884
anchorRefs: anchorRefMap[tooltipId ?? defaultTooltipId] ?? new Set(),
7985
activeAnchor: activeAnchorMap[tooltipId ?? defaultTooltipId] ?? { current: null },
@@ -84,9 +90,25 @@ const TooltipProvider: React.FC<PropsWithChildren> = ({ children }) => {
8490
[defaultTooltipId, anchorRefMap, activeAnchorMap, attach, detach],
8591
)
8692

93+
const context = useMemo(() => {
94+
const contextData: TooltipContextData = getTooltipData(defaultTooltipId)
95+
const contextWrapper = Object.assign(
96+
(tooltipId?: string) => getTooltipData(tooltipId),
97+
contextData,
98+
)
99+
return contextWrapper
100+
}, [getTooltipData])
101+
87102
return <TooltipContext.Provider value={context}>{children}</TooltipContext.Provider>
88103
}
89104

105+
/*
106+
// this will use the "global" tooltip (same as `useTooltip()()`)
107+
const { anchorRefs, attach, detach } = useTooltip()
108+
109+
// this will use the tooltip with id `tooltip-id`
110+
const { anchorRefs, attach, detach } = useTooltip()('tooltip-id')
111+
*/
90112
export function useTooltip() {
91113
return useContext(TooltipContext)
92114
}

0 commit comments

Comments
 (0)