Skip to content
This repository was archived by the owner on Jan 10, 2024. It is now read-only.

Commit 13c3d31

Browse files
feat: show/hide commits pane and file tree pane (#235)
1 parent 3665155 commit 13c3d31

17 files changed

+520
-399
lines changed

Diff for: components/ActivityFeed.tsx

+85-85
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { FileContext } from "@githubnext/blocks";
22
import {
33
GitCommitIcon,
44
SidebarCollapseIcon,
5-
SidebarExpandIcon,
65
XCircleIcon,
76
} from "@primer/octicons-react";
87
import { Avatar, Box, IconButton, Text, Timeline } from "@primer/react";
@@ -11,7 +10,8 @@ import { getRelativeTime } from "lib/date-utils";
1110
import { useSession } from "next-auth/react";
1211
import Link from "next/link";
1312
import { useRouter } from "next/router";
14-
import { useState } from "react";
13+
import { useHistoryPane } from "state";
14+
import { Tooltip } from "./Tooltip";
1515

1616
type ActivityFeedProps = {
1717
context: Omit<FileContext, "file">;
@@ -31,100 +31,100 @@ export const ActivityFeed = ({
3131
blockType,
3232
}: ActivityFeedProps) => {
3333
const session = useSession();
34-
35-
const [open, setOpen] = useState(true);
34+
const { toggle } = useHistoryPane();
3635

3736
return (
38-
<div
39-
className={`h-full transition-width overflow-hidden ${
40-
open ? "w-80" : "w-12"
41-
}`}
42-
>
43-
<div className={`h-full overflow-y-auto w-80 duration-200`}>
44-
<div className="flex flex-col h-full">
45-
<Box
46-
bg="canvas.subtle"
47-
borderBottom="1px solid"
48-
display="flex"
49-
alignItems="center"
50-
p={2}
51-
borderColor="border.muted"
52-
flex="none"
53-
>
37+
<div className={`h-full overflow-hidden`}>
38+
<div className="flex flex-col h-full">
39+
<Box
40+
bg="canvas.subtle"
41+
borderBottom="1px solid"
42+
display="flex"
43+
alignItems="center"
44+
p={2}
45+
borderColor="border.muted"
46+
flex="none"
47+
className="h-panelHeader flex-shrink-0"
48+
>
49+
<Tooltip placement="top" label="Close Commits Pane">
5450
<IconButton
55-
icon={open ? SidebarCollapseIcon : SidebarExpandIcon}
56-
onClick={() => setOpen(!open)}
51+
icon={SidebarCollapseIcon}
52+
onClick={toggle}
5753
sx={{ mr: 2 }}
58-
title={open ? "Hide history" : "Show history"}
54+
title={"Close Commits Pane"}
5955
/>
60-
<Box
61-
sx={{ fontWeight: "bold", display: "flex", alignItems: "center" }}
62-
>
63-
<div className="flex-none">
64-
Commits {blockType ? `for this ${blockType}` : ""}
65-
</div>
66-
</Box>
56+
</Tooltip>
57+
<Box
58+
sx={{
59+
fontWeight: "bold",
60+
display: "flex",
61+
alignItems: "center",
62+
}}
63+
>
64+
<div className="flex-none">
65+
Commits {blockType ? `for this ${blockType}` : ""}
66+
</div>
6767
</Box>
68+
</Box>
6869

69-
<Box className="relative">
70-
{!open && <div className="absolute inset-0 bg-white z-10"></div>}
71-
{timeline && (
72-
<LayoutGroup>
73-
<Timeline>
74-
<AnimatePresence initial={false}>
75-
{updatedContent && (
76-
<motion.div
77-
layoutId="ghost-commit"
78-
key="ghost-commit"
79-
className="z-10"
80-
>
81-
<Commit
82-
username={session.data.user?.name}
83-
message={"Working changes"}
84-
isSelected={context.sha === branchName}
85-
onClickRef={branchName}
86-
onRemove={clearUpdatedContent}
87-
/>
88-
</motion.div>
89-
)}
90-
</AnimatePresence>
91-
{timeline.map((item, index) => {
92-
// When `context.sha === branchName` (i.e. `fileRef` is empty or
93-
// set to `branchName`) we show the current version of the file.
94-
// If there is updated content for the file, the current version
95-
// is the ghost commit; otherwise it is the tip of the selected
96-
// branch.
97-
//
98-
// To make it easier to compare an older version of a file against
99-
// the current version, clicking the selected version takes you to
100-
// the current version (so you can swap between them with repeated
101-
// clicks).
70+
<Box className="relative flex-1 overflow-auto">
71+
{!open && <div className="absolute inset-0 bg-white z-10"></div>}
72+
{timeline && (
73+
<LayoutGroup>
74+
<Timeline>
75+
<AnimatePresence initial={false}>
76+
{updatedContent && (
77+
<motion.div
78+
layoutId="ghost-commit"
79+
key="ghost-commit"
80+
className="z-10"
81+
>
82+
<Commit
83+
username={session.data.user?.name}
84+
message={"Working changes"}
85+
isSelected={context.sha === branchName}
86+
onClickRef={branchName}
87+
onRemove={clearUpdatedContent}
88+
/>
89+
</motion.div>
90+
)}
91+
</AnimatePresence>
92+
{timeline.map((item, index) => {
93+
// When `context.sha === branchName` (i.e. `fileRef` is empty or
94+
// set to `branchName`) we show the current version of the file.
95+
// If there is updated content for the file, the current version
96+
// is the ghost commit; otherwise it is the tip of the selected
97+
// branch.
98+
//
99+
// To make it easier to compare an older version of a file against
100+
// the current version, clicking the selected version takes you to
101+
// the current version (so you can swap between them with repeated
102+
// clicks).
102103

103-
const isCurrent = index === 0 && !updatedContent;
104+
const isCurrent = index === 0 && !updatedContent;
104105

105-
const isSelected =
106-
item.sha === context.sha ||
107-
(isCurrent && context.sha === branchName);
106+
const isSelected =
107+
item.sha === context.sha ||
108+
(isCurrent && context.sha === branchName);
108109

109-
const onClickRef =
110-
isSelected || isCurrent ? branchName : item.sha;
110+
const onClickRef =
111+
isSelected || isCurrent ? branchName : item.sha;
111112

112-
return (
113-
<motion.div layout layoutId={item.sha} key={item.sha}>
114-
<Commit
115-
{...item}
116-
onClickRef={onClickRef}
117-
isSelected={isSelected}
118-
key={item.sha}
119-
/>
120-
</motion.div>
121-
);
122-
})}
123-
</Timeline>
124-
</LayoutGroup>
125-
)}
126-
</Box>
127-
</div>
113+
return (
114+
<motion.div layout layoutId={item.sha} key={item.sha}>
115+
<Commit
116+
{...item}
117+
onClickRef={onClickRef}
118+
isSelected={isSelected}
119+
key={item.sha}
120+
/>
121+
</motion.div>
122+
);
123+
})}
124+
</Timeline>
125+
</LayoutGroup>
126+
)}
127+
</Box>
128128
</div>
129129
</div>
130130
);

Diff for: components/Sidebar.tsx renamed to components/FileTree.tsx

+28-6
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ import {
66
FileDirectoryOpenFillIcon,
77
FileIcon,
88
SearchIcon,
9+
SidebarExpandIcon,
910
} from "@primer/octicons-react";
10-
import { Box, StyledOcticon, Text, TextInput } from "@primer/react";
11+
import { Box, IconButton, StyledOcticon, Text, TextInput } from "@primer/react";
1112
import Link from "next/link";
1213
import { useRouter } from "next/router";
1314
import { CSSProperties, useEffect, useMemo, useRef, useState } from "react";
1415
import { VscCircleOutline } from "react-icons/vsc";
1516
import type { FixedSizeNodeData, FixedSizeNodePublicState } from "react-vtree";
1617
import { FixedSizeTree as Tree } from "react-vtree";
18+
import { Tooltip } from "./Tooltip";
1719
import makeBranchPath from "utils/makeBranchPath";
20+
import { useFileTreePane } from "state";
1821

1922
type TreeData = {
2023
id: string;
@@ -47,7 +50,7 @@ interface NestedFileTree {
4750
type: string;
4851
}
4952

50-
type SidebarProps = {
53+
type FileTreeProps = {
5154
owner: string;
5255
repo: string;
5356
branchName: string;
@@ -56,20 +59,21 @@ type SidebarProps = {
5659
updatedContents: Record<string, unknown>;
5760
};
5861

59-
export const Sidebar = ({
62+
export const FileTree = ({
6063
owner = "",
6164
repo = "",
6265
branchName,
6366
files = [],
6467
activeFilePath = "",
6568
updatedContents,
66-
}: SidebarProps) => {
69+
}: FileTreeProps) => {
6770
const [searchTerm, setSearchTerm] = useState("");
6871
const wrapperElement = useRef<HTMLDivElement>(null);
6972
const tree = useRef<Tree>(null);
7073
const [dimensions, setDimensions] = useState<[number, number]>([100, 100]);
7174
const router = useRouter();
7275
const query = router.query;
76+
const { toggle: toggleFileTree } = useFileTreePane();
7377

7478
useEffect(() => {
7579
const onResize = () => {
@@ -186,16 +190,34 @@ export const Sidebar = ({
186190
if (!files.map) return null;
187191

188192
return (
189-
<Box className="sidebar flex flex-col h-full overflow-hidden flex-1 w-[17rem]">
190-
<Box className="p-2 pb-0">
193+
<Box className="sidebar flex flex-col h-full overflow-hidden flex-1">
194+
<Box
195+
bg="canvas.subtle"
196+
p={2}
197+
className="h-panelHeader"
198+
borderBottom="1px solid"
199+
borderColor="border.muted"
200+
display="flex"
201+
alignItems="center"
202+
justifyContent="space-between"
203+
>
191204
<TextInput
192205
value={searchTerm}
193206
onChange={(e) => setSearchTerm(e.target.value)}
194207
placeholder="Search files & folders"
195208
leadingVisual={SearchIcon}
196209
className="w-full"
197210
/>
211+
<Tooltip placement="top-end" label="Close File Tree">
212+
<IconButton
213+
icon={SidebarExpandIcon}
214+
onClick={toggleFileTree}
215+
sx={{ ml: 2 }}
216+
title={"Close sidebar"}
217+
/>
218+
</Tooltip>
198219
</Box>
220+
199221
<Box className="flex-1 overflow-auto">
200222
<div className="h-full w-full file-tree-wrapper" ref={wrapperElement}>
201223
{filteredFiles.length > 0 ? (

Diff for: components/Tooltip.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import {
22
arrow,
33
autoUpdate,
44
flip,
5+
FloatingDelayGroup,
56
offset,
67
Placement,
78
shift,
9+
useDelayGroup,
10+
useDelayGroupContext,
811
useDismiss,
912
useFloating,
1013
useFocus,
@@ -26,6 +29,7 @@ export const Tooltip = ({
2629
label,
2730
placement: initialPlacement,
2831
}: Props) => {
32+
const { delay, setCurrentId } = useDelayGroupContext();
2933
const [open, setOpen] = useState(false);
3034
const arrowRef = useRef<HTMLDivElement>(null);
3135

@@ -41,19 +45,27 @@ export const Tooltip = ({
4145
} = useFloating({
4246
placement: initialPlacement,
4347
open,
44-
onOpenChange: setOpen,
48+
onOpenChange(open) {
49+
setOpen(open);
50+
51+
if (open) {
52+
setCurrentId(label);
53+
}
54+
},
4555
strategy: "fixed",
4656
middleware: [offset(8), shift(), flip(), arrow({ element: arrowRef })],
4757
whileElementsMounted: autoUpdate,
4858
});
4959

5060
const { getReferenceProps, getFloatingProps } = useInteractions([
51-
useHover(context),
61+
useHover(context, { delay }),
5262
useFocus(context),
5363
useRole(context, { role: "tooltip" }),
5464
useDismiss(context),
5565
]);
5666

67+
useDelayGroup(context, { id: label });
68+
5769
// Preserve the consumer's ref
5870
const ref = useMemo(
5971
() => mergeRefs([reference, (children as any).ref]),

Diff for: components/repo-detail/BlockPane.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ type BlockPaneProps = {
1515
path: string;
1616
metadata: any;
1717
setRequestedBlockMetadata: (metadata: any) => void;
18-
isFullscreen: boolean;
1918
context: Context;
2019
branchName: string;
2120
onSaveChanges: () => void;
@@ -26,7 +25,6 @@ export default function BlockPane({
2625
path,
2726
metadata,
2827
setRequestedBlockMetadata,
29-
isFullscreen,
3028
context,
3129
onSaveChanges,
3230
}: BlockPaneProps) {
@@ -86,7 +84,6 @@ export default function BlockPane({
8684
<BlockPaneHeader
8785
{...{
8886
manageBlockResult,
89-
isFullscreen,
9087
path,
9188
isFolder,
9289
metadata,

0 commit comments

Comments
 (0)