Skip to content

Commit 7fd733e

Browse files
authored
Merge pull request #78 from NeuroJSON/dev-fan
feat: add About page, fix fNIRS display, reset scroll on navigation, and add walkthrough video
2 parents 14f653f + af01303 commit 7fd733e

File tree

13 files changed

+558
-304
lines changed

13 files changed

+558
-304
lines changed

public/img/section3/atlas.png

65.2 KB
Loading

public/img/section3/fnirs.png

128 KB
Loading

public/img/section3/mesh.png

122 KB
Loading

public/img/section3/mri.png

93.5 KB
Loading

src/components/HomePageComponents/Section3.tsx

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,82 @@ import { Colors } from "design/theme";
66
import React from "react";
77
import { useState } from "react";
88

9+
type Tile = {
10+
src: string;
11+
alt: string;
12+
video: string;
13+
};
14+
15+
const tiles: Tile[] = [
16+
{
17+
src: `${process.env.PUBLIC_URL}/img/section3/mesh.png`,
18+
// src: "/img/section3/mesh.png",
19+
alt: "Brain mesh",
20+
video: "https://neurojson.io/io/download/static/videos/preview_mesh.mp4",
21+
},
22+
{
23+
src: `${process.env.PUBLIC_URL}/img/section3/fnirs.png`,
24+
// src: "/img/section3/fnirs.png",
25+
alt: "fNIRS signals",
26+
video: "https://neurojson.io/io/download/static/videos/preview_fnirs.mp4",
27+
},
28+
{
29+
src: `${process.env.PUBLIC_URL}/img/section3/atlas.png`,
30+
// src: "/img/section3/atlas.png",
31+
alt: "atlas",
32+
video: "https://neurojson.io/io/download/static/videos/preview_atlas.mp4",
33+
},
34+
{
35+
src: `${process.env.PUBLIC_URL}/img/section3/mri.png`,
36+
// src: "/img/section3/mri.png",
37+
alt: "mri",
38+
video: "https://neurojson.io/io/download/static/videos/preview_mri.mp4",
39+
},
40+
];
41+
42+
// Vertical rectangle image tile (clickable)
43+
const PreviewTile: React.FC<{ tile: Tile; onClick: () => void }> = ({
44+
tile,
45+
onClick,
46+
}) => (
47+
<Box
48+
onClick={onClick}
49+
role="button"
50+
aria-label={tile.alt}
51+
sx={{
52+
position: "relative",
53+
width: "100%",
54+
aspectRatio: "2.5 / 3",
55+
borderRadius: 3,
56+
overflow: "hidden",
57+
cursor: "pointer",
58+
boxShadow: 4,
59+
backgroundImage: `url(${tile.src})`,
60+
backgroundSize: "cover",
61+
backgroundPosition: "center",
62+
transition: "transform .2s ease",
63+
"&:hover": { transform: "translateY(-2px)" },
64+
}}
65+
/>
66+
);
67+
968
interface Section3Props {
1069
scrollToNext: () => void;
1170
}
1271

