Skip to content

Commit

Permalink
refactor: docs design
Browse files Browse the repository at this point in the history
  • Loading branch information
iCrawl committed Aug 14, 2022
1 parent d08da8a commit cc70d0c
Show file tree
Hide file tree
Showing 33 changed files with 1,525 additions and 1,570 deletions.
16 changes: 8 additions & 8 deletions packages/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@emotion/react": "^11.10.0",
"@emotion/server": "^11.10.0",
"@mantine/core": "^5.1.5",
"@mantine/hooks": "^5.1.5",
"@mantine/next": "^5.1.5",
"@mantine/nprogress": "^5.1.5",
"@mantine/spotlight": "^5.1.5",
"@microsoft/api-extractor-model": "^7.23.0",
"@microsoft/tsdoc": "0.14.1",
"@microsoft/tsdoc-config": "0.16.1",
Expand All @@ -60,23 +67,17 @@
"sharp": "^0.30.7"
},
"devDependencies": {
"@testing-library/cypress": "^8.0.3",
"@testing-library/dom": "^8.17.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "^16.11.47",
"@types/react-dom": "^18.0.6",
"@types/react-syntax-highlighter": "^15.5.4",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"@unocss/cli": "^0.45.5",
"@unocss/preset-web-fonts": "^0.45.5",
"@unocss/reset": "^0.45.5",
"@vitejs/plugin-react": "^2.0.0",
"@vitejs/plugin-react": "^2.0.1",
"c8": "^7.12.0",
"concurrently": "^7.3.0",
"cypress": "^10.4.0",
"eslint": "^8.21.0",
"eslint-config-marine": "^9.4.1",
"eslint-config-prettier": "^8.5.0",
Expand All @@ -85,7 +86,6 @@
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"happy-dom": "^6.0.4",
"msw": "^0.44.2",
"prettier": "^2.7.1",
"typescript": "^4.7.4",
"unocss": "^0.45.5",
Expand Down
46 changes: 22 additions & 24 deletions packages/website/src/components/CodeListing.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Group, Stack, Title } from '@mantine/core';
import type { ReactNode } from 'react';
import { CommentSection } from './Comment';
import { HyperlinkedText } from './HyperlinkedText';
Expand All @@ -9,36 +10,33 @@ export enum CodeListingSeparatorType {
Value = '=',
}

export interface CodeListingProps {
name: string;
summary?: ReturnType<DocItem['toJSON']>['summary'];
typeTokens: TokenDocumentation[];
separator?: CodeListingSeparatorType;
children?: ReactNode;
className?: string | undefined;
}

export function CodeListing({
name,
className,
separator = CodeListingSeparatorType.Type,
summary,
typeTokens,
children,
}: CodeListingProps) {
}: {
name: string;
summary?: ReturnType<DocItem['toJSON']>['summary'];
typeTokens: TokenDocumentation[];
separator?: CodeListingSeparatorType;
children?: ReactNode;
className?: string | undefined;
}) {
return (
<div className={className}>
<div key={name} className="flex flex-col">
<div className="w-full flex flex-row gap-3">
<h4 className="font-mono m-0">{`${name}`}</h4>
<h4 className="m-0">{separator}</h4>
<h4 className="font-mono m-0 break-all">
<HyperlinkedText tokens={typeTokens} />
</h4>
</div>
{summary && <CommentSection textClassName="text-dark-100 dark:text-gray-300" node={summary} />}
{children}
</div>
</div>
<Stack key={name}>
<Group>
<Title order={4} className="font-mono">
{name}
</Title>
<Title order={4}>{separator}</Title>
<Title order={4} className="font-mono break-all">
<HyperlinkedText tokens={typeTokens} />
</Title>
</Group>
{summary && <CommentSection node={summary} />}
{children}
</Stack>
);
}
54 changes: 39 additions & 15 deletions packages/website/src/components/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,70 @@
import { Anchor, Box, Text } from '@mantine/core';
import Link from 'next/link';
import type { ReactNode } from 'react';
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import type { CommentNode } from '~/DocModel/comment/CommentNode';
import type { CommentNodeContainer } from '~/DocModel/comment/CommentNodeContainer';
import type { FencedCodeCommentNode } from '~/DocModel/comment/FencedCodeCommentNode';
import type { LinkTagCommentNode } from '~/DocModel/comment/LinkTagCommentNode';
import type { PlainTextCommentNode } from '~/DocModel/comment/PlainTextCommentNode';

