Skip to content

Commit

Permalink
Synchronize tabs and persist to localstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
sulaiman-fern committed Jul 30, 2024
1 parent ef42bc2 commit 4cc5639
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 8 deletions.
18 changes: 18 additions & 0 deletions packages/ui/app/src/atoms/codeGroupTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useAtomValue } from "jotai";
import { atomWithStorage } from "jotai/utils";

export const FERN_CODE_GROUP_TAB = atomWithStorage<{ groupId: string; value: string }[]>("code-group-tab-id", []);
FERN_CODE_GROUP_TAB.debugLabel = "FERN_CODE_GROUP_TAB";

interface Group {
groupId: string;
value: string;
}

export function useCodeGroup({ groupId }: { groupId?: string }): { selectedGroup?: Group; groupIds: Group[] } {
const groupIds = useAtomValue(FERN_CODE_GROUP_TAB);
if (groupId) {
return { selectedGroup: groupIds.find((pair) => pair.groupId === groupId), groupIds };
}
return { selectedGroup: undefined, groupIds };
}
1 change: 1 addition & 0 deletions packages/ui/app/src/atoms/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from "./apis";
export * from "./auth";
export * from "./codeGroupTab";
export * from "./docs";
export * from "./files";
export * from "./flags";
Expand Down
32 changes: 26 additions & 6 deletions packages/ui/app/src/mdx/components/code/CodeGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { CopyToClipboardButton } from "@fern-ui/components";
import * as Tabs from "@radix-ui/react-tabs";
import clsx from "clsx";
import { useState } from "react";
import { useFeatureFlags } from "../../../atoms";
import { useAtom } from "jotai";
import { useEffect, useState } from "react";
import { FERN_CODE_GROUP_TAB, useCodeGroup, useFeatureFlags } from "../../../atoms";
import { HorizontalOverflowMask } from "../../../commons/HorizontalOverflowMask";
import { FernSyntaxHighlighter, FernSyntaxHighlighterProps } from "../../../syntax-highlighting/FernSyntaxHighlighter";

Expand All @@ -13,12 +14,15 @@ export declare namespace CodeGroup {

export interface Props {
items: Item[];
groupId?: string;
}
}

export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({ items }) => {
export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({ items, groupId }) => {
const { isDarkCodeEnabled } = useFeatureFlags();
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const [selectedTabIndex, setSelectedTabIndex] = useState("0");
const [_, setSelectedTab] = useAtom(FERN_CODE_GROUP_TAB);
const { selectedGroup, groupIds } = useCodeGroup({ groupId });

const containerClass = clsx(
"after:ring-card-border bg-card relative mt-4 first:mt-0 mb-6 flex w-full min-w-0 max-w-full flex-col rounded-lg shadow-sm after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:ring-1 after:ring-inset after:content-['']",
Expand All @@ -27,6 +31,12 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
},
);

useEffect(() => {
if (!!selectedGroup) {

Check failure on line 35 in packages/ui/app/src/mdx/components/code/CodeGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Redundant double negation
setSelectedTabIndex(selectedGroup.value);
}
}, [selectedGroup]);

if (items.length === 1 && items[0] != null) {
return (
<div className={containerClass}>
Expand All @@ -50,8 +60,18 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
return (
<Tabs.Root
className={containerClass}
onValueChange={(value) => setSelectedTabIndex(parseInt(value, 10))}
defaultValue="0"
onValueChange={(value) => {
setSelectedTabIndex(value);
if (groupId) {
if (selectedGroup) {
const filteredGroupIds = groupIds.filter((group) => group.groupId !== selectedGroup.groupId);
setSelectedTab([{ groupId: groupId, value: value }, ...filteredGroupIds]);

Check failure on line 68 in packages/ui/app/src/mdx/components/code/CodeGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand

Check failure on line 68 in packages/ui/app/src/mdx/components/code/CodeGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand
} else {
setSelectedTab([{ groupId: groupId, value: value }, ...groupIds]);

Check failure on line 70 in packages/ui/app/src/mdx/components/code/CodeGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand

Check failure on line 70 in packages/ui/app/src/mdx/components/code/CodeGroup.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand
}
}
}}
value={selectedTabIndex}
>
<div className="rounded-t-[inherit] bg-tag-default-soft">
<div className="mx-px flex min-h-10 items-center justify-between shadow-[inset_0_-1px_0_0] shadow-border-default">
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/app/src/mdx/plugins/rehypeFernCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,16 @@ export function rehypeFernCode(): (tree: Root) => void {

if (isMdxJsxFlowElement(node) && (node.name === "CodeBlocks" || node.name === "CodeGroup")) {
const codeBlockItems = visitCodeBlockNodes(node);
const attributes = [toAttribute("items", codeBlockItems)];

if (node.attributes.length > 0 && node.attributes[0]?.value) {
attributes.push(toAttribute("groupId", node.attributes[0]?.value));
}

parent?.children.splice(index, 1, {
type: "mdxJsxFlowElement",
name: "CodeBlocks",
attributes: [toAttribute("items", codeBlockItems)],
attributes: attributes,

Check failure on line 37 in packages/ui/app/src/mdx/plugins/rehypeFernCode.ts

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand
children: [],
});
return "skip";
Expand Down Expand Up @@ -107,6 +113,8 @@ export function rehypeFernCode(): (tree: Root) => void {

function visitCodeBlockNodes(nodeToVisit: MdxJsxFlowElementHast) {
const codeBlockItems: CodeGroup.Item[] = [];
let groupId: string | undefined;

Check failure on line 116 in packages/ui/app/src/mdx/plugins/rehypeFernCode.ts

View workflow job for this annotation

GitHub Actions / lint

'groupId' is defined but never used. Allowed unused vars must match /^_/u

visit(nodeToVisit, (node) => {
if (isMdxJsxFlowElement(node) && node.name === "CodeBlock") {
const jsxAttributes = node.attributes.filter(
Expand Down Expand Up @@ -154,7 +162,6 @@ function visitCodeBlockNodes(nodeToVisit: MdxJsxFlowElementHast) {
});
}
}
return true;
});
return codeBlockItems;
}
Expand Down

0 comments on commit 4cc5639

Please sign in to comment.