Skip to content

Commit f8cb8a9

Browse files
committed
Started building the frontend (WIP)
1 parent 6a770f5 commit f8cb8a9

File tree

12 files changed

+1556
-289
lines changed

12 files changed

+1556
-289
lines changed

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
</head>
66
<body>
77
<div id="root"></div>
8-
<script type="module" src="/src/main.tsx"></script>
8+
<script type="module" src="/src/index.tsx"></script>
99
</body>
1010
</html>

package-lock.json

+1,228-181
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+11
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,27 @@
1313
"tauri": "tauri"
1414
},
1515
"dependencies": {
16+
"@emotion/react": "^11.10.0",
17+
"@mantine/core": "^5.0.3",
18+
"@mantine/hooks": "^5.0.3",
19+
"@mantine/modals": "^5.0.3",
20+
"@tabler/icons": "^1.78.1",
1621
"@tauri-apps/api": "^1.0.2",
1722
"react": "^18.2.0",
23+
"react-async-hook": "^4.0.0",
1824
"react-dom": "^18.2.0",
25+
"react-router-dom": "^6.3.0",
26+
"react-virtualized-auto-sizer": "github:Narcha/react-virtualized-auto-sizer",
27+
"react-window": "^1.8.7",
1928
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#dev",
2029
"tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#dev"
2130
},
2231
"devDependencies": {
2332
"@tauri-apps/cli": "^1.0.5",
2433
"@types/react": "^18.0.15",
2534
"@types/react-dom": "^18.0.6",
35+
"@types/react-virtualized-auto-sizer": "^1.0.1",
36+
"@types/react-window": "^1.8.5",
2637
"@typescript-eslint/eslint-plugin": "^5.30.7",
2738
"@typescript-eslint/parser": "^5.30.7",
2839
"@vitejs/plugin-react": "^2.0.0",

src-tauri/tauri.conf.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
"height": 600,
6060
"resizable": true,
6161
"title": "DemoMan",
62-
"width": 800
62+
"width": 800,
63+
"decorations": false
6364
}
6465
]
6566
}

src/App.tsx

+164-29
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,169 @@
1-
import { useState } from "react";
2-
import reactLogo from "./assets/react.svg";
3-
import "./App.css";
1+
import { appWindow } from "@tauri-apps/api/window";
2+
import { Routes, Route, useNavigate } from "react-router-dom";
43