export interface RemarksBlockProps {
node: ReturnType<CommentNode['toJSON']>;
textClassName?: string | undefined;
}

export function CommentSection({ node, textClassName }: RemarksBlockProps): JSX.Element {
export function CommentSection({ node }: { node: ReturnType<CommentNode['toJSON']> }): JSX.Element {
const createNode = (node: ReturnType<CommentNode['toJSON']>, idx?: number): ReactNode => {
switch (node.kind) {
case 'PlainText':
return <span key={idx}>{(node as ReturnType<PlainTextCommentNode['toJSON']>).text}</span>;
return (
<Text key={idx} span>
{(node as ReturnType<PlainTextCommentNode['toJSON']>).text}
</Text>
);
case 'Paragraph':
return (
<p key={idx} className={textClassName}>
<Text key={idx} inline>
{(node as ReturnType<CommentNodeContainer['toJSON']>).nodes.map((node, idx) => createNode(node, idx))}
</p>
</Text>
);
case 'SoftBreak':
return <br key={idx} />;
case 'LinkTag': {
const { codeDestination, urlDestination, text } = node as ReturnType<LinkTagCommentNode['toJSON']>;

if (codeDestination) {
return <Link href={codeDestination.path}>{text ?? codeDestination.name}</Link>;
return (
<Link key={idx} href={codeDestination.path} passHref>
<Anchor component="a" className="font-mono">
{text ?? codeDestination.name}
</Anchor>
</Link>
);
}

if (urlDestination) {
return <Link href={urlDestination}>{text ?? urlDestination}</Link>;
return (
<Link key={idx} href={urlDestination} passHref>
<Anchor component="a" className="font-mono">
{text ?? urlDestination}
</Anchor>
</Link>
);
}

return null;
}
case 'FencedCodeBlock': {
const { language, code } = node as ReturnType<FencedCodeCommentNode['toJSON']>;
return <SyntaxHighlighter language={language}>{code}</SyntaxHighlighter>;
return (
<SyntaxHighlighter
key={idx}
wrapLines
wrapLongLines
language={language}
style={vscDarkPlus}
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
>
{code}
</SyntaxHighlighter>
);
}
default:
break;
Expand All @@ -50,12 +74,12 @@ export function CommentSection({ node, textClassName }: RemarksBlockProps): JSX.
};

return (
<div>
<Box>
{node.kind === 'Paragraph' || node.kind === 'Section' ? (
<>{(node as CommentNodeContainer).nodes.map((node, idx) => createNode(node, idx))}</>
) : (
<>{createNode(node)}</>
createNode(node)
)}
</div>
</Box>
);
}
128 changes: 65 additions & 63 deletions packages/website/src/components/DocContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Group, Stack, Title, Text, Box } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';
import type { ReactNode } from 'react';
import { VscListSelection, VscSymbolParameter } from 'react-icons/vsc';
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
Expand Down Expand Up @@ -32,73 +34,73 @@ export function DocContainer({
extendsTokens,
implementsTokens,
}: DocContainerProps) {
const matches = useMediaQuery('(max-width: 768px)', true, { getInitialValueInEffect: false });

return (
<div className="flex flex-col min-h-full max-h-full grow">
<div className="border-0.5 border-gray px-10 py-2">
<h2 className="flex gap-2 items-center break-all m-0 dark:text-white">
<Stack>
<Title order={2} ml="xs">
<Group>
{generateIcon(kind)}
{name}
</h2>
</div>
</Group>
</Title>

<div className="min-h-full overflow-y-auto overflow-x-clip px-10 pt-5 pb-10">
<Section iconElement={<VscListSelection />} title="Summary" className="dark:text-white mb-5">
{summary ? (
<CommentSection textClassName="text-dark-100 dark:text-gray-300" node={summary} />
) : (
<p className="text-dark-100 dark:text-gray-300">No summary provided.</p>
)}
</Section>
<div className={extendsTokens?.length ? 'mb-2' : 'mb-10'}>
<SyntaxHighlighter
wrapLines
wrapLongLines
language="typescript"
style={vscDarkPlus}
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
>
{excerpt}
</SyntaxHighlighter>
</div>
{extendsTokens?.length ? (
<div
className={`flex flex-row items-center dark:text-white gap-3 ${implementsTokens?.length ? '' : 'mb-10'}`}
>
<h3 className="m-0">Extends</h3>
<h3 className="m-0">{CodeListingSeparatorType.Type}</h3>
<p className="font-mono break-all">
<HyperlinkedText tokens={extendsTokens} />
</p>
</div>
) : null}
{implementsTokens?.length ? (
<div className={`flex flex-row items-center dark:text-white gap-3 mb-10`}>
<h3 className="m-0">Implements</h3>
<h3 className="m-0">{CodeListingSeparatorType.Type}</h3>
<p className="font-mono break-all">
{implementsTokens.map((token, i) => (
<>
<HyperlinkedText key={i} tokens={token} />
{i < implementsTokens.length - 1 ? ', ' : ''}
</>
))}
</p>
</div>
<Section title="Summary" icon={<VscListSelection />} padded dense={matches}>
{summary ? <CommentSection node={summary} /> : <Text>No summary provided.</Text>}
</Section>

<Box px="xs" pb="xs">
<SyntaxHighlighter
wrapLongLines
language="typescript"
style={vscDarkPlus}
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
>
{excerpt}
</SyntaxHighlighter>
</Box>

{extendsTokens?.length ? (
<Group noWrap>
<Title order={3} ml="xs">
Extends
</Title>
<Title order={3} ml="xs">
{CodeListingSeparatorType.Type}
</Title>
<Text className="font-mono break-all">
<HyperlinkedText tokens={extendsTokens} />
</Text>
</Group>
) : null}

{implementsTokens?.length ? (
<Group noWrap>
<Title order={3} ml="xs">
Implements
</Title>
<Title order={3} ml="xs">
{CodeListingSeparatorType.Type}
</Title>
<Text className="font-mono break-all">
{implementsTokens.map((token, idx) => (
<>
<HyperlinkedText tokens={token} />
{idx < implementsTokens.length - 1 ? ', ' : ''}
</>
))}
</Text>
</Group>
) : null}

<Stack>
{typeParams?.length ? (
<Section title="Type Parameters" icon={<VscSymbolParameter />} padded dense={matches} defaultClosed>
<TypeParamTable data={typeParams} />
</Section>
) : null}
<div className="space-y-10">
{typeParams?.length ? (
<Section
iconElement={<VscSymbolParameter />}
title="Type Parameters"
className="dark:text-white"
defaultClosed
>
<TypeParamTable data={typeParams} />
</Section>
) : null}
<div className="space-y-10">{children}</div>
</div>
</div>
</div>
<Stack>{children}</Stack>
</Stack>
</Stack>
);
}
19 changes: 9 additions & 10 deletions packages/website/src/components/HyperlinkedText.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import { Anchor, Text } from '@mantine/core';
import Link from 'next/link';
import type { TokenDocumentation } from '~/util/parse.server';

export interface HyperlinkedTextProps {
tokens: TokenDocumentation[];
}

/**
* Constructs a hyperlinked html node based on token type references
*
* @param tokens An array of documentation tokens to construct the HTML
*
* @returns An array of JSX elements and string comprising the hyperlinked text
*/
export function HyperlinkedText({ tokens }: HyperlinkedTextProps) {
export function HyperlinkedText({ tokens }: { tokens: TokenDocumentation[] }) {
return (
<>
{tokens.map((token) => {
{tokens.map((token, idx) => {
if (token.path) {
return (
<Link key={token.text} href={token.path}>
<a className="text-blue-500 dark:text-blue-300 no-underline">{token.text}</a>
<Link key={idx} href={token.path} passHref>
<Anchor component="a" inherit>
{token.text}
</Anchor>
</Link>
);
}

return (
<span key={token.text} className="text-blue-500 dark:text-blue-300">
<Text key={idx} span unstyled>
{token.text}
</span>
</Text>
);
})}
</>
Expand Down
Loading

0 comments on commit cc70d0c

Please sign in to comment.