Skip to content

Commit 00cf81c

Browse files
author
Alex Bates
authored
Fit scratch toolbar onto one row when possible (#548)
* refactor scratch actions to its own component * move toolbar actions into nav area * fit ScratchToolbar on one line where possible * fix HydrationError * reduce wasted space by calculating layout in js * avoid layout shift when edit time changes * move edit time next to scratch name * stop showing "Active now" after time * align edit time on baseline * drop 'Edited' prefix
1 parent b17d647 commit 00cf81c

File tree

14 files changed

+332
-223
lines changed

14 files changed

+332
-223
lines changed

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@svgr/webpack": "^6.2.1",
5151
"@types/diff": "^5.0.2",
5252
"@types/react-modal": "^3.13.1",
53+
"@types/react-timeago": "^4.1.3",
5354
"@types/react-virtualized-auto-sizer": "^1.0.1",
5455
"@types/react-window": "^1.8.5",
5556
"@typescript-eslint/eslint-plugin": "^5.0.0",

frontend/src/components/Breadcrumbs.module.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
list-style: none;
99

1010
display: flex;
11-
flex-wrap: wrap;
11+
flex-wrap: nowrap;
1212
align-items: stretch;
1313

1414
// Page links
@@ -38,7 +38,7 @@
3838
content: "";
3939

4040
display: inline-block;
41-
margin: 0 0.7em;
41+
margin: 0 0.7em 0 0.4em;
4242

4343
width: 0.5em;
4444
height: 0.5em;

frontend/src/components/Button.module.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
font-size: 0.8rem;
66
font-weight: 500;
77

8+
white-space: nowrap;
9+
810
user-select: none;
911
appearance: none;
1012

frontend/src/components/Nav/Nav.module.scss

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ $padding: 8px;
66
user-select: none;
77
background: var(--g300);
88

9+
z-index: 2;
10+
911
ul {
1012
list-style: none;
1113
}
1214
}
1315

1416
.header {
15-
height: $innerSize;
17+
min-height: $innerSize;
1618
padding: $padding;
1719
box-sizing: content-box;
1820

@@ -21,10 +23,8 @@ $padding: 8px;
2123
grid-template-areas: "menutoggle sitelogo loginstate";
2224
justify-content: space-between;
2325

24-
border-bottom: 1px solid var(--g500);
25-
2626
& > li {
27-
height: $innerSize;
27+
min-height: $innerSize;
2828
}
2929
}
3030

@@ -34,9 +34,10 @@ $padding: 8px;
3434
& > button {
3535
width: $innerSize;
3636
height: $innerSize;
37+
3738
border: none;
3839
background: transparent;
39-
border-radius: 4px;
40+
4041
cursor: pointer;
4142
}
4243
}
@@ -45,8 +46,10 @@ $padding: 8px;
4546
grid-area: loginstate;
4647

4748
display: flex;
49+
align-items: center;
4850
justify-content: flex-end;
4951

52+
height: $innerSize;
5053
padding-left: 12px;
5154
}
5255

