Skip to content

Commit

Permalink
feat: unify language display in codeblocks (#2103)
Browse files Browse the repository at this point in the history
  • Loading branch information
chdeskur authored Feb 3, 2025
1 parent 4a79b06 commit b84220b
Showing 1 changed file with 69 additions and 6 deletions.
75 changes: 69 additions & 6 deletions packages/fern-docs/ui/src/mdx/components/code/CodeGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { ApiDefinition } from "@fern-api/fdr-sdk";
import { CopyToClipboardButton } from "@fern-docs/components";
import {
FernSyntaxHighlighter,
type FernSyntaxHighlighterProps,
} from "@fern-docs/syntax-highlighter";
import * as Tabs from "@radix-ui/react-tabs";
import clsx from "clsx";
import { useState } from "react";
import { useEdgeFlags } from "../../../atoms";
import { useAtom } from "jotai";
import { useEffect, useRef, useState } from "react";
import { getLanguageDisplayName } from "../../../api-reference/examples/code-example";
import { FERN_LANGUAGE_ATOM, useEdgeFlags } from "../../../atoms";
import { HorizontalOverflowMask } from "../../../components/HorizontalOverflowMask";

export declare namespace CodeGroup {
Expand All @@ -24,6 +27,64 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
}) => {
const { isDarkCodeEnabled } = useEdgeFlags();
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const [selectedLanguage, setSelectedLanguage] = useAtom(FERN_LANGUAGE_ATOM);
const itemsRef = useRef(items);
itemsRef.current = items;

useEffect(() => {
if (selectedLanguage) {
const matchingTab = itemsRef.current.find((item) => {
const normalizedLanguage = ApiDefinition.cleanLanguage(item.language);
return item.language && normalizedLanguage === selectedLanguage;
});

if (matchingTab) {
const newIndex = itemsRef.current.indexOf(matchingTab);
setSelectedTabIndex((prevIndex) => {
const prevTab = itemsRef.current[prevIndex];
if (
prevTab?.language &&
ApiDefinition.cleanLanguage(prevTab.language) === selectedLanguage
) {
return prevIndex;
}
return newIndex;
});
}
}
}, [selectedLanguage]);

const handleTabChange = (value: string) => {
const newIndex = parseInt(value, 10);
setSelectedTabIndex(newIndex);

const tab = itemsRef.current[newIndex];
const normalizedLanguage = tab?.language
? ApiDefinition.cleanLanguage(tab.language)
: undefined;

if (normalizedLanguage && normalizedLanguage !== selectedLanguage) {
setSelectedLanguage(normalizedLanguage);
}
};

const getDisplayNameWithCount = (
language: string | undefined,
items: CodeGroup.Item[],
currentIndex: number
): string => {
const normalizedLanguage = ApiDefinition.cleanLanguage(language ?? "");
const displayName = getLanguageDisplayName(normalizedLanguage);
const sameLanguageCount = items
.slice(0, currentIndex)
.filter(
(i) =>
ApiDefinition.cleanLanguage(i.language ?? "") === normalizedLanguage
).length;
return sameLanguageCount > 0
? `${displayName} ${sameLanguageCount}`
: displayName;
};

const containerClass = clsx(
"bg-card after:ring-card-border relative mb-6 mt-4 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-[''] first:mt-0",
Expand All @@ -40,7 +101,8 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
<div className="flex min-h-10 overflow-x-auto">
<div className="flex items-center px-3 py-1.5">
<span className="t-muted rounded text-sm font-semibold">
{items[0].title ?? "Untitled"}
{items[0].title ??
ApiDefinition.cleanLanguage(items[0].language)}
</span>
</div>
</div>
Expand All @@ -58,8 +120,8 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
return (
<Tabs.Root
className={containerClass}
onValueChange={(value) => setSelectedTabIndex(parseInt(value, 10))}
defaultValue="0"
onValueChange={handleTabChange}
value={selectedTabIndex.toString()}
>
<div className="bg-tag-default-soft rounded-t-[inherit]">
<div className="shadow-border-default mx-px flex min-h-10 items-center justify-between shadow-[inset_0_-1px_0_0]">
Expand All @@ -72,7 +134,8 @@ export const CodeGroup: React.FC<React.PropsWithChildren<CodeGroup.Props>> = ({
className="data-[state=active]:shadow-accent group flex min-h-10 items-center px-2 py-1.5 data-[state=active]:shadow-[inset_0_-2px_0_0_rgba(0,0,0,0.1)]"
>
<span className="t-muted group-data-[state=active]:t-default group-hover:bg-tag-default whitespace-nowrap rounded px-2 py-1 text-sm group-data-[state=active]:font-semibold">
{item.title ?? `Untitled ${idx + 1}`}
{item.title ??
getDisplayNameWithCount(item.language, items, idx)}
</span>
</Tabs.Trigger>
))}
Expand Down

0 comments on commit b84220b

Please sign in to comment.