Skip to content

Commit

Permalink
feat: tabPlacement=header (#576)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Mar 26, 2024
1 parent 1299723 commit 60e7ac9
Show file tree
Hide file tree
Showing 24 changed files with 183 additions and 186 deletions.
17 changes: 6 additions & 11 deletions packages/ui/app/src/api-playground/PlaygroundContext.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { SidebarNode } from "@fern-ui/fdr-utils";
import { useAtom } from "jotai";
import { atomWithStorage } from "jotai/utils";
import { mapValues, noop } from "lodash-es";
import dynamic from "next/dynamic";
import { createContext, FC, PropsWithChildren, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { FC, PropsWithChildren, createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { capturePosthogEvent } from "../analytics/posthog";
import { FeatureFlags, useFeatureFlags } from "../contexts/FeatureFlagContext";
import { useNavigationContext } from "../contexts/navigation-context";
import { APIS } from "../sidebar/atom";
import {
ResolvedApiDefinition,
ResolvedRootPackage,
flattenRootPackage,
isEndpoint,
isWebSocket,
ResolvedApiDefinition,
ResolvedRootPackage,
} from "../util/resolver";
import {
PlaygroundSelectionState,
createFormStateKey,
getInitialEndpointRequestFormStateWithExample,
PlaygroundSelectionState,
usePlaygroundHeight,
} from "./PlaygroundDrawer";
import { PlaygroundRequestFormState } from "./types";
Expand Down Expand Up @@ -49,11 +48,7 @@ export const PLAYGROUND_FORM_STATE_ATOM = atomWithStorage<Record<string, Playgro
{},
);

interface PlaygroundProps {
navigation: SidebarNode[];
}

export const PlaygroundContextProvider: FC<PropsWithChildren<PlaygroundProps>> = ({ children, navigation }) => {
export const PlaygroundContextProvider: FC<PropsWithChildren> = ({ children }) => {
const { isApiPlaygroundEnabled } = useFeatureFlags();
const [apis, setApis] = useAtom(APIS);
const { domain, basePath, selectedSlug } = useNavigationContext();
Expand Down Expand Up @@ -166,7 +161,7 @@ export const PlaygroundContextProvider: FC<PropsWithChildren<PlaygroundProps>> =
}}
>
{children}
<PlaygroundDrawer navigation={navigation} apis={flattenedApis} />
<PlaygroundDrawer apis={flattenedApis} />
{isPlaygroundOpen && hasPlayground && <div style={{ height: playgroundHeight }} />}
</PlaygroundContext.Provider>
);
Expand Down
15 changes: 8 additions & 7 deletions packages/ui/app/src/api-playground/PlaygroundDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { APIV1Read, FdrAPI } from "@fern-api/fdr-sdk";
import { EMPTY_OBJECT, visitDiscriminatedUnion } from "@fern-ui/core-utils";
import { SidebarNode } from "@fern-ui/fdr-utils";
import { Portal, Transition } from "@headlessui/react";
import { Cross1Icon } from "@radix-ui/react-icons";
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { atom, useAtom } from "jotai";
import { mapValues } from "lodash-es";
import { Dispatch, FC, SetStateAction, useCallback, useEffect } from "react";
import { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo } from "react";
import { capturePosthogEvent } from "../analytics/posthog";
import { FernButton, FernButtonGroup } from "../components/FernButton";
import { FernErrorBoundary } from "../components/FernErrorBoundary";
Expand All @@ -25,7 +24,7 @@ import {
import { PLAYGROUND_FORM_STATE_ATOM, PLAYGROUND_OPEN_ATOM, usePlaygroundContext } from "./PlaygroundContext";
import { PlaygroundEndpoint } from "./PlaygroundEndpoint";
import { PlaygroundEndpointSelector } from "./PlaygroundEndpointSelector";
import { PlaygroundEndpointSelectorContent } from "./PlaygroundEndpointSelectorContent";
import { PlaygroundEndpointSelectorContent, flattenApiSection } from "./PlaygroundEndpointSelectorContent";
import { PlaygroundWebSocket } from "./PlaygroundWebSocket";
import {
PlaygroundEndpointRequestFormState,
Expand Down Expand Up @@ -90,14 +89,16 @@ export function usePlaygroundHeight(): [number, Dispatch<SetStateAction<number>>
}

interface PlaygroundDrawerProps {
navigation: SidebarNode[];
apis: Record<string, FlattenedRootPackage>;
}

export const PlaygroundDrawer: FC<PlaygroundDrawerProps> = ({ navigation, apis }) => {
export const PlaygroundDrawer: FC<PlaygroundDrawerProps> = ({ apis }) => {
const { selectionState, hasPlayground, collapsePlayground } = usePlaygroundContext();
const windowHeight = useWindowHeight();

const { sidebarNodes } = useDocsContext();
const apiGroups = useMemo(() => flattenApiSection(sidebarNodes), [sidebarNodes]);

const matchedSection = selectionState != null ? apis[selectionState.api] : undefined;

const types = matchedSection?.types ?? EMPTY_OBJECT;
Expand Down Expand Up @@ -285,7 +286,7 @@ export const PlaygroundDrawer: FC<PlaygroundDrawerProps> = ({ navigation, apis }

<div className="flex items-center justify-center">
{selectionState != null ? (
<PlaygroundEndpointSelector navigation={navigation} />
<PlaygroundEndpointSelector apiGroups={apiGroups} />
) : (
<h6 className="t-accent">Select an endpoint to get started</h6>
)}
Expand Down Expand Up @@ -344,7 +345,7 @@ export const PlaygroundDrawer: FC<PlaygroundDrawerProps> = ({ navigation, apis }
<TooltipProvider>
<div className="flex min-h-0 flex-1 shrink flex-col items-center justify-start">
<PlaygroundEndpointSelectorContent
navigation={navigation}
apiGroups={apiGroups}
className="fern-card mb-6 min-h-0 shrink p-px"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { SidebarNode } from "@fern-ui/fdr-utils";
import { useBooleanState } from "@fern-ui/react-commons";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { ChevronDownIcon, SlashIcon } from "@radix-ui/react-icons";
import { TooltipProvider } from "@radix-ui/react-tooltip";
import cn from "clsx";
import { FC, Fragment, useCallback, useMemo, useRef } from "react";
import { FC, Fragment, useCallback, useRef } from "react";
import { withStream } from "../commons/withStream";
import { FernButton } from "../components/FernButton";
import { usePlaygroundContext } from "./PlaygroundContext";
import { flattenApiSection, PlaygroundEndpointSelectorContent } from "./PlaygroundEndpointSelectorContent";
import { ApiGroup, PlaygroundEndpointSelectorContent } from "./PlaygroundEndpointSelectorContent";

export interface PlaygroundEndpointSelectorProps {
navigation: SidebarNode[];
apiGroups: ApiGroup[];
placeholderText?: string;
buttonClassName?: string;
disabled?: boolean;
}

export const PlaygroundEndpointSelector: FC<PlaygroundEndpointSelectorProps> = ({
navigation,
apiGroups,
placeholderText,
buttonClassName,
disabled,
Expand All @@ -28,8 +27,6 @@ export const PlaygroundEndpointSelector: FC<PlaygroundEndpointSelectorProps> = (

const selectedItemRef = useRef<HTMLLIElement>(null);

const apiGroups = useMemo(() => flattenApiSection(navigation), [navigation]);

const { endpoint: selectedEndpoint, group: selectedGroup } = apiGroups
.flatMap((group) => [
...group.items
Expand Down Expand Up @@ -104,7 +101,7 @@ export const PlaygroundEndpointSelector: FC<PlaygroundEndpointSelectorProps> = (
<DropdownMenu.Portal>
<DropdownMenu.Content sideOffset={4} ref={determinePlacement} className="fern-dropdown rounded-xl">
<PlaygroundEndpointSelectorContent
navigation={navigation}
apiGroups={apiGroups}
closeDropdown={closeDropdown}
selectedEndpoint={selectedEndpoint}
className="h-full"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Cross1Icon, MagnifyingGlassIcon, SlashIcon } from "@radix-ui/react-icon
import cn from "clsx";
import { noop } from "lodash-es";
import dynamic from "next/dynamic";
import { forwardRef, Fragment, ReactElement, useImperativeHandle, useMemo, useRef, useState } from "react";
import { Fragment, ReactElement, forwardRef, useImperativeHandle, useRef, useState } from "react";
import { HttpMethodTag } from "../commons/HttpMethodTag";
import { withStream } from "../commons/withStream";
import { Chip } from "../components/Chip";
Expand All @@ -18,7 +18,7 @@ import { usePlaygroundContext } from "./PlaygroundContext";
const Markdown = dynamic(() => import("../mdx/Markdown").then(({ Markdown }) => Markdown), { ssr: true });

export interface PlaygroundEndpointSelectorContentProps {
navigation: SidebarNode[];
apiGroups: ApiGroup[];
closeDropdown?: () => void;
selectedEndpoint?: SidebarNode.ApiPage;
className?: string;
Expand Down Expand Up @@ -82,15 +82,13 @@ function matchesEndpoint(query: string, group: ApiGroup, endpoint: SidebarNode.A
}

export const PlaygroundEndpointSelectorContent = forwardRef<HTMLDivElement, PlaygroundEndpointSelectorContentProps>(
function PlaygroundEndpointSelectorContent({ navigation, closeDropdown, selectedEndpoint, className }, ref) {
function PlaygroundEndpointSelectorContent({ apiGroups, closeDropdown, selectedEndpoint, className }, ref) {
const { setSelectionStateAndOpen } = usePlaygroundContext();

const [filterValue, setFilterValue] = useState<string>("");

const selectedItemRef = useRef<HTMLLIElement>(null);

const apiGroups = useMemo(() => flattenApiSection(navigation), [navigation]);

const createSelectEndpoint = (group: ApiGroup, endpoint: SidebarNode.EndpointPage) => () => {
setSelectionStateAndOpen({
type: "endpoint",
Expand Down
9 changes: 7 additions & 2 deletions packages/ui/app/src/contexts/docs-context/DocsContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DocsV1Read } from "@fern-api/fdr-sdk";
import { ColorsConfig } from "@fern-ui/fdr-utils";
import { ColorsConfig, SidebarNavigation } from "@fern-ui/fdr-utils";
import React from "react";

export const DocsContext = React.createContext<DocsContextValue>({
Expand All @@ -14,9 +14,14 @@ export const DocsContext = React.createContext<DocsContextValue>({
css: undefined,
files: {},
resolveFile: () => undefined,
currentTabIndex: undefined,
tabs: [],
currentVersionIndex: undefined,
versions: [],
sidebarNodes: [],
});

export interface DocsContextValue {
export interface DocsContextValue extends SidebarNavigation {
domain: string;
basePath: string | undefined;
layout: DocsV1Read.DocsLayoutConfig | undefined;
Expand Down
30 changes: 21 additions & 9 deletions packages/ui/app/src/contexts/docs-context/DocsContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { DocsV1Read, DocsV2Read } from "@fern-api/fdr-sdk";
import { ColorsConfig } from "@fern-ui/fdr-utils";
import { ColorsConfig, SidebarNavigation } from "@fern-ui/fdr-utils";
import { PropsWithChildren, useCallback } from "react";
import { DocsContext } from "./DocsContext";

export declare namespace DocsContextProvider {
export type Props = PropsWithChildren<{
files: Record<DocsV1Read.FileId, DocsV1Read.File_>;
layout: DocsV1Read.DocsLayoutConfig | undefined;
typography: DocsV1Read.DocsTypographyConfigV2 | undefined;
css: DocsV1Read.CssConfig | undefined;
colors: ColorsConfig;
baseUrl: DocsV2Read.BaseUrl;
}>;
export type Props = PropsWithChildren<
{
files: Record<DocsV1Read.FileId, DocsV1Read.File_>;
layout: DocsV1Read.DocsLayoutConfig | undefined;
typography: DocsV1Read.DocsTypographyConfigV2 | undefined;
css: DocsV1Read.CssConfig | undefined;
colors: ColorsConfig;
baseUrl: DocsV2Read.BaseUrl;
} & SidebarNavigation
>;
}

export const DocsContextProvider: React.FC<DocsContextProvider.Props> = ({
Expand All @@ -21,6 +23,11 @@ export const DocsContextProvider: React.FC<DocsContextProvider.Props> = ({
typography,
css,
colors,
currentTabIndex,
tabs,
currentVersionIndex,
versions,
sidebarNodes,
children,
}) => {
const resolveFile = useCallback(
Expand All @@ -45,6 +52,11 @@ export const DocsContextProvider: React.FC<DocsContextProvider.Props> = ({
css,
files,
resolveFile,
currentTabIndex,
tabs,
currentVersionIndex,
versions,
sidebarNodes,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { noop } from "@fern-ui/core-utils";
import { SidebarNavigation, SidebarNode, SidebarVersionInfo } from "@fern-ui/fdr-utils";
import { SidebarNode, SidebarVersionInfo } from "@fern-ui/fdr-utils";
import React from "react";
import { type ResolvedPath } from "../../util/ResolvedPath";

Expand All @@ -24,13 +24,6 @@ export const NavigationContext = React.createContext<NavigationContextValue>({
},
apis: {},
},
navigation: {
sidebarNodes: [],
versions: [],
tabs: [],
currentVersionIndex: undefined,
currentTabIndex: undefined,
},
});

export interface NavigationContextValue {
Expand All @@ -42,5 +35,4 @@ export interface NavigationContextValue {
onScrollToPath: (slug: string) => void;
registerScrolledToPathListener: (slugWithVersion: string, listener: () => void) => () => void;
resolvedPath: ResolvedPath; // the initial path that was hard-navigated
navigation: SidebarNavigation;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SidebarNavigation, SidebarNode, traverseSidebarNodes } from "@fern-ui/fdr-utils";
import { SidebarNode, traverseSidebarNodes } from "@fern-ui/fdr-utils";
import { useEventCallback } from "@fern-ui/react-commons";
import { debounce, memoize } from "lodash-es";
import Head from "next/head";
Expand All @@ -12,6 +12,7 @@ import { useCloseMobileSidebar, useCloseSearchDialog } from "../../sidebar/atom"
import { ResolvedPath } from "../../util/ResolvedPath";
import { getRouteNodeWithAnchor } from "../../util/anchor";
import { useFeatureFlags } from "../FeatureFlagContext";
import { useDocsContext } from "../docs-context/useDocsContext";
import { NavigationContext } from "./NavigationContext";
import { useSlugListeners } from "./useSlugListeners";

Expand All @@ -20,7 +21,6 @@ export declare namespace NavigationContextProvider {
resolvedPath: ResolvedPath;
domain: string;
basePath: string | undefined;
navigation: SidebarNavigation;
title: string | undefined;
}>;
}
Expand Down Expand Up @@ -90,15 +90,15 @@ export const NavigationContextProvider: React.FC<NavigationContextProvider.Props
children,
domain,
basePath,
navigation,
title,
}) => {
const { sidebarNodes, versions, currentVersionIndex } = useDocsContext();
const { isApiScrollingDisabled } = useFeatureFlags();
const router = useRouter();

const [activeNavigatable, setActiveNavigatable] = useState(() =>
resolveActiveSidebarNode(
navigation.sidebarNodes,
sidebarNodes,
resolvedPath.fullSlug.split("/").filter((str) => str.trim().length > 0),
),
);
Expand Down Expand Up @@ -156,7 +156,7 @@ export const NavigationContextProvider: React.FC<NavigationContextProvider.Props
justScrolledTo = `/${fullSlug}`;
void router.replace(`/${fullSlug}`, undefined, { shallow: true, scroll: false });
scrollToPathListeners.invokeListeners(fullSlug);
setActiveNavigatable(resolveActiveSidebarNode(navigation.sidebarNodes, fullSlug.split("/")));
setActiveNavigatable(resolveActiveSidebarNode(sidebarNodes, fullSlug.split("/")));
startScrollTracking(`/${fullSlug}`, true);
},
300,
Expand All @@ -171,7 +171,7 @@ export const NavigationContextProvider: React.FC<NavigationContextProvider.Props
justScrolledTo = undefined;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const fullSlug = route.substring(1).split("#")[0]!;
setActiveNavigatable(resolveActiveSidebarNode(navigation.sidebarNodes, decodeURI(fullSlug).split("/")));
setActiveNavigatable(resolveActiveSidebarNode(sidebarNodes, decodeURI(fullSlug).split("/")));
startScrollTracking(route);
});

Expand Down Expand Up @@ -233,9 +233,8 @@ export const NavigationContextProvider: React.FC<NavigationContextProvider.Props
onScrollToPath,
registerScrolledToPathListener: scrollToPathListeners.registerListener,
resolvedPath,
activeVersion: navigation.versions[navigation.currentVersionIndex ?? 0],
activeVersion: versions[currentVersionIndex ?? 0],
selectedSlug,
navigation,
}}
>
<Head>
Expand Down
Loading

0 comments on commit 60e7ac9

Please sign in to comment.