Skip to content

Commit 2d17c57

Browse files
authored
Merge pull request #21 from TomPlum/develop
Fixed graph and table empty state
2 parents d1a8128 + 2c889a3 commit 2d17c57

16 files changed

Lines changed: 213 additions & 53 deletions

File tree

packages/demo/.storybook/preview.scss

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@
2222
font-display: swap;
2323
}
2424

25-
#storybook-root {
26-
height: 100%;
27-
}
28-
2925
html,
30-
body {
26+
body,
27+
#storybook-preview-iframe,
28+
#storybook-root {
3129
margin: 0;
3230
padding: 0;
31+
height: 100%;
32+
overflow: hidden;
3333
font-family: 'JetBrains Mono', system-ui, Avenir, Helvetica, Arial, sans-serif;
34-
min-height: 100%;
3534
}

packages/demo/src/GitLog.stories.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
.container {
22
padding: 20px;
33
box-sizing: border-box;
4+
display: flex;
45
height: 100%;
6+
flex-direction: column;
7+
overflow-y: auto;
8+
}
9+
10+
.gitLogContainer {
11+
flex: 1;
512
}
613

714
.loading {

packages/demo/src/GitLog.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ export const Default: Story = {
283283
containerStyles: {
284284
background: backgroundColour
285285
},
286+
containerClass: styles.gitLogContainer,
286287
logTableClass: styles.table
287288
}}
288289
/>