5-
function App() {
6-
const [count, setCount] = useState(0);
4+
import {
5+
AppShell,
6+
Navbar,
7+
Header,
8+
Stack,
9+
Tooltip,
10+
UnstyledButton,
11+
createStyles,
12+
Menu,
13+
ActionIcon,
14+
} from "@mantine/core";
15+
import {
16+
IconSettings,
17+
IconDots,
18+
TablerIcon,
19+
IconFolder,
20+
IconArrowLeft,
21+
IconArrowRight,
22+
IconMaximize,
23+
IconMinimize,
24+
IconX,
25+
IconLetterI,
26+
} from "@tabler/icons";
727

28+
import HomeView from "./views/home";
29+
import React, { useState } from "react";
30+
import SettingsView from "./views/settings";
31+
import DemoDetailsView from "./views/demoDetails";
32+
33+
const useStyles = createStyles((theme) => ({
34+
link: {
35+
width: 50,
36+
height: 50,
37+
borderRadius: theme.radius.md,
38+
display: "flex",
39+
alignItems: "center",
40+
justifyContent: "center",
41+
color:
42+
theme.colorScheme === "dark"
43+
? theme.colors.dark[0]
44+
: theme.colors.gray[7],
45+
46+
"&:hover": {
47+
backgroundColor:
48+
theme.colorScheme === "dark"
49+
? theme.colors.dark[5]
50+
: theme.colors.gray[0],
51+
},
52+
},
53+
54+
active: {
55+
"&, &:hover": {
56+
backgroundColor: theme.fn.variant({
57+
variant: "light",
58+
color: theme.primaryColor,
59+
}).background,
60+
color: theme.fn.variant({ variant: "light", color: theme.primaryColor })
61+
.color,
62+
},
63+
},
64+
}));
65+
66+
type NavbarButtonProps = {
67+
icon: TablerIcon;
68+
active?: boolean;
69+
onClick?(): void;
70+
};
71+
72+
const NavbarButton = React.forwardRef<HTMLButtonElement, NavbarButtonProps>(
73+
function _NavbarButton(
74+
{ icon: Icon, active, onClick }: NavbarButtonProps,
75+
ref
76+
) {
77+
const { classes, cx } = useStyles();
78+
return (
79+
<UnstyledButton
80+
onClick={onClick}
81+
className={cx(classes.link, { [classes.active]: active })}
82+
ref={ref}
83+
>
84+
<Icon stroke={1.5} />
85+
</UnstyledButton>
86+
);
87+
}
88+
);
89+
90+
type HeaderIconProps = {
91+
icon: JSX.Element;
92+
onClick(): void;
93+
};
94+
95+
const HeaderIcon = ({ icon, onClick }: HeaderIconProps) => {
896
return (
9-
<div className="App">
10-
<div>
11-
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
12-
<img src="/vite.svg" className="logo" alt="Vite logo" />
13-
</a>
14-
<a href="https://reactjs.org" target="_blank" rel="noreferrer">
15-
<img src={reactLogo} className="logo react" alt="React logo" />
16-
</a>
17-
</div>
18-
<h1>Vite + React</h1>
19-
<div className="card">
20-
<button onClick={() => setCount((count) => count + 1)}>
21-
count is {count}
22-
</button>
23-
<p>
24-
Edit <code>src/App.tsx</code> and save to test HMR
25-
</p>
26-
</div>
27-
<p className="read-the-docs">
28-
Click on the Vite and React logos to learn more
29-
</p>
30-
</div>
97+
<ActionIcon variant="subtle" radius={0} size={40} onClick={onClick} tabIndex={-1}>
98+
{icon}
99+
</ActionIcon>
31100
);
32-
}
101+
};
102+
103+
export default function App() {
104+
const navigate = useNavigate();
105+
const [isMaximized, setIsMaximized] = useState(false);
106+
107+
appWindow.onResized(() => appWindow.isMaximized().then(setIsMaximized));
33108

34-
export default App;
109+
return (
110+
<AppShell
111+
padding={0}
112+
navbar={
113+
<Navbar width={{ base: 80 }} p="md">
114+
<Navbar.Section grow>
115+
{/* TODO */}
116+
</Navbar.Section>
117+
<Navbar.Section>
118+
<Stack justify="center" spacing={0}>
119+
<Menu shadow="md" width={200} position="right-end">
120+
<Menu.Target>
121+
<NavbarButton icon={IconDots} />
122+
</Menu.Target>
123+
<Menu.Dropdown>
124+
<Menu.Item icon={<IconFolder size={14} />}>
125+
Open demos folder
126+
</Menu.Item>
127+
<Menu.Item
128+
icon={<IconSettings size={14} />}
129+
onClick={() => navigate("/settings")}
130+
>
131+
Settings
132+
</Menu.Item>
133+
</Menu.Dropdown>
134+
</Menu>
135+
</Stack>
136+
</Navbar.Section>
137+
</Navbar>
138+
}
139+
header={
140+
<Header height={40} style={{ display: "flex" }}>
141+
<HeaderIcon icon={<IconArrowLeft />} onClick={() => navigate(-1)} />
142+
<HeaderIcon icon={<IconArrowRight />} onClick={() => navigate(1)} />
143+
<div style={{ flexGrow: 1 }} data-tauri-drag-region />
144+
<HeaderIcon
145+
// Pull a sneaky on them (The icon set has no plain "line" icon)
146+
icon={<IconLetterI style={{ transform: "rotate(90deg)" }} />}
147+
onClick={() => appWindow.minimize()}
148+
/>
149+
<HeaderIcon icon={isMaximized ? <IconMinimize /> : <IconMaximize />} onClick={() => appWindow.toggleMaximize()} />
150+
<HeaderIcon icon={<IconX />} onClick={() => appWindow.close()} />
151+
</Header>
152+
}
153+
styles={(theme) => ({
154+
main: {
155+
backgroundColor:
156+
theme.colorScheme === "dark"
157+
? theme.colors.dark[8]
158+
: theme.colors.gray[0],
159+
},
160+
})}
161+
>
162+
<Routes>
163+
<Route path="/" element={<HomeView />} />
164+
<Route path="/demo/:demoName" element={<DemoDetailsView />} />
165+
<Route path="/settings" element={<SettingsView />} />
166+
</Routes>
167+
</AppShell>
168+
);
169+
}

