diff --git a/apps/main/src/electron/electron.service.ts b/apps/main/src/electron/electron.service.ts index e6a2a6c..68964a4 100644 --- a/apps/main/src/electron/electron.service.ts +++ b/apps/main/src/electron/electron.service.ts @@ -62,6 +62,11 @@ export class ElectronService implements OnApplicationBootstrap { width: 1300, height: 800, minWidth: 500, + titleBarStyle: 'hidden', + trafficLightPosition: { + x: 15, + y: 13, + }, webPreferences: { preload: process.env.NODE_ENV === 'production' diff --git a/apps/renderer/package.json b/apps/renderer/package.json index 2549127..814d374 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -14,6 +14,7 @@ "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^6.1.6", "@mui/material": "^5.14.5", "apollo-link-logger": "^2.0.1", "graphql": "^16.9.0", diff --git a/apps/renderer/src/components/App.tsx b/apps/renderer/src/components/App.tsx index 8e99169..a5a2cc3 100644 --- a/apps/renderer/src/components/App.tsx +++ b/apps/renderer/src/components/App.tsx @@ -5,19 +5,15 @@ import { ThemeProvider } from '@mui/material' import { ApolloProvider } from '@apollo/client' import apolloClient from '@graphql/client' -import { theme } from '@styles/theme' - -import { Layout } from '@components/Layout' +import { darkTheme } from '@styles/theme' import { Routes } from '@pages' export function App() { return ( - - - - + + ) diff --git a/apps/renderer/src/components/Layout.styles.tsx b/apps/renderer/src/components/Layout.styles.tsx index da2e041..22327bb 100644 --- a/apps/renderer/src/components/Layout.styles.tsx +++ b/apps/renderer/src/components/Layout.styles.tsx @@ -1,5 +1,6 @@ import styled from '@emotion/styled' import { css } from '@emotion/react' +import { NAVIGATOR_WIDTH, TITLE_BAR_HEIGHT } from '@constants/layout' export const GlobalStyles = css` html, @@ -12,3 +13,15 @@ export const GlobalStyles = css` export const Root = styled.div` height: 100%; ` + +export const Content = styled.div` + padding: ${({ theme }) => theme.spacing(2)}; + + position: fixed; + top: ${({ theme }) => theme.spacing(TITLE_BAR_HEIGHT)}; + left: ${({ theme }) => theme.spacing(NAVIGATOR_WIDTH)}; + right: 0; + bottom: 0; + + overflow: auto; +` diff --git a/apps/renderer/src/components/Layout.tsx b/apps/renderer/src/components/Layout.tsx index 574ecd5..1ba8342 100644 --- a/apps/renderer/src/components/Layout.tsx +++ b/apps/renderer/src/components/Layout.tsx @@ -1,18 +1,24 @@ import React from 'react' +import { Outlet } from 'react-router-dom' import { Global } from '@emotion/react' import { CssBaseline } from '@mui/material' -import { GlobalStyles, Root } from '@components/Layout.styles' +import TitleBar from '@components/TitleBar' +import Navigator from '@components/Navigator' -export interface LayoutProps {} +import * as Styled from '@components/Layout.styles' -export function Layout({ children }: React.PropsWithChildren) { +export function Layout() { return ( - - + + - {children} - + + + + + + ) } diff --git a/apps/renderer/src/components/Navigator.styled.ts b/apps/renderer/src/components/Navigator.styled.ts new file mode 100644 index 0000000..033f743 --- /dev/null +++ b/apps/renderer/src/components/Navigator.styled.ts @@ -0,0 +1,17 @@ +import styled from '@emotion/styled' + +import { NAVIGATOR_WIDTH, TITLE_BAR_HEIGHT } from '@constants/layout' + +export const Root = styled.div` + width: ${({ theme }) => theme.spacing(NAVIGATOR_WIDTH)}; + + padding: ${({ theme }) => theme.spacing(1)}; + border-right: 1px solid #505153; + + position: fixed; + top: ${({ theme }) => theme.spacing(TITLE_BAR_HEIGHT)}; + left: 0; + bottom: 0; + + background-color: #3f4042; +` diff --git a/apps/renderer/src/components/Navigator.tsx b/apps/renderer/src/components/Navigator.tsx new file mode 100644 index 0000000..86cc01a --- /dev/null +++ b/apps/renderer/src/components/Navigator.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import { Link, useLocation } from 'react-router-dom' + +import { Box, IconButton, Stack, Tooltip } from '@mui/material' + +import { NAVIGATOR_ITEMS } from '@constants/navigator' + +import * as Styled from './Navigator.styled' + +interface NavigatorProps {} + +function Navigator({}: NavigatorProps) { + const location = useLocation() + + return ( + + + {NAVIGATOR_ITEMS.map(({ path, label, icon: Icon }) => ( + + + + + theme.transitions.create(['color'], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.shorter, + }), + }} + /> + + + + ))} + + + ) +} + +export default Navigator diff --git a/apps/renderer/src/components/TitleBar.styled.ts b/apps/renderer/src/components/TitleBar.styled.ts new file mode 100644 index 0000000..70819d3 --- /dev/null +++ b/apps/renderer/src/components/TitleBar.styled.ts @@ -0,0 +1,14 @@ +import styled from '@emotion/styled' + +import { TITLE_BAR_HEIGHT } from '@constants/layout' + +export const Root = styled.div` + height: ${({ theme }) => theme.spacing(TITLE_BAR_HEIGHT)}; + + border-bottom: 1px solid #505153; + + background-color: #3f4042; + + -webkit-app-region: drag; + user-select: none; +` diff --git a/apps/renderer/src/components/TitleBar.tsx b/apps/renderer/src/components/TitleBar.tsx new file mode 100644 index 0000000..d98ee22 --- /dev/null +++ b/apps/renderer/src/components/TitleBar.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +import * as Styled from './TitleBar.styled' + +interface TitleBarProps {} + +function TitleBar({}: TitleBarProps) { + return +} + +export default TitleBar diff --git a/apps/renderer/src/constants/layout.ts b/apps/renderer/src/constants/layout.ts new file mode 100644 index 0000000..5952d1f --- /dev/null +++ b/apps/renderer/src/constants/layout.ts @@ -0,0 +1,2 @@ +export const TITLE_BAR_HEIGHT = 5 // 40px +export const NAVIGATOR_WIDTH = 8 // 64px diff --git a/apps/renderer/src/constants/navigator.ts b/apps/renderer/src/constants/navigator.ts new file mode 100644 index 0000000..0310468 --- /dev/null +++ b/apps/renderer/src/constants/navigator.ts @@ -0,0 +1,25 @@ +import React from 'react' + +import HomeRounded from '@mui/icons-material/HomeRounded' +import SearchRounded from '@mui/icons-material/SearchRounded' + +import { SvgIconProps } from '@mui/material' + +export interface NavigatorItem { + icon: React.ComponentType + label: string + path: string +} + +export const NAVIGATOR_ITEMS: NavigatorItem[] = [ + { + icon: HomeRounded, + label: 'Home', + path: '/', + }, + { + icon: SearchRounded, + label: 'Search', + path: '/search', + }, +] diff --git a/apps/renderer/src/emotion.d.ts b/apps/renderer/src/emotion.d.ts new file mode 100644 index 0000000..9c2507e --- /dev/null +++ b/apps/renderer/src/emotion.d.ts @@ -0,0 +1,5 @@ +import { createTheme } from '@mui/material' + +declare module '@emotion/react' { + export interface Theme extends ReturnType {} +} diff --git a/apps/renderer/src/pages/Search.styled.ts b/apps/renderer/src/pages/Search.styled.ts new file mode 100644 index 0000000..9048e73 --- /dev/null +++ b/apps/renderer/src/pages/Search.styled.ts @@ -0,0 +1,3 @@ +import styled from '@emotion/styled' + +export const Root = styled.div`` diff --git a/apps/renderer/src/pages/Search.tsx b/apps/renderer/src/pages/Search.tsx new file mode 100644 index 0000000..7563b8a --- /dev/null +++ b/apps/renderer/src/pages/Search.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +import * as Styled from './Search.styled' + +interface SearchProps {} + +export function Search({}: SearchProps) { + return Search +} diff --git a/apps/renderer/src/pages/index.tsx b/apps/renderer/src/pages/index.tsx index 4bdc093..77bd487 100644 --- a/apps/renderer/src/pages/index.tsx +++ b/apps/renderer/src/pages/index.tsx @@ -1,14 +1,26 @@ import React from 'react' import { createHashRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom' +import { Layout } from '@components/Layout' + import { Home } from '@pages/Home' +import { Search } from '@pages/Search' const router = createHashRouter( createRoutesFromElements( } - />, + element={} + > + } + /> + } + /> + , ), ) diff --git a/apps/renderer/src/styles/theme.ts b/apps/renderer/src/styles/theme.ts index 79b0c3e..1979837 100644 --- a/apps/renderer/src/styles/theme.ts +++ b/apps/renderer/src/styles/theme.ts @@ -1,3 +1,10 @@ import { createTheme } from '@mui/material' -export const theme = createTheme() +export const darkTheme = createTheme({ + palette: { + mode: 'dark', + background: { + default: '#242428', + }, + }, +}) diff --git a/apps/renderer/tsconfig.json b/apps/renderer/tsconfig.json index aa5b7ba..f918db1 100644 --- a/apps/renderer/tsconfig.json +++ b/apps/renderer/tsconfig.json @@ -8,7 +8,8 @@ "@pages": ["src/pages"], "@pages/*": ["src/pages/*"], "@components/*": ["src/components/*"], - "@styles/*": ["src/styles/*"] + "@styles/*": ["src/styles/*"], + "@constants/*": ["src/constants/*"], } }, "include": ["src"] diff --git a/packages/tsconfig/renderer.json b/packages/tsconfig/renderer.json index 51618a8..74bfc75 100644 --- a/packages/tsconfig/renderer.json +++ b/packages/tsconfig/renderer.json @@ -6,7 +6,7 @@ "noUnusedParameters": true, "noImplicitReturns": true, "moduleResolution": "bundler", - "allowImportingTsExtensions": true, + "allowImportingTsExtensions": false, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5fb37d7..f3dca6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -229,6 +229,9 @@ importers: '@emotion/styled': specifier: ^11.11.0 version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) + '@mui/icons-material': + specifier: ^6.1.6 + version: 6.1.6(@mui/material@5.14.5)(@types/react@18.2.20)(react@18.2.0) '@mui/material': specifier: ^5.14.5 version: 5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) @@ -1392,6 +1395,13 @@ packages: dependencies: regenerator-runtime: 0.14.0 + /@babel/runtime@7.26.0: + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + dev: false + /@babel/template@7.22.5: resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} engines: {node: '>=6.9.0'} @@ -3018,6 +3028,23 @@ packages: resolution: {integrity: sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA==} dev: false + /@mui/icons-material@6.1.6(@mui/material@5.14.5)(@types/react@18.2.20)(react@18.2.0): + resolution: {integrity: sha512-5r9urIL2lxXb/sPN3LFfFYEibsXJUb986HhhIeu1gOcte460pwdSiEhBSxkAuyT8Dj7jvu9MjqSBmSumQELo8A==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@mui/material': ^6.1.6 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.26.0 + '@mui/material': 5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.20 + react: 18.2.0 + dev: false + /@mui/material@5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA==} engines: {node: '>=12.0.0'}