packages/demo/src/components/PackageInfo/PackageInfo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export const PackageInfo = ({ theme }: PackageInfoProps) => {
88
return (
99
<a href='https://github.com/TomPlum/react-git-log' className={styles.info}>
1010
<div className={styles.top}>
11-
<a className={styles.packageName}>
11+
<span className={styles.packageName}>
1212
react-git-log
13-
</a>
13+
</span>
1414
</div>
1515

1616
<div className={styles.bottom}>

packages/library/README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
![NPM Version](https://img.shields.io/npm/v/%40tomplum%2Freact-git-log?style=for-the-badge&logo=npm&color=red&logoColor=red)
2+
![GitHub Release](https://img.shields.io/github/v/release/TomPlum/react-git-log?style=for-the-badge&logo=github&color=green)
3+
![NPM Type Definitions](https://img.shields.io/npm/types/%40tomplum%2Freact-git-log?style=for-the-badge&logo=typescript)
4+
![npm package minimized gzipped size](https://img.shields.io/bundlejs/size/%40tomplum%2Freact-git-log?style=for-the-badge&logo=vite&color=gold&logoColor=gold)
5+
6+
# :seedling: React Git Log
7+
8+
A flexible and interactive React component for visualising Git commit history. Displays a branching graph alongside commit, branch and tag metadata, with support for customised theming.
9+
10+
# Features
11+
12+
- :seedling: Responsive commit history graph
13+
- :memo: Table with commit message and date
14+
- :bookmark: Branch and tagging information
15+
- :art: Custom theming API
16+
- :waning_crescent_moon: Dark and light modes
17+
18+
# Using the component
19+
20+
1. Install the package using your preferred package manager.
21+
22+
Using npm
23+
```shell
24+
npm install @tomplum/react-git-log
25+
```
26+
27+
Using yarn
28+
```shell
29+
yarn add @tomplum/react-git-log
30+
```
31+
32+
Using pnpm
33+
```shell
34+
pnpm add @tomplum/react-git-log
35+
```
36+
37+
2. Make sure that `react` and `react-dom` are installed in your project, as they are peer dependencies.
38+
39+
```shell
40+
npm install react react-dom
41+
```
42+
43+
3. Render the component in your application.
44+
45+
Below is an example `YourConsumer.tsx` component that is using `GitLog`. See the [required](#required) component props to get started and the [optional](#optional) props for further configuration and theming.
46+
47+
```typescript jsx
48+
import { GitLog } from "@tomplum/react-git-log"
49+
50+
const YourConsumer = () => {
51+
const { entries, currentBranch } = useYourDataSource()
52+
53+
return (
54+
<GitLog
55+
entries={entries} // <-- Pass the git log entry data in
56+
currentBranch={currentBranch} // <-- Tell it the branch that is checked out
57+
/>
58+
)
59+
}
60+
```
61+
62+
# Git Log Data
63+
64+
The array of `GitLogEntry` objects is the source of data used by the `GitLog` component. It has the following properties:
65+
66+
| Property | Type | Description |
67+
|-----------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
68+
| `hash` | `string` | The unique hash identifier of the commit. |
69+
| `branch` | `string` | The name of the branch this commit belongs to. |
70+
| `parents` | `string[]` | An array of parent commit hashes. If this is a merge commit, it will have multiple parents. If it's an initial commit, it will have none. |
71+
| `message` | `string` | The commit message describing the changes made in this commit. |
72+
| `committerDate` | `string` | The date and time when the commit was applied by the committer. Typically the timestamp when the commit was finalized. |
73+
| `authorDate` | `string?` | *(Optional)* The date and time when the commit was originally authored. May differ from `committerDate` if the commit was rebased or amended. |
74+
75+
> [!TIP]
76+
> Usually you'd be sourcing this data from a backend service like a web-api, but you can extract it from the command line with the following command.
77+
78+
```bash
79+
git log --all --pretty=format:'hash:%h,parents:%p,branch:%S,msg:%s,cdate:%cd,adate:%ad' --date=iso >> git-log.txt
80+
```
81+
82+
This will write `git-log.txt` in the directory where you ran the command. It can be passed to the `parseGitLog.ts` function from the library to produce an array of `GitLogEntry`.
83+
84+
# Component Props
85+
86+
## Required
87+
88+
| Prop | Type | Description |
89+
|-------------------------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
90+
| `entries` | `GitLogEntry[]` | The git log entries to visualize on the graph. |
91+
| `currentBranch` | `string` | The name of the branch that is currently checked out. |
92+
93+
## Optional
94+
95+
| Prop | Type | Description |
96+
|-------------------------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
97+
| `theme` | `ThemeMode` | The variant of the default color theme to apply to the log. |
98+
| `colours` | `ThemeColours \| string[]` | An array of colors used to color the log elements such as the graph. If not enough colors are provided, they will loop back from the start. |
99+
| `nodeTheme` | `NodeTheme` | The theme to apply the commit node elements in the graph. |
100+
| `showBranchesTags` | `boolean` | Whether to show labels for nodes that are the tips of branches or tags in the graph. |
101+
| `showTable` | `boolean` | Whether to show a table of commit metadata on the right-hand side of the graph. |
102+
| `showCommitNodeHashes` | `boolean` | Whether to show the commit hash next to the node in the graph. |
103+
| `showCommitNodeTooltips` | `boolean` | Whether to show tooltips when hovering over a commit node in the graph. |
104+
| `showTableHeaders` | `boolean` | Whether to show the names of the elements at the top of the component (e.g., "Graph", "Commit message"). |
105+
| `enableExperimentalAnimation` | `boolean` | Enables Framer Motion animation for simple fading transitions. Experimental feature. |
106+
| `enableResize` | `boolean` | Enables the graph's horizontal width to be resized. (Default: `false`) |
107+
| `rowSpacing` | `number` | The spacing between the rows of the log, affecting all elements across branches, graph, and table. (Default: `0`) |
108+
| `githubRepositoryUrl` | `string` | A link to the GitHub repository from which the log entries came. Enables links for commits, tags, and PRs. |
109+
| `defaultGraphContainerWidth` | `number` | The default width of the graph in pixels. (Default: `300`) |
110+
| `timestampFormat` | `string` | A timestamp format string passed to DayJS to format commit timestamps. (Default: `ISO-8601`) |
111+
| `onSelectCommit` | `(commit?: Commit) => void` | A callback function invoked when a commit is selected or unselected. |
112+
| `classes` | `GitLogStylingProps` | CSS classes for various underlying elements for custom styling. |
113+
| `paging` | `GitLogPaging` | Optional paging information to show a window of the given size from the set of git log entries. |
114+
115+
### GitLogStylingProps
116+
117+
| Prop | Type | Description |
118+
|-------------------|---------------------------------------------------------------------------------------------|---------------------------------------------------------|
119+
| `containerClass` | `string` | A class name for the wrapping container around the log. |
120+
| `containerStyles` | `CSSProperties` | A React CSS styling object for the wrapping container. |
121+
| `logTableClass` | `string` | A class name for the table element in the git log. |
122+
| `logTableStyles` | `{ table?: CSSProperties; thead?: CSSProperties; tr?: CSSProperties; td?: CSSProperties; }` | A React CSS styling object for the git log table. |
123+
124+
### GitLogPaging
125+
126+
| Prop | Type | Description |
127+
|--------|----------|-------------------------------------------------|
128+
| `size` | `number` | The number of rows to show per page. |
129+
| `page` | `number` | The page number to display (first page is `0`). |
130+
131+
### NodeTheme
132+
133+
| Prop | Type | Description |
134+
|-----------|----------|-----------------------------------------------------------------------|
135+
| `default` | `string` | The default theme where nodes change their style based on their type. |
136+
| `plain` | `string` | All nodes look the same, except for their colours. |

packages/library/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@tomplum/react-git-log",
33
"repository": "https://github.com/TomPlum/react-git-log",
44
"description": "A flexible, themable, React component for visualising Git commit history, branch and tag metadata.",
5-
"version": "1.0.0",
5+
"version": "1.0.1",
66
"type": "module",
77
"main": "dist/react-git-log.umd.js",
88
"module": "dist/react-git-log.es.js",

packages/library/src/Layout.module.scss

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22
position: relative;
33
width: 100%;
44
height: 100%;
5-
background: white;
65
display: flex;
76

87
.tags {
98
flex-grow: 1;
109
max-width: 175px;
1110
}
1211

13-
.graph {
14-
flex-grow: 1;
15-
}
16-
1712
.table {
1813
flex-grow: 1;
1914
}
@@ -24,22 +19,3 @@
2419
line-height: 22px;
2520
font-weight: 600;
2621
}
27-
28-
.selected {
29-
position: absolute;
30-
$borderRadius: 20px;
31-
border-bottom-left-radius: $borderRadius;
32-
border-top-left-radius: $borderRadius;
33-
right: 0;
34-
opacity: 0.15;
35-
z-index: 0;
36-
}
37-
38-
.hovered {
39-
$borderRadius: 20px;
40-
border-bottom-left-radius: $borderRadius;
41-
border-top-left-radius: $borderRadius;
42-
position: absolute;
43-
right: 0;
44-
z-index: 0;
45-
}

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useColumnData } from 'modules/Graph/hooks/useColumnData'
77
import { SkeletonGraph } from 'modules/Graph/components/SkeletonGraph'
88
import { useResize } from 'hooks/useResize'
99
import { ROW_HEIGHT } from 'constants/constants'
10+
import { placeholderCommits } from 'modules/Graph/hooks/usePlaceholderData/data'
1011

1112
export const Graph = () => {
1213
const {
@@ -17,21 +18,38 @@ export const Graph = () => {
1718
} = useGitContext()
1819

1920
const { width, ref, startResizing } = useResize()
20-
2121
const { columnData, getEmptyColumnState } = useColumnData()
2222

2323
const visibleCommits = useMemo(() => {
2424
return commits.slice(paging.startIndex, paging.endIndex)
2525
}, [commits, paging])
2626

27+
const commitQuantity = useMemo(() => {
28+
// If there is no data being show, then we'll
29+
// be rendering the skeleton graph placeholder which
30+
// shows fake commits.
31+
if (visibleCommits.length === 0) {
32+
return placeholderCommits.length
33+
}
34+
35+
// If the index node is visible then we show one
36+
// extra commit in the form of the index pseudo-node.
37+
if (paging.isIndexVisible) {
38+
return visibleCommits.length + 1
39+
}
40+
41+
// Else, just the number of visible commits, relative
42+
// to the current pagination configuration.
43+
return visibleCommits.length
44+
}, [paging.isIndexVisible, visibleCommits.length])
45+
2746
return (
2847
<div className={styles.container} style={{ width }} ref={ref}>
2948
<div
3049
className={styles.graph}
3150
style={{
3251
gridTemplateColumns: `repeat(${graphWidth}, 1fr)`,
33-
// +1 to length to include index. TODO: If add enableIndex prop, drive the +1 with it
34-
gridTemplateRows: `repeat(${visibleCommits.length + 1}, ${ROW_HEIGHT + rowSpacing}px)`
52+
gridTemplateRows: `repeat(${commitQuantity}, ${ROW_HEIGHT + rowSpacing}px)`
3553
}}
3654
>
3755
{visibleCommits.length === 0 && (

packages/library/src/modules/Graph/components/CurvedEdge/CurvedEdge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const CurvedEdge = ({ colour, path, dashed }: CurvedEdgeProps) => {
1111
strokeWidth="2"
1212
fill="transparent"
1313
vectorEffect='non-scaling-stroke'
14-
strokeDasharray={dashed ? '3 4': undefined}
14+
strokeDasharray={dashed ? '2 2': undefined}
1515
/>
1616
</svg>
1717
)

packages/library/src/modules/Graph/components/GraphColumn/GraphColumn.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ export const GraphColumn = ({
6565
// has no parents, then it must be the first commit
6666
// in the graph, so just draw a solid line above it.
6767
const isFirstCommit = state.isNode && commit.parents.length === 0
68-
// Or if we're a merge target node that closed a branch
69-
// const isMergeTarget = state.isNode && state.mergeSourceNodeColumnIndex // TODO: Are we gonna use this?
7068
if (isFirstCommit || state.isColumnBelowEmpty) {
7169
return {
7270
top: 0,
@@ -229,7 +227,7 @@ export const GraphColumn = ({
229227
<ColumnBackground
230228
index={index}
231229
commitNodeIndex={commitNodeIndex}
232-
colour={reduceOpacity(getGraphColumnColour(commitNodeIndex), 0.15)}
230+
colour={state.isPlaceholderSkeleton ? hoverColour : reduceOpacity(getGraphColumnColour(commitNodeIndex), 0.15)}
233231
/>
234232
)}
235233

0 commit comments

Comments
 (0)