src/index.css

+2-67
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,5 @@
1-
:root {
2-
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3-
font-size: 16px;
4-
line-height: 24px;
5-
font-weight: 400;
6-
7-
color-scheme: light dark;
8-
color: rgba(255, 255, 255, 0.87);
9-
background-color: #242424;
10-
11-
font-synthesis: none;
12-
text-rendering: optimizeLegibility;
13-
-webkit-font-smoothing: antialiased;
14-
-moz-osx-font-smoothing: grayscale;
15-
-webkit-text-size-adjust: 100%;
16-
}
17-
18-
a {
19-
font-weight: 500;
20-
color: #646cff;
21-
text-decoration: inherit;
22-
}
23-
a:hover {
24-
color: #535bf2;
25-
}
26-
271
body {
282
margin: 0;
29-
display: flex;
30-
place-items: center;
31-
min-width: 320px;
32-
min-height: 100vh;
33-
}
34-
35-
h1 {
36-
font-size: 3.2em;
37-
line-height: 1.1;
38-
}
39-
40-
button {
41-
border-radius: 8px;
42-
border: 1px solid transparent;
43-
padding: 0.6em 1.2em;
44-
font-size: 1em;
45-
font-weight: 500;
46-
font-family: inherit;
47-
background-color: #1a1a1a;
48-
cursor: pointer;
49-
transition: border-color 0.25s;
50-
}
51-
button:hover {
52-
border-color: #646cff;
53-
}
54-
button:focus,
55-
button:focus-visible {
56-
outline: 4px auto -webkit-focus-ring-color;
57-
}
58-
59-
@media (prefers-color-scheme: light) {
60-
:root {
61-
color: #213547;
62-
background-color: #ffffff;
63-
}
64-
a:hover {
65-
color: #747bff;
66-
}
67-
button {
68-
background-color: #f9f9f9;
69-
}
3+
user-select: none;
4+
-webkit-user-select: none;
705
}

src/index.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import { createRoot } from "react-dom/client";
3+
import { BrowserRouter } from "react-router-dom";
4+
5+
import { MantineProvider } from "@mantine/core";
6+
7+
import "./index.css";
8+
import App from "./App";
9+
10+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
11+
createRoot(document.getElementById("root")!).render(
12+
<React.StrictMode>
13+
<MantineProvider theme={{ colorScheme: "dark" }}>
14+
<BrowserRouter>
15+
<App />
16+
</BrowserRouter>
17+
</MantineProvider>
18+
</React.StrictMode>
19+
);

src/main.tsx

-10
This file was deleted.

src/views/demoDetails/index.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useAsync } from "react-async-hook";
2+
import { Link, useParams } from "react-router-dom";
3+
import { getDemoByName } from "../../api";
4+
5+
export default function DemoDetailsView() {
6+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
7+
const demoName = decodeURIComponent(useParams().demoName!);
8+
const asyncDemo = useAsync(getDemoByName, [demoName]);
9+
10+
if (asyncDemo.loading) {
11+
return <h1>Loading...</h1>;
12+
}
13+
if (asyncDemo.error !== undefined) {
14+
return <h1>Error!</h1>;
15+
}
16+
17+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18+
const demo = asyncDemo.result!;
19+
20+
return (
21+
<div>
22+
<h1>{demo.name}</h1>
23+
<Link to="/">Back</Link>
24+
</div>
25+
);
26+
}

0 commit comments

Comments
 (0)