Skip to content

Commit 7eca164

Browse files
committed
feat(graph): exposed custom tooltip prop on HTML graph (#102)
1 parent ff590a8 commit 7eca164

File tree

10 files changed

+278
-12
lines changed

10 files changed

+278
-12
lines changed

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ All components have optional props to further configure the log.
343343
| `highlightedBackgroundHeight` | `number` | The height, in pixels, of the background colour of a row that is being previewed or has been selected. |
344344
| `node` | [`CustomCommitNode`](#customcommitnode) | A function that returns a custom commit node implementation used by the graph. |
345345
| `breakPointTheme` | [`BreakPointTheme`](#breakpointtheme) | Changes how the break-points between rows render when the log is being filtered. |
346+
| `tooltip` | [`CustomTooltip`](#customtooltip) | Overrides the graph node tooltip with a custom implementation. Commit metadata is injected. |
346347

347348
#### CustomCommitNode
348349

@@ -380,6 +381,43 @@ The following properties are injected into the functions `props` argument:
380381
| `nodeSize` | `number` | The diameter (in pixels) of the node. This defaults but can be changed in the graph props. |
381382
| `isIndexPseudoNode` | `boolean` | Denotes whether the node is the "pseudo node" added above the head to represent the working tree index. |
382383
384+
#### CustomTooltip
385+
386+
A function with the following signature:
387+
```typescript
388+
type CustomTooltip = (props: CustomTooltipProps) => ReactElement<HTMLElement>
389+
```
390+
391+
For example:
392+
```typescript jsx
393+
<GitLog.GraphHTMLGrid
394+
showCommitNodeTooltips
395+
tooltip={({ commit, backgroundColour, borderColour }) => (
396+
<div
397+
data-testid='my-custom-tooltip'
398+
style={{
399+
border: `2px solid ${borderColour}`,
400+
backgroundColor: backgroundColour,
401+
color: 'white',
402+
padding: '20px 10px',
403+
borderRadius: '5px'
404+
}}
405+
>
406+
<p>My Custom Tooltip</p>
407+
<p>{commit.message}</p>
408+
</div>
409+
)}
410+
/>
411+
```
412+
413+
The following properties are injected into the functions `props` argument:
414+
415+
| Property | Type | Description |
416+
|--------------------|----------|-------------------------------------------------------------------------------|
417+
| `commit` | `Commit` | Details of the commit that the tooltip is being rendered for. |
418+
| `borderColour` | `string` | The border colour of the commit based on the column in its and the theme. |
419+
| `backgroundColour` | `number` | The background colour of the commit based on the column in its and the theme. |
420+
383421
### GraphCanvas2D
384422
385423
| Property | Type | Description |

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/demo/src/GitLog.stories.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,82 @@ export const CustomCommitNode = () => {
483483
)}
484484
/>
485485

486+
<GitLog.Table
487+
className={styles.table}
488+
/>
489+
</GitLog>
490+
)}
491+
</div>
492+
)
493+
}
494+
495+
export const CustomCommitTooltip = () => {
496+
const {
497+
loading,
498+
colours,
499+
entries,
500+
branch,
501+
buildUrls,
502+
repository,
503+
backgroundColour,
504+
handleChangeColors,
505+
handleChangeRepository
506+
} = useStoryState()
507+
508+
const { theme } = useDemoContext()
509+
510+
return (
511+
<div style={{ background: backgroundColour }} className={styles.container}>
512+
<StoryHeader
513+
colours={colours}
514+
repository={repository}
515+
onChangeColours={handleChangeColors}
516+
onChangeRepository={handleChangeRepository}
517+
/>
518+
519+
{loading && (
520+
<div className={styles.loading}>
521+
<Loading />
522+
</div>
523+
)}
524+
525+
{!loading && entries && (
526+
<GitLog
527+
colours={colours.colors}
528+
entries={entries}
529+
theme={theme}
530+
currentBranch={branch}
531+
classes={{
532+
containerStyles: {
533+
background: backgroundColour
534+
},
535+
containerClass: styles.gitLogContainer
536+
}}
537+
indexStatus={{
538+
added: 2,
539+
modified: 5,
540+
deleted: 1
541+
}}
542+
urls={buildUrls}
543+
>
544+
<GitLog.GraphHTMLGrid
545+
showCommitNodeTooltips
546+
tooltip={({ commit, backgroundColour, borderColour }) => (
547+
<div
548+
style={{
549+
border: `2px solid ${borderColour}`,
550+
backgroundColor: backgroundColour,
551+
color: 'white',
552+
padding: 20,
553+
borderRadius: 5
554+
}}
555+
>
556+
<p>My Custom Tooltip</p>
557+
<p>{commit.message.slice(0, 25)}</p>
558+
</div>
559+
)}
560+
/>
561+
486562
<GitLog.Table
487563
className={styles.table}
488564
/>

packages/library/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ All components have optional props to further configure the log.
260260
| `highlightedBackgroundHeight` | `number` | The height, in pixels, of the background colour of a row that is being previewed or has been selected. |
261261
| `node` | [`CustomCommitNode`](#customcommitnode) | A function that returns a custom commit node implementation used by the graph. |
262262
| `breakPointTheme` | [`BreakPointTheme`](#breakpointtheme) | Changes how the break-points between rows render when the log is being filtered. |
263+
| `tooltip` | [`CustomTooltip`](#customtooltip) | Overrides the graph node tooltip with a custom implementation. Commit metadata is injected. |
263264
264265
#### CustomCommitNode
265266
@@ -297,6 +298,43 @@ The following properties are injected into the functions `props` argument:
297298
| `nodeSize` | `number` | The diameter (in pixels) of the node. This defaults but can be changed in the graph props. |
298299
| `isIndexPseudoNode` | `boolean` | Denotes whether the node is the "pseudo node" added above the head to represent the working tree index. |
299300
301+
#### CustomTooltip
302+
303+
A function with the following signature:
304+
```typescript
305+
type CustomTooltip = (props: CustomTooltipProps) => ReactElement<HTMLElement>
306+
```
307+
308+
For example:
309+
```typescript jsx
310+
<GitLog.GraphHTMLGrid
311+
showCommitNodeTooltips
312+
tooltip={({ commit, backgroundColour, borderColour }) => (
313+
<div
314+
data-testid='my-custom-tooltip'
315+
style={{
316+
border: `2px solid ${borderColour}`,
317+
backgroundColor: backgroundColour,
318+
color: 'white',
319+
padding: '20px 10px',
320+
borderRadius: '5px'
321+
}}
322+
>
323+
<p>My Custom Tooltip</p>
324+
<p>{commit.message}</p>
325+
</div>
326+
)}
327+
/>
328+
```
329+
330+
The following properties are injected into the functions `props` argument:
331+
332+
| Property | Type | Description |
333+
|--------------------|----------|-------------------------------------------------------------------------------|
334+
| `commit` | `Commit` | Details of the commit that the tooltip is being rendered for. |
335+
| `borderColour` | `string` | The border colour of the commit based on the column in its and the theme. |
336+
| `backgroundColour` | `number` | The background colour of the commit based on the column in its and the theme. |
337+
300338
### GraphCanvas2D
301339
302340
| Property | Type | Description |

packages/library/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"author": "Thomas Plumpton",
44
"repository": "https://github.com/TomPlum/react-git-log",
55
"description": "A flexible, themable, React component for visualising Git commit history, branch and tag metadata.",
6-
"version": "3.4.2",
6+
"version": "3.5.0",
77
"license": "Apache-2.0",
88
"type": "module",
99
"main": "dist/react-git-log.js",

packages/library/src/modules/Graph/context/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { BreakPointTheme, NodeTheme } from 'hooks/useTheme'
2-
import { GraphOrientation } from 'modules/Graph'
2+
import { CustomTooltip, GraphOrientation } from 'modules/Graph'
33
import { Commit } from 'types/Commit'
44
import { RowIndexToColumnStates } from 'modules/Graph/strategies/Grid/hooks/useColumnData'
55
import { CustomCommitNode } from 'modules/Graph/strategies/Grid'
@@ -89,4 +89,10 @@ export interface GraphContextBag {
8989
* respective column states.
9090
*/
9191
columnData: RowIndexToColumnStates
92+
93+
/**
94+
* An optional custom tooltip implementation
95+
* passed in by the user.
96+
*/
97+
tooltip?: CustomTooltip
9298
}

packages/library/src/modules/Graph/core/GraphCore.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export const GraphCore = <T,>({
1818
enableResize = false,
1919
showCommitNodeHashes = false,
2020
showCommitNodeTooltips = false,
21-
highlightedBackgroundHeight
21+
highlightedBackgroundHeight,
22+
tooltip
2223
}: PropsWithChildren<GraphCoreProps<T>>) => {
2324
const {
2425
paging,
@@ -68,8 +69,9 @@ export const GraphCore = <T,>({
6869
visibleCommits,
6970
columnData,
7071
isHeadCommitVisible,
71-
highlightedBackgroundHeight
72-
}), [node, showCommitNodeTooltips, breakPointTheme, isHeadCommitVisible, showCommitNodeHashes, nodeTheme, nodeSize, graphWidth, virtualColumns, orientation, visibleCommits, columnData, highlightedBackgroundHeight])
72+
highlightedBackgroundHeight,
73+
tooltip
74+
}), [node, showCommitNodeTooltips, breakPointTheme, isHeadCommitVisible, showCommitNodeHashes, nodeTheme, nodeSize, graphWidth, virtualColumns, orientation, visibleCommits, columnData, highlightedBackgroundHeight, tooltip])
7375

7476
return (
7577
<GraphContext.Provider value={contextValue}>

packages/library/src/modules/Graph/strategies/Grid/components/CommitNode/CommitNode.spec.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,53 @@ describe('CommitNode', () => {
4949
expect(commitElement).toBeInTheDocument()
5050
})
5151

52+
it('should render a custom tooltip on hover of the node if the custom tooltip prop is passed', async () => {
53+
vi.spyOn(graphContext, 'useGraphContext').mockReturnValue(graphContextBag({
54+
showCommitNodeTooltips: true,
55+
tooltip: () => (
56+
<div data-testid='custom-tooltip'>
57+
Custom Tooltip
58+
</div>
59+
)
60+
}))
61+
62+
vi.spyOn(selectCommit, 'useSelectCommit').mockReturnValue({
63+
selectCommitHandler: {
64+
onMouseOut: vi.fn(),
65+
onClick: vi.fn(),
66+
onMouseOver: vi.fn()
67+
}
68+
})
69+
70+
vi.spyOn(themeHook, 'useTheme').mockReturnValue(themeFunctions())
71+
72+
render(
73+
<CommitNode
74+
colour='white'
75+
commit={commit({
76+
hash: 'commit-to-hover'
77+
})}
78+
/>
79+
)
80+
81+
const commitElement = commitNode.withHash({
82+
hash: 'commit-to-hover'
83+
})
84+
85+
await userEvent.hover(commitElement)
86+
expect(commitElement).toBeInTheDocument()
87+
88+
const tooltip = screen.getByTestId('custom-tooltip')
89+
expect(tooltip).toBeInTheDocument()
90+
expect(tooltip).toHaveTextContent('Custom Tooltip')
91+
92+
await userEvent.unhover(commitElement)
93+
await waitFor(() => {
94+
expect(tooltip).not.toBeInTheDocument()
95+
})
96+
expect(commitElement).toBeInTheDocument()
97+
})
98+
5299
it('should not render a tooltip on hover of the node if the prop is disabled', async () => {
53100
vi.spyOn(graphContext, 'useGraphContext').mockReturnValue(graphContextBag({
54101
showCommitNodeTooltips: false

packages/library/src/modules/Graph/strategies/Grid/components/CommitNode/CommitNode.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const CommitNode = ({ commit, colour }: CommitNodeProps) => {
1414
const { selectCommitHandler } = useSelectCommit()
1515
const { remoteProviderUrlBuilder } = useGitContext()
1616
const { textColour, theme, getCommitNodeColours } = useTheme()
17-
const { showCommitNodeTooltips, showCommitNodeHashes, nodeTheme, nodeSize } = useGraphContext()
17+
const { showCommitNodeTooltips, showCommitNodeHashes, nodeTheme, nodeSize, tooltip } = useGraphContext()
1818

1919
const commitHashLabelHeight = 20
2020
const isMergeCommit = nodeTheme === 'default' && commit.parents.length > 1
@@ -69,12 +69,21 @@ export const CommitNode = ({ commit, colour }: CommitNodeProps) => {
6969
childRect={childRect}
7070
popoverRect={popoverRect}
7171
>
72-
<CommitNodeTooltip
73-
commit={commit}
74-
color={borderColour}
75-
/>
72+
{
73+
tooltip
74+
? tooltip({
75+
commit,
76+
borderColour,
77+
backgroundColour
78+
}) : (
79+
<CommitNodeTooltip
80+
commit={commit}
81+
color={borderColour}
82+
/>
83+
)
84+
}
7685
</ArrowContainer>
77-
), [borderColour, commit])
86+
), [backgroundColour, borderColour, commit, tooltip])
7887

7988
return (
8089
<Popover

0 commit comments

Comments
 (0)