1372
const Section3: React.FC<Section3Props> = ({ scrollToNext }) => {
1473
const [open, setOpen] = useState(false);
74+
const [videoSrc, setVideoSrc] = useState("");
75+
76+
const handleOpen = (video: string) => {
77+
setVideoSrc(video);
78+
setOpen(true);
79+
};
1580

16-
const handleOpen = () => setOpen(true);
17-
const handleClose = () => setOpen(false);
81+
const handleClose = () => {
82+
setOpen(false);
83+
setVideoSrc("");
84+
};
1885

1986
return (
2087
<Box
@@ -84,18 +151,25 @@ const Section3: React.FC<Section3Props> = ({ scrollToNext }) => {
84151
alignItems: "center",
85152
mt: { xs: 4, md: 2 },
86153
mb: { xs: 8, md: 0 },
87-
cursor: "pointer",
88154
}}
89-
onClick={handleOpen}
90155
>
91-
<img
92-
src={`${process.env.PUBLIC_URL}/img/section3_cards.png`}
93-
alt="rendering feature info cards"
94-
style={{
95-
width: "70%",
96-
height: "auto",
97-
}}
98-
></img>
156+
<Box sx={{ width: "70%" }}>
157+
<Box
158+
sx={{
159+
display: "grid",
160+
gridTemplateColumns: { xs: "1fr 1fr", sm: "1fr 1fr" },
161+
gap: 2,
162+
}}
163+
>
164+
{tiles.map((t, i) => (
165+
<PreviewTile
166+
key={i}
167+
tile={t}
168+
onClick={() => handleOpen(t.video)}
169+
/>
170+
))}
171+
</Box>
172+
</Box>
99173
</Box>
100174

101175
{/* video dialog */}
@@ -113,12 +187,12 @@ const Section3: React.FC<Section3Props> = ({ scrollToNext }) => {
113187
>
114188
<CloseIcon />
115189
</IconButton>
116-
117-
<video controls style={{ width: "100%", borderRadius: "4px" }}>
118-
<source
119-
src="https://neurojson.io/video/preview_video.mp4"
120-
type="video/mp4"
121-
/>
190+
<video
191+
key={videoSrc}
192+
controls
193+
style={{ width: "100%", borderRadius: 4 }}
194+
>
195+
{videoSrc && <source src={videoSrc} type="video/mp4" />}
122196
Your browser does not support the video tag.
123197
</video>
124198
</Box>

src/components/NavBar/NavItems.tsx

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Toolbar, Grid, Button, Typography, Box } from "@mui/material";
1+
import { Toolbar, Grid, Button, Typography, Box, Tooltip } from "@mui/material";
22
import { Colors } from "design/theme";
33
import React from "react";
44
import { useNavigate, Link } from "react-router-dom";
@@ -82,20 +82,71 @@ const NavItems: React.FC = () => {
8282
<Grid item xs={12} md="auto">
8383
<Grid
8484
container
85-
spacing={3}
85+
spacing={{ xs: 2, md: 5 }}
86+
direction={{ xs: "row", sm: "row" }} // row on mobile
8687
justifyContent="center"
87-
sx={{ mb: { xs: 1 } }}
88+
alignItems="center"
89+
sx={{
90+
mb: { xs: 1 },
91+
rowGap: { xs: 1, sm: 2 },
92+
}}
8893
>
8994
{[
90-
// { text: "ABOUT", url: "https://neurojson.org/Doc/Start" },
9195
{ text: "About", url: RoutesEnum.ABOUT },
9296
{ text: "Wiki", url: "https://neurojson.org/Wiki" },
9397
{ text: "Search", url: RoutesEnum.SEARCH },
9498
{ text: "Databases", url: RoutesEnum.DATABASES },
95-
{ text: "V1", url: "https://neurojson.io/v1" },
96-
].map(({ text, url }) => (
99+
{
100+
text: "V1",
101+
url: "https://neurojson.io/v1",
102+
tooltip: "Visit the previous version of website",
103+
},
104+
].map(({ text, url, tooltip }) => (
97105
<Grid item key={text}>
98-
{url?.startsWith("https") ? (
106+
{tooltip ? (
107+
<Tooltip
108+
title={tooltip}
109+
arrow
110+
componentsProps={{
111+
tooltip: {
112+
sx: {
113+
bgcolor: Colors.lightGray,
114+
color: Colors.darkPurple,
115+
},
116+
},
117+
arrow: {
118+
sx: {
119+
color: Colors.lightGray,
120+
},
121+
},
122+
}}
123+
>
124+
<a
125+
href={url}
126+
target="_blank"
127+
rel="noopener noreferrer"
128+
style={{ textDecoration: "none" }}
129+
>
130+
<Typography
131+
align="center"
132+
fontWeight={600}
133+
lineHeight={"1.5rem"}
134+
letterSpacing={"0.05rem"}
135+
sx={{
136+
color: Colors.white,
137+
transition: "color 0.3s ease, transform 0.3s ease",
138+
textTransform: "uppercase",
139+
"&:hover": {
140+
transform: "scale(1.2)",
141+
cursor: "pointer",
142+
},
143+
}}
144+
>
145+
{text}
146+
</Typography>
147+
</a>
148+
</Tooltip>
149+
) : url?.startsWith("https") ? (
99150
<a
100151
href={url}
101152
target="_blank"
@@ -108,6 +159,10 @@ const NavItems: React.FC = () => {
108159
lineHeight={"1.5rem"}
109160
letterSpacing={"0.05rem"}
110161
sx={{
162+
fontSize: {
163+
xs: "0.8rem", // font size on mobile
164+
sm: "1rem",
165+
},
111166
color: Colors.white,
112167
transition: "color 0.3s ease, transform 0.3s ease",
113168
textTransform: "uppercase",
@@ -128,6 +183,10 @@ const NavItems: React.FC = () => {
128183
lineHeight={"1.5rem"}
129184
letterSpacing={"0.05rem"}
130185
sx={{
186+
fontSize: {
187+
xs: "0.8rem", // font size on mobile
188+
sm: "1rem",
189+
},
131190
color: Colors.white,
132191
transition: "color 0.3s ease, transform 0.3s ease",
133192
textTransform: "uppercase",

src/components/Routes.tsx

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ScrollToTop from "./ScrollToTop";
12
import FullScreen from "design/Layouts/FullScreen";
23
import AboutPage from "pages/AboutPage";
34
import DatabasePage from "pages/DatabasePage";
@@ -11,34 +12,37 @@ import { Navigate, Route, Routes as RouterRoutes } from "react-router-dom";
1112
import RoutesEnum from "types/routes.enum";
1213

1314
const Routes = () => (
14-
<RouterRoutes>
15-
{/* FullScreen Layout */}
16-
<Route element={<FullScreen />}>
17-
{/* Home Page */}
18-
<Route path={RoutesEnum.HOME} element={<Home />} />
19-
{/* Databases Page */}
20-
<Route path={RoutesEnum.DATABASES} element={<DatabasePage />} />
15+
<>
16+
<ScrollToTop />
17+
<RouterRoutes>
18+
{/* FullScreen Layout */}
19+
<Route element={<FullScreen />}>
20+
{/* Home Page */}
21+
<Route path={RoutesEnum.HOME} element={<Home />} />
22+
{/* Databases Page */}
23+
<Route path={RoutesEnum.DATABASES} element={<DatabasePage />} />
2124

22-
{/* Dataset List Page */}
23-
<Route
24-
path={`${RoutesEnum.DATABASES}/:dbName`}
25-
// element={<DatasetPage />}
26-
element={<NewDatasetPage />}
27-
/>
25+
{/* Dataset List Page */}
26+
<Route
27+
path={`${RoutesEnum.DATABASES}/:dbName`}
28+
// element={<DatasetPage />}
29+
element={<NewDatasetPage />}
30+
/>
2831

29-
{/* Dataset Details Page */}
30-
<Route
31-
path={`${RoutesEnum.DATABASES}/:dbName/:docId`}
32-
element={<DatasetDetailPage />}
33-
/>
32+
{/* Dataset Details Page */}
33+
<Route
34+
path={`${RoutesEnum.DATABASES}/:dbName/:docId`}
35+
element={<DatasetDetailPage />}
36+
/>
3437

35-
{/* Search Page */}
36-
<Route path={RoutesEnum.SEARCH} element={<SearchPage />} />
38+
{/* Search Page */}
39+
<Route path={RoutesEnum.SEARCH} element={<SearchPage />} />
3740

38-
{/* About Page */}
39-
<Route path={RoutesEnum.ABOUT} element={<AboutPage />} />
40-
</Route>
41-
</RouterRoutes>
41+
{/* About Page */}
42+
<Route path={RoutesEnum.ABOUT} element={<AboutPage />} />
43+
</Route>
44+
</RouterRoutes>
45+
</>
4246
);
4347

4448
export default Routes;

src/components/ScrollToTop.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useEffect } from "react";
2+
import { useLocation } from "react-router-dom";
3+
4+
const ScrollToTop = () => {
5+
const { pathname } = useLocation();
6+
7+
useEffect(() => {
8+
window.scrollTo({ top: 0, left: 0, behavior: "instant" as ScrollBehavior });
9+
}, [pathname]);
10+
11+
return null;
12+
};
13+
14+
export default ScrollToTop;

0 commit comments

Comments
 (0)