Skip to content

Commit

Permalink
[ENG-1784] Finish /sdk page (#656)
Browse files Browse the repository at this point in the history
* swap /sdk to SdkDirectory

* ignore .mdx files

* fix shrunken mermaid diagram

* companies.json

* do not activate on every terminal

* reassign DEV

* reassign DEV

* link companies.json to SdkDirectory

* embed link to /sdk/{company} page

* some UI changes

* add more padding to bottom

* /sdk/category/all

* yarn pages

* pass filter to SdkDirectory

* generate subpaths

* generated all category pages

* fix some bugs

* put vimeo under Video & Audio

* move CategoryFilters into its own file

* TODO: expand/close all

* increase default # of APIs to show

* expand/close all

* highlight trigger if selected

* disable search + mobile friendly

* friendly on mobile

* fix window === undefined
  • Loading branch information
dphuang2 authored Mar 22, 2024
1 parent effa7dd commit a5cafd0
Show file tree
Hide file tree
Showing 76 changed files with 2,366 additions and 1,596 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/*.mdx
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
],
"files.insertFinalNewline": false,
"terminal.integrated.scrollback": 10000,
"git.ignoreLimitWarning": true
"git.ignoreLimitWarning": true,
"python.terminal.activateEnvironment": false
}
64 changes: 6 additions & 58 deletions generator/konfig-docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,7 @@ const { themes } = require("prism-react-renderer");
const lightCodeTheme = themes.github;
const darkCodeTheme = themes.dracula;

const { remarkCodeHike } = require("konfig-code-hike-mdx");

/**
* mdx-mermaid plugin.
*
* @param config Config passed in from parser.
* @returns Function to transform mdxast.
*/
function mermaid(config) {
return async function transformer(ast) {
const visit = await import("unist-util-visit").then((mod) =>
typeof mod.default === "function" ? mod.default : mod.visit
);

// Find all the mermaid diagram code blocks. i.e. ```mermaid
const instances = [];
visit(ast, { type: "code", lang: "mermaid" }, (node, index, parent) => {
instances.push([node, index, parent]);
});

// Replace each Mermaid code block with the Mermaid component
for (let i = 0; i < instances.length; i++) {
const [node, index, parent] = instances[i];
const result = createMermaidNode(
node,
"Mermaid",
i === 0 ? config : undefined
);
Array.prototype.splice.apply(parent.children, [index, 1, ...result]);
}
return ast;
};
}

function createMermaidNode(node, hName, config) {
return [
{
type: "mermaidCodeBlock",
data: {
hName,
hProperties: {
config: JSON.stringify(config),
chart: node.value,
},
},
},
];
}
const { remarkCodeHike } = require("@code-hike/mdx");

const beforeRemarkPlugins = [
[
Expand Down Expand Up @@ -93,15 +46,7 @@ const beforeRemarkPluginsForPages = [
* @returns {Promise<import('@docusaurus/types').Config>}
*/
async function createConfig() {
const remarkPlugins = [
(await import("remark-gfm")).default,
[
mermaid,
{
theme: { light: "default", dark: "dark" },
},
],
];
const remarkPlugins = [(await import("remark-gfm")).default];
return {
title: "Konfig",
tagline: "Generate SDKs for your REST API",
Expand All @@ -118,8 +63,12 @@ async function createConfig() {
async: true,
},
],
markdown: {
mermaid: true,
},
themes: [
"docusaurus-json-schema-plugin",
"@docusaurus/theme-mermaid",
[
require.resolve("@easyops-cn/docusaurus-search-local"),
{
Expand All @@ -128,7 +77,6 @@ async function createConfig() {
docsRouteBasePath: "/",
},
],
"mdx-v2",
],
plugins: [
async function docusaurus(context, options) {
Expand Down
11 changes: 7 additions & 4 deletions generator/konfig-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@docusaurus/core": "^3.1.1",
"@docusaurus/plugin-google-gtag": "^3.1.1",
"@docusaurus/preset-classic": "^3.1.1",
"@docusaurus/theme-mermaid": "^3.1.1",
"@easyops-cn/docusaurus-search-local": "^0.40.1",
"@fortawesome/fontawesome-free": "^6.4.0",
"@mdx-js/react": "^3.0.1",
Expand All @@ -38,13 +39,15 @@
"clsx": "^2.1.0",
"cmdk": "^1.0.0",
"docusaurus-json-schema-plugin": "^1.6.0",
"docusaurus-theme-mdx-v2": "^0.1.2",
"express": "^4.18.2",
"konfig-code-hike-mdx": "0.9.0",
"konfig-lib": "^1.35.0",
"lucide-react": "^0.358.0",
"marked": "^11.1.1",
"mermaid": "^10.2.4",
"mermaid": "^10.9.0",
"mobx": "^6.12.0",
"mobx-persist-store": "^1.1.4",
"mobx-react-lite": "^4.0.6",
"moment": "^2.30.1",
"party-js": "^2.2.0",
"postcss": "^8.4.25",
Expand All @@ -57,8 +60,8 @@
"react-innertext": "^1.1.5",
"react-player": "^2.12.0",
"react-tooltip": "^5.15.0",
"remark-footnotes": "2.0.0",
"remark-gfm": "^3.0.1",
"remark-footnotes": "^4.0.1",
"remark-gfm": "^4.0.0",
"swiper": "^10.1.0",
"tailwind-merge": "^2.2.1",
"tailwindcss": "^3.3.2",
Expand Down
235 changes: 235 additions & 0 deletions generator/konfig-docs/src/components/CategoryFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@radix-ui/react-collapsible";
import { ChevronDown, ChevronUp } from "lucide-react";
import { useState } from "react";
import { makeAutoObservable } from "mobx";
import { observer } from "mobx-react-lite";
import { makePersistable } from "mobx-persist-store";
import Link from "@docusaurus/Link";
import { Button } from "./ui/button";
import { cn } from "../util/util";

export type Filter = "all" | string;

type CategoryFiltersProps = {
categories: {
parentCategory: string;
subCategories: { category: string; subpath: string }[];
subpath: string;
}[];
filter: Filter;
className?: string;
};

class AllCategories {
categories: Record<string, ParentCategorySection>;

constructor(categories: CategoryFiltersProps["categories"]) {
this.categories = categories.reduce((acc, category) => {
acc[category.parentCategory] = new ParentCategorySection();
return acc;
}, {});
makeAutoObservable(this, {}, { autoBind: true });
if (typeof window === "undefined") return;
makePersistable(this, {
name: "AllCategories",
properties: ["categories"],
storage: window.localStorage,
});
}

get anyCategoryIsOpen() {
return Object.values(this.categories).some((category) => category.isOpen);
}
}

class ParentCategorySection {
isOpen: boolean = false;

constructor() {
makeAutoObservable(this);
}
}

export const CategoryFilters = observer((props: CategoryFiltersProps) => {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Collapsible
className="md:hidden w-full relative"
open={isOpen}
onOpenChange={setIsOpen}
>
<CollapsibleTrigger asChild>
<Button className="w-full mb-2">
{isOpen ? "Hide" : "Show"} Categories
</Button>
</CollapsibleTrigger>
<CollapsibleContent>
<CategoryFilterControls {...props} />
</CollapsibleContent>
</Collapsible>
<CategoryFilterControls className="hidden md:block" {...props} />
</>
);
});

export const CategoryFilterControls = observer(
({ categories, filter, className }: CategoryFiltersProps) => {
const [allCategories] = useState(() => new AllCategories(categories));
return (
<div className={cn("w-full md:w-[300px]", className)}>
<h3>Categories</h3>
<Button
variant="outline"
size="sm"
className="mb-1 w-full"
onClick={() => {
const anyCategoryIsOpen = allCategories.anyCategoryIsOpen;
Object.values(allCategories.categories).forEach((category) => {
category.isOpen = !anyCategoryIsOpen;
});
}}
>
{allCategories.anyCategoryIsOpen ? "Close All" : "Expand All"}
</Button>
<ul className="pl-0 mb-0 list-none">
<li>
<CategoryLink
selected={filter === "all"}
indented={false}
category="All Categories"
subpath="/sdk/category/all"
/>
</li>
{categories.map(({ parentCategory, subCategories, subpath }, i) => (
<Category
allCategories={allCategories}
filter={filter}
key={i}
parentCategory={parentCategory}
subCategories={subCategories}
subpath={subpath}
/>
))}
</ul>
</div>
);
}
);

type CategoryProps = {
parentCategory: string;
subCategories: { category: string; subpath: string }[];
filter: Filter;
subpath: string;
allCategories: AllCategories;
};

const Category = observer(
({
parentCategory,
subCategories,
filter,
subpath,
allCategories,
}: CategoryProps) => {
const category = allCategories.categories[parentCategory];

return (
<Collapsible
open={category.isOpen}
onOpenChange={(open) => {
category.isOpen = open;
}}
className="w-full md:w-[300px]"
>
<CollapsibleTrigger
aria-selected={
filter === parentCategory ||
subCategories.map((sub) => sub.category).includes(filter)
}
className="group aria-selected:hover:bg-blue-100 aria-selected:bg-blue-100 aria-selected:text-blue-800 text-slate-500 hover:text-slate-800 rounded-md py-2 px-2 w-full hover:bg-slate-100 transition-all"
>
<li>
<div className="flex items-center gap-x-2">
{category.isOpen ? (
<ChevronUp className="text-slate-400 group-aria-selected:text-blue-400" />
) : (
<ChevronDown className="text-slate-400 group-aria-selected:text-blue-400" />
)}
<div className="font-semibold">{parentCategory}</div>
</div>
</li>
</CollapsibleTrigger>
<CollapsibleContent className="mt-0">
<ul className="mb-0 pl-0 list-none">
<SubCategory
filter={filter}
label={`All ${parentCategory}`}
category={parentCategory}
subpath={subpath}
/>
{subCategories.map(({ category, subpath }) => (
<SubCategory
subpath={subpath}
filter={filter}
key={category}
category={category}
/>
))}
</ul>
</CollapsibleContent>
</Collapsible>
);
}
);

type SubCategoryProps = {
category: string;
label?: string;
filter: string;
subpath: string;
};
function SubCategory({ category, label, filter, subpath }: SubCategoryProps) {
return (
<li>
<CategoryLink
subpath={subpath}
selected={filter === category}
category={category}
label={label}
/>
</li>
);
}

function CategoryLink({
category,
label,
indented,
selected = false,
subpath,
}: {
category: string;
label?: string;
selected?: boolean;
indented?: boolean;
subpath: string;
}) {
return (
<Link
aria-selected={selected}
data-indent={indented}
className={
"pl-12 rounded-md data-[indent=false]:pl-2 aria text-slate-500 hover:text-slate-800 hover:no-underline block py-2 hover:bg-slate-100 transition-all aria-selected:hover:bg-blue-100 aria-selected:bg-blue-100 aria-selected:text-blue-800"
}
href={subpath}
>
{label ?? category}
</Link>
);
}
2 changes: 1 addition & 1 deletion generator/konfig-docs/src/components/CommandMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function CommandMenu({ ...props }: DialogProps) {
onClick={() => setOpen(true)}
{...props}
>
<span className="hidden lg:inline-flex">Search all APIs...</span>
<span className="hidden lg:inline-flex">Search all Companies...</span>
<span className="inline-flex lg:hidden">Search...</span>
<kbd className="pointer-events-none absolute right-[0.3rem] hidden select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<span className="text-xs"></span>K
Expand Down
Loading

0 comments on commit a5cafd0

Please sign in to comment.