Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/devtools site #14

Merged
merged 15 commits into from
Apr 10, 2024
3 changes: 3 additions & 0 deletions docs/site/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
36 changes: 36 additions & 0 deletions docs/site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
16 changes: 16 additions & 0 deletions docs/site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Devtools Docs Site
## Getting Started

This is still a WIP, For now, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Then got to [http://localhost:3000](http://localhost:3000) with your browser to see the result.
22 changes: 22 additions & 0 deletions docs/site/components/ColorSchemeSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { IconButton, useColorMode, useColorModeValue } from '@chakra-ui/react';
import { FaMoon, FaSun } from 'react-icons/fa';

export const ColorSchemeSwitch = () => {
const { toggleColorMode } = useColorMode();
const SwitchIcon = useColorModeValue(FaMoon, FaSun);
const text = useColorModeValue('dark', 'light');

return (
<IconButton
size="md"
fontSize="lg"
aria-label={`Switch to ${text} mode`}
variant="ghost"
color="current"
ml={{ base: '0', md: '3' }}
icon={<SwitchIcon />}
onClick={toggleColorMode}
/>
);
};
27 changes: 27 additions & 0 deletions docs/site/components/Context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

export const DEFAULT_CONTEXT = {
bannerExpanded: true,
setBannerExpanded: (expanded: boolean) => {},
};

export const AppContext = React.createContext(DEFAULT_CONTEXT);

export const Context = (props: React.PropsWithChildren<unknown>) => {
const [state, setState] = React.useState(DEFAULT_CONTEXT);

const withHandlers = React.useMemo(() => {
return {
...state,
setBannerExpanded: (expanded: boolean) => {
setState({ ...state, bannerExpanded: expanded });
},
};
}, [state]);

return (
<AppContext.Provider value={withHandlers}>
{props.children}
</AppContext.Provider>
);
};
31 changes: 31 additions & 0 deletions docs/site/components/DevtoolsTeam.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { Avatar, SimpleGrid, VStack, Text } from '@chakra-ui/react';
import teamdata from '../config/team.json';

/**
* Individual Profile card with avatar, name and domain vertically stacked
*/
const ProfileCard = (props: any) => {
return (
<VStack>
<Avatar size="2xl" name={props.profile.name} src={props.profile.avatar} />
<Text fontSize="lg">{props.profile.name}</Text>
<Text fontSize="md">{props.profile.domain.join(', ')}</Text>
</VStack>
);
};

/**
* Component to render Player Team cards
*/
export const DevtoolsTeam = () => {
return (
<SimpleGrid columns={[2, null, 3]} spacing="40px">
{teamdata
.sort(() => 0.5 - Math.random())
.map((element) => {
return <ProfileCard key={element.name} profile={element} />;
})}
</SimpleGrid>
);
};
13 changes: 13 additions & 0 deletions docs/site/components/Image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import path from 'path';

export function withBasePrefix(location?: string): string | undefined {
if (!location) {
return location;
}

if (process.env.NEXT_PUBLIC_BASE_PATH) {
return path.join(process.env.NEXT_PUBLIC_BASE_PATH, location);
}

return location;
}
226 changes: 226 additions & 0 deletions docs/site/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import React from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import {
Flex,
Button,
Box,
chakra,
Drawer,
DrawerContent,
Heading,
HStack,
Image,
Icon,
IconButton,
UnorderedList,
useColorModeValue,
useDisclosure,
useBreakpointValue,
Text,
} from '@chakra-ui/react';
import { HamburgerIcon } from '@chakra-ui/icons';
import type { Route } from '../config/navigation';
import NAV, { PATH_TO_NAV } from '../config/navigation';
import { ColorSchemeSwitch } from './ColorSchemeSwitch';
import { GITHUB_URL } from '../config/constants';
import { withBasePrefix } from './Image';
import { GithubIcon } from './gh-icon';

const getPathFromRoute = (route: Route): string => {
if (route.path) {
return route.path;
}

if (route.routes) {
for (const r of route.routes) {
const nestedRoute = getPathFromRoute(r);
if (nestedRoute) {
return nestedRoute;
}
}
}

return '';
};


const NavTitleOrLink = (props: { route: Route }) => {
const { route } = props;

const { pathname } = useRouter();
const router = useRouter();
const langpref = router.query.lang;
const selectedButtonColor = useColorModeValue('blue.800', 'blue.600');

if (route.path) {
return (
<chakra.li>
<Link
passHref
href={{
pathname: route.path,
query: langpref ? { lang: langpref } : undefined,
}}
>
<Button
size="sm"
variant="ghost"
mx="3"
colorScheme={pathname === route.path ? 'blue' : 'gray'}
color={pathname === route.path ? selectedButtonColor : undefined}
>
<HStack spacing="2">
<Text>{route.title}</Text>
</HStack>
</Button>
</Link>
</chakra.li>
);
}

return (
<Heading as="h4" size="md" mt="8">
{route.title}
</Heading>
);
};

const SideNavigationList = (props: { route: Route }) => {
const { route } = props;

return (
<Box>
<NavTitleOrLink route={route} />

{route.routes && (
<UnorderedList spacing={1} ml="0" mt="2" styleType="none">
{route.routes.map((r) => (
<SideNavigationList key={r.title} route={r} />
))}
</UnorderedList>
)}
</Box>
);
};

export const SideNavigation = () => {
const { pathname } = useRouter();
const subRoutes = PATH_TO_NAV.get(pathname);

const route = NAV.routes.find((r) => r.title === subRoutes?.[0]);

if (!route) {
return null;
}

return (
<Box as="nav">
<SideNavigationList route={route} />
</Box>
);
};

export const Footer = () => {
return null;
};

export const GitHubButton = () => {
return (
<Link aria-label="Go to our GitHub page" href={GITHUB_URL}>
<IconButton
variant="ghost"
aria-label="Go to our Github page"
icon={
<Icon
as={GithubIcon}
display="block"
transition="color 0.2s"
w="5"
h="5"
/>
}
/>
</Link>
);
};

export const TopNavigation = () => {
const { pathname } = useRouter();
const subRoutes = PATH_TO_NAV.get(pathname);
const mobileNavDisclosure = useDisclosure();

const currentTopLevelRoute = NAV.routes.find(
(r) => r.title === subRoutes?.[0]
);

const logoSrc = useBreakpointValue({
base: useColorModeValue(
withBasePrefix('/logo/logo-light-small.png'),
withBasePrefix('/logo/logo-dark-small.png')
),
lg: useColorModeValue(
withBasePrefix('/logo/logo-light-large.png'),
withBasePrefix('/logo/logo-dark-large.png')
),
});

const selectedButtonColor = useColorModeValue('blue.800', 'blue.600');

return (
<Flex w="100%" h="100%" direction="column" align="center">
<Flex px="6" w="100%" h="100%" align="center" justify="space-between">
<HStack>
<IconButton
variant="ghost"
icon={<HamburgerIcon />}
display={{ base: 'flex', md: 'none' }}
aria-label="Open Side Navigation Menu"
onClick={mobileNavDisclosure.onOpen}
/>
<Link passHref href="/">
<Image alt="Player Logo" height="48px" src={logoSrc} style={{ margin: '16px 0 16px 0' }} />
</Link>
</HStack>

<Box>
<HStack spacing="4">
{NAV.routes.map((topRoute) => {
const navRoute = getPathFromRoute(topRoute);
const isSelected = currentTopLevelRoute?.title === topRoute.title;

return (
<Link key={topRoute.title} passHref href={navRoute} >
<Button
variant="ghost"
colorScheme={isSelected ? 'blue' : 'gray'}
color={isSelected ? selectedButtonColor : undefined}
size="md"
ml="0"
suppressHydrationWarning
>
{topRoute.title}
</Button>
</Link>
);
})}
<ColorSchemeSwitch />
<GitHubButton />
</HStack>
</Box>
<Drawer
isOpen={mobileNavDisclosure.isOpen}
placement="left"
onOverlayClick={mobileNavDisclosure.onClose}
onClose={mobileNavDisclosure.onClose}
>
<DrawerContent>
<Box px="10" maxH="100vh" overflowY="auto">
<SideNavigation />
</Box>
</DrawerContent>
</Drawer>
</Flex>
</Flex>
);
};
Loading