mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 11:03:30 +01:00
refactor: docs design (#8487)
This commit is contained in:
@@ -1,30 +1,207 @@
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { type ItemListProps, ItemSidebar } from './ItemSidebar';
|
||||
import {
|
||||
useMantineTheme,
|
||||
AppShell,
|
||||
Navbar,
|
||||
MediaQuery,
|
||||
// Aside,
|
||||
Header,
|
||||
Burger,
|
||||
Anchor,
|
||||
Breadcrumbs,
|
||||
ScrollArea,
|
||||
Group,
|
||||
Text,
|
||||
ThemeIcon,
|
||||
Box,
|
||||
UnstyledButton,
|
||||
createStyles,
|
||||
Menu,
|
||||
ActionIcon,
|
||||
useMantineColorScheme,
|
||||
} from '@mantine/core';
|
||||
import { NextLink } from '@mantine/next';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { type PropsWithChildren, useState } from 'react';
|
||||
import { VscChevronDown, VscPackage } from 'react-icons/vsc';
|
||||
import { WiDaySunny, WiNightClear } from 'react-icons/wi';
|
||||
import { SidebarItems } from './SidebarItems';
|
||||
import type { DocItem } from '~/DocModel/DocItem';
|
||||
import type { findMember } from '~/util/model.server';
|
||||
import type { getMembers } from '~/util/parse.server';
|
||||
|
||||
export interface SidebarLayoutProps {
|
||||
packageName: string;
|
||||
data: {
|
||||
members: ReturnType<typeof getMembers>;
|
||||
member: ReturnType<typeof findMember>;
|
||||
};
|
||||
|
||||
selectedMember?: ReturnType<DocItem['toJSON']> | undefined;
|
||||
}
|
||||
|
||||
export type Members = SidebarLayoutProps['data']['members'];
|
||||
|
||||
export interface GroupedMembers {
|
||||
Classes: Members;
|
||||
Functions: Members;
|
||||
Enums: Members;
|
||||
Interfaces: Members;
|
||||
Types: Members;
|
||||
Variables: Members;
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme, { opened }: { opened: boolean }) => ({
|
||||
control: {
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
padding: theme.spacing.xs,
|
||||
color: theme.colorScheme === 'dark' ? theme.colors.dark![0] : theme.black,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark![7] : theme.colors.gray![0],
|
||||
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
|
||||
},
|
||||
},
|
||||
|
||||
icon: {
|
||||
transition: 'transform 150ms ease',
|
||||
transform: opened ? 'rotate(180deg)' : 'rotate(0deg)',
|
||||
},
|
||||
}));
|
||||
|
||||
const libraries = [
|
||||
{ label: 'builders', value: 'builders' },
|
||||
{ label: 'collection', value: 'collection' },
|
||||
{ label: 'discord.js', value: 'discord.js' },
|
||||
{ label: 'proxy', value: 'proxy' },
|
||||
{ label: 'rest', value: 'rest' },
|
||||
{ label: 'voice', value: 'voice' },
|
||||
{ label: 'ws', value: 'ws' },
|
||||
];
|
||||
|
||||
export function SidebarLayout({ packageName, data, children }: PropsWithChildren<Partial<SidebarLayoutProps>>) {
|
||||
const router = useRouter();
|
||||
|
||||
const theme = useMantineTheme();
|
||||
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === 'dark';
|
||||
|
||||
const [opened, setOpened] = useState(false);
|
||||
const [openedPicker, setOpenedPicker] = useState(false);
|
||||
|
||||
const { classes } = useStyles({ opened: openedPicker });
|
||||
|
||||
const libraryMenuItems = libraries.map((item) => (
|
||||
<Menu.Item key={item.label} component={NextLink} href={`/docs/main/packages/${item.value}`}>
|
||||
{item.label}
|
||||
</Menu.Item>
|
||||
));
|
||||
|
||||
const asPathWithoutQuery = router.asPath.split('?')[0];
|
||||
const breadcrumbs = asPathWithoutQuery?.split('/').map((path, idx, original) => (
|
||||
<Link key={idx} href={original.slice(0, idx + 1).join('/')} passHref>
|
||||
<Anchor component="a">{path}</Anchor>
|
||||
</Link>
|
||||
));
|
||||
|
||||
export function SidebarLayout({
|
||||
packageName,
|
||||
data,
|
||||
children,
|
||||
}: PropsWithChildren<Partial<ItemListProps & { data: { member: ReturnType<typeof findMember> } }>>) {
|
||||
return (
|
||||
<div className="flex flex-col max-w-full h-full max-h-full bg-white dark:bg-dark">
|
||||
<div className="flex min-h-[40px] border-0.5 border-b-0 border-gray items-center m-0 px-2 dark:text-white">
|
||||
Breadcrumbs
|
||||
</div>
|
||||
<div className="flex flex-col lg:flex-row overflow-hidden">
|
||||
<div className="h-full w-full lg:max-w-[310px] lg:min-w-[310px]">
|
||||
<AppShell
|
||||
styles={{
|
||||
main: {
|
||||
background: theme.colorScheme === 'dark' ? theme.colors.dark![8] : theme.colors.gray![0],
|
||||
},
|
||||
}}
|
||||
navbarOffsetBreakpoint="sm"
|
||||
asideOffsetBreakpoint="sm"
|
||||
navbar={
|
||||
<Navbar hiddenBreakpoint="sm" hidden={!opened} width={{ sm: 200, lg: 300 }}>
|
||||
{packageName && data ? (
|
||||
<ItemSidebar packageName={packageName} data={data} selectedMember={data.member} />
|
||||
<>
|
||||
<Navbar.Section p="xs">
|
||||
<>
|
||||
<Menu
|
||||
onOpen={() => setOpenedPicker(true)}
|
||||
onClose={() => setOpenedPicker(false)}
|
||||
radius="md"
|
||||
width="target"
|
||||
>
|
||||
<Menu.Target>
|
||||
<UnstyledButton className={classes.control}>
|
||||
<Group position="apart">
|
||||
<Group>
|
||||
<ThemeIcon variant="outline" size={30}>
|
||||
<VscPackage />
|
||||
</ThemeIcon>
|
||||
<Text weight="600" size="md">
|
||||
{packageName}
|
||||
</Text>
|
||||
</Group>
|
||||
<VscChevronDown className={classes.icon} size={20} />
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>{libraryMenuItems}</Menu.Dropdown>
|
||||
</Menu>
|
||||
</>
|
||||
</Navbar.Section>
|
||||
|
||||
<Navbar.Section p="xs" grow component={ScrollArea}>
|
||||
<SidebarItems members={data.members} setOpened={setOpened} />
|
||||
</Navbar.Section>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="h-full grow">{children}</div>
|
||||
<div className="h-full w-full lg:max-w-[310px] lg:min-w-[310px]">
|
||||
{packageName && data?.member ? (
|
||||
<ItemSidebar packageName={packageName} data={data} selectedMember={data.member} />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Navbar>
|
||||
}
|
||||
// aside={
|
||||
// packageName && data?.member ? (
|
||||
// <MediaQuery smallerThan="sm" styles={{ display: 'none' }}>
|
||||
// <Aside hiddenBreakpoint="sm" width={{ sm: 200, lg: 300 }}>
|
||||
// <ScrollArea p="xs">
|
||||
// <SidebarItems members={data.members} />
|
||||
// </ScrollArea>
|
||||
// </Aside>
|
||||
// </MediaQuery>
|
||||
// ) : (
|
||||
// <></>
|
||||
// )
|
||||
// }
|
||||
// footer={
|
||||
// <Footer height={60} p="md">
|
||||
// Application footer
|
||||
// </Footer>
|
||||
// }
|
||||
header={
|
||||
<Header height={70} p="md">
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', height: '100%' }}>
|
||||
<div>
|
||||
<MediaQuery largerThan="sm" styles={{ display: 'none' }}>
|
||||
<Burger
|
||||
opened={opened}
|
||||
onClick={() => setOpened((o) => !o)}
|
||||
size="sm"
|
||||
color={theme.colors.gray![6]}
|
||||
mr="xl"
|
||||
/>
|
||||
</MediaQuery>
|
||||
|
||||
<MediaQuery smallerThan="sm" styles={{ display: 'none' }}>
|
||||
<Breadcrumbs>{breadcrumbs}</Breadcrumbs>
|
||||
</MediaQuery>
|
||||
</div>
|
||||
<ActionIcon
|
||||
variant="outline"
|
||||
color={dark ? 'yellow' : 'blurple'}
|
||||
onClick={() => toggleColorScheme()}
|
||||
title="Toggle color scheme"
|
||||
>
|
||||
{dark ? <WiDaySunny size={18} /> : <WiNightClear size={18} />}
|
||||
</ActionIcon>
|
||||
</Box>
|
||||
</Header>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user