@@ -122,17 +125,34 @@ $padding: 8px;
122125
display: none;
123126
visibility: hidden;
124127
}
128+
}
129+
130+
@mixin borderBottomNoLayoutShift {
131+
padding-bottom: $padding - 1px;
132+
border-bottom: 1px solid var(--g600);
133+
}
134+
135+
.border .header {
136+
@include borderBottomNoLayoutShift;
137+
}
138+
139+
// Sidebar
140+
@media (min-width: 500px) {
141+
.container[data-open="true"] .header {
142+
@include borderBottomNoLayoutShift;
143+
}
125144

126-
// sidebar (tablets, desktop + data-force-toggle="true")
127-
@media (min-width: 500px) {
145+
.menu {
128146
width: 300px;
129-
border-right: 1px solid var(--g500);
147+
border-right: 1px solid var(--g600);
148+
149+
// Cover up header's border-bottom
150+
box-shadow: -2px 0 0 2px var(--g300);
130151
}
131152
}
132153

133154
.searchContainer {
134155
padding: $padding;
135-
border-bottom: 1px solid var(--g500);
136156
}
137157

138158
.search {
@@ -146,7 +166,7 @@ $padding: 8px;
146166
padding: 1.5 * $padding;
147167

148168
&:not(:last-child) {
149-
border-bottom: 1px solid var(--g500);
169+
border-bottom: 1px solid var(--g400);
150170
}
151171

152172
a {
@@ -222,6 +242,8 @@ $padding: 8px;
222242
display: flex;
223243
align-items: center;
224244
width: 100%;
245+
246+
overflow: hidden;
225247
}
226248
}
227249

frontend/src/components/Nav/Nav.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ import Link from "next/link"
44
import { useRouter } from "next/router"
55

66
import { ThreeBarsIcon, XIcon } from "@primer/octicons-react"
7+
import classNames from "classnames"
78

89
import Frog from "./frog.svg"
910
import LoginState from "./LoginState"
1011
import styles from "./Nav.module.scss"
1112
import Search from "./Search"
1213

1314
export interface Props {
15+
border?: boolean
1416
children?: React.ReactNode
1517
}
1618

17-
export default function Nav({ children }: Props) {
19+
export default function Nav({ border, children }: Props) {
1820
const [isOpen, toggleOpen] = useReducer(isOpen => !isOpen, false)
1921
const toggleLabel = `${isOpen ? "Close" : "Open"} Global Navigation Menu`
2022
const router = useRouter()
@@ -51,7 +53,10 @@ export default function Nav({ children }: Props) {
5153
}, [isOpen])
5254

5355
return <nav
54-
className={styles.container}
56+
className={classNames({
57+
[styles.container]: true,
58+
[styles.border]: border,
59+
})}
5560
aria-labelledby="navtoggle"
5661
data-open={isOpen}
5762
data-force-toggle={!!children}

frontend/src/components/Scratch/AboutScratch.module.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,6 @@
116116
margin-right: 6px;
117117
}
118118

119-
.signInPrompt {
120-
margin-left: 16px;
121-
}
122-
123119
.projectFunctionLinks {
124120
a:last-child {
125121
color: var(--g800);

frontend/src/components/Scratch/AboutScratch.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import TimeAgo from "react-timeago"
44
import useSWR from "swr"
55

66
import * as api from "../../lib/api"
7-
import GitHubLoginButton from "../GitHubLoginButton"
87
import LoadingSpinner from "../loading.svg"
98
import PlatformIcon from "../PlatformSelect/PlatformIcon"
109
import PlatformName from "../PlatformSelect/PlatformName"
1110
import { getScoreText } from "../ScoreBadge"
1211
import UserLink from "../user/UserLink"
1312

1413
import styles from "./AboutScratch.module.scss"
15-
import ClaimScratchButton from "./buttons/ClaimScratchButton"
1614

1715
function ScratchLink({ url }: { url: string }) {
1816
const { data: scratch, error } = useSWR<api.Scratch>(url, api.get)
@@ -60,7 +58,6 @@ export type Props = {
6058
}
6159

6260
export default function AboutScratch({ scratch, setScratch }: Props) {
63-
const userIsYou = api.useUserIsYou()
6461
const { data: project } = useSWR<api.Project>(scratch.project, api.get)
6562
const { data: projectFunction } = useSWR<api.ProjectFunction>(scratch.project_function, api.get)
6663

@@ -72,13 +69,7 @@ export default function AboutScratch({ scratch, setScratch }: Props) {
7269
</div>
7370
{<div className={styles.horizontalField}>
7471
<p className={styles.label}>Owner</p>
75-
{scratch.owner
76-
? <UserLink user={scratch.owner} />
77-
: <ClaimScratchButton scratch={scratch} />
78-
}
79-
{scratch.owner?.is_anonymous && userIsYou(scratch.owner)
80-
&& <GitHubLoginButton popup label="Sign in to keep" className={styles.signInPrompt} />
81-
}
72+
{scratch.owner && <UserLink user={scratch.owner} />}
8273
</div>}
8374
{scratch.parent &&<div className={styles.horizontalField}>
8475
<p className={styles.label}>Fork of</p>

frontend/src/components/Scratch/Scratch.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ export default function Scratch({
291291
setScratch={setScratch}
292292
setDecompilationTabEnabled={setDecompilationTabEnabled}
293293
/>
294-
<hr />
295294
{layout && <CustomLayout
296295
layout={layout}
297296
onChange={setLayout}

0 commit comments

Comments
 (0)