diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index bcf33381d4..4152bd2f0b 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -1,83 +1,83 @@ -name: Vercel Preview Deployment -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }} - ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} - ALGOLIA_SEARCH_INDEX: ${{ secrets.ALGOLIA_SEARCH_INDEX }} - FONTAWESOME_CDN_HOST: https://fontawesome-cdn.vercel.app - WORKOS_API_KEY: ${{ secrets.WORKOS_API_KEY }} - WORKOS_CLIENT_ID: ${{ secrets.WORKOS_CLIENT_ID }} - JWT_SECRET_KEY: ${{ secrets.PROD_JWT_SECRET_KEY }} -on: pull_request +# name: Vercel Preview Deployment +# env: +# VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} +# VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} +# ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }} +# ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} +# ALGOLIA_SEARCH_INDEX: ${{ secrets.ALGOLIA_SEARCH_INDEX }} +# FONTAWESOME_CDN_HOST: https://fontawesome-cdn.vercel.app +# WORKOS_API_KEY: ${{ secrets.WORKOS_API_KEY }} +# WORKOS_CLIENT_ID: ${{ secrets.WORKOS_CLIENT_ID }} +# JWT_SECRET_KEY: ${{ secrets.PROD_JWT_SECRET_KEY }} +# on: pull_request -# Cancel previous workflows on previous push so we don't have deploys overwriting eachother here -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true +# # Cancel previous workflows on previous push so we don't have deploys overwriting eachother here +# concurrency: +# group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} +# cancel-in-progress: true -jobs: - deploy: - runs-on: ubuntu-latest - permissions: write-all - steps: - - uses: actions/checkout@v4 +# jobs: +# deploy: +# runs-on: ubuntu-latest +# permissions: write-all +# steps: +# - uses: actions/checkout@v4 - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 +# - name: Setup pnpm +# uses: pnpm/action-setup@v2 +# with: +# version: 8 - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - cache: pnpm +# - name: Setup Node.js +# uses: actions/setup-node@v4 +# with: +# node-version: 18 +# cache: pnpm - - name: Comment in PR - uses: thollander/actions-comment-pull-request@v2.4.3 - with: - message: | - ## PR Preview - Building... - comment_tag: pr_preview +# - name: Comment in PR +# uses: thollander/actions-comment-pull-request@v2.4.3 +# with: +# message: | +# ## PR Preview +# Building... +# comment_tag: pr_preview - - name: Install Vercel CLI - run: npm install --global vercel@latest +# - name: Install Vercel CLI +# run: npm install --global vercel@latest - - name: Pull Vercel Environment Information - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} +# - name: Pull Vercel Environment Information +# run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - name: Build Project Artifacts - run: VERSION="$(scripts/git-version.sh)" ENABLE_SOURCE_MAPS=true vercel build --debug --token=${{ secrets.VERCEL_TOKEN }} +# - name: Build Project Artifacts +# run: VERSION="$(scripts/git-version.sh)" ENABLE_SOURCE_MAPS=true vercel build --debug --token=${{ secrets.VERCEL_TOKEN }} - - name: Comment in PR - uses: thollander/actions-comment-pull-request@v2.4.3 - with: - message: | - ## PR Preview - Deploying... - comment_tag: pr_preview +# - name: Comment in PR +# uses: thollander/actions-comment-pull-request@v2.4.3 +# with: +# message: | +# ## PR Preview +# Deploying... +# comment_tag: pr_preview - - name: Deploy Project Artifacts to Vercel - run: | - DEPLOYMENT_URL="$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})" - echo "Deployment URL: $DEPLOYMENT_URL" +# - name: Deploy Project Artifacts to Vercel +# run: | +# DEPLOYMENT_URL="$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})" +# echo "Deployment URL: $DEPLOYMENT_URL" - DEPLOYMENT_INFO=$(curl -s -X GET "https://api.vercel.com/v9/projects/fern-prod/domains?limit=50&teamId=team_6FKOM5nw037hv8g2mTk3gaH7&withGitRepoInfo=false" -H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}") - ALIAS_DOMAINS=$(jq -r '.domains[].name' <<< $DEPLOYMENT_INFO) +# DEPLOYMENT_INFO=$(curl -s -X GET "https://api.vercel.com/v9/projects/fern-prod/domains?limit=50&teamId=team_6FKOM5nw037hv8g2mTk3gaH7&withGitRepoInfo=false" -H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}") +# ALIAS_DOMAINS=$(jq -r '.domains[].name' <<< $DEPLOYMENT_INFO) - echo "## PR Preview" > preview.txt +# echo "## PR Preview" > preview.txt - for DOMAIN in ${ALIAS_DOMAINS[@]}; do - echo "Handling domain: $DOMAIN" - if [[ "$DOMAIN" != *"buildwithfern.com"* ]] && [[ "$DOMAIN" != *"vercel.app"* ]]; then - echo "- [ ] [$DOMAIN]($DEPLOYMENT_URL/api/fern-docs/preview?host=$DOMAIN)" >> preview.txt - fi - done +# for DOMAIN in ${ALIAS_DOMAINS[@]}; do +# echo "Handling domain: $DOMAIN" +# if [[ "$DOMAIN" != *"buildwithfern.com"* ]] && [[ "$DOMAIN" != *"vercel.app"* ]]; then +# echo "- [ ] [$DOMAIN]($DEPLOYMENT_URL/api/fern-docs/preview?host=$DOMAIN)" >> preview.txt +# fi +# done - - name: Comment URL in PR - uses: thollander/actions-comment-pull-request@v2.4.3 - with: - filePath: preview.txt - comment_tag: pr_preview +# - name: Comment URL in PR +# uses: thollander/actions-comment-pull-request@v2.4.3 +# with: +# filePath: preview.txt +# comment_tag: pr_preview diff --git a/package.json b/package.json index fe1c304fa3..e6fb07921f 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ } }, "dependencies": { + "@radix-ui/colors": "^3.0.0", "fern-api": "^0.21.0" } } diff --git a/packages/ui/app/package.json b/packages/ui/app/package.json index 40228fd957..611139db1e 100644 --- a/packages/ui/app/package.json +++ b/packages/ui/app/package.json @@ -37,23 +37,27 @@ "dependencies": { "@datadog/browser-logs": "^5.14.0", "@emotion/is-prop-valid": "^1.2.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@fern-api/fdr-sdk": "workspace:*", "@fern-api/template-resolver": "workspace:*", + "@fern-ui/components": "workspace:*", "@fern-ui/core-utils": "workspace:*", "@fern-ui/fdr-utils": "workspace:*", "@fern-ui/loadable": "workspace:*", "@fern-ui/react-commons": "workspace:*", - "@fern-ui/components": "workspace:*", "@headlessui/react": "^1.7.18", + "@mui/icons-material": "^5.15.19", + "@mui/material": "^5.15.19", "@next/third-parties": "^14.2.3", "@radix-ui/colors": "^3.0.0", - "@radix-ui/react-tooltip": "^1.0.7", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", "@segment/snippet": "^5.2.1", "@sentry/nextjs": "^7.105.0", "@shikijs/transformers": "^1.2.2", diff --git a/packages/ui/app/src/api-page/ApiPackageContents.tsx b/packages/ui/app/src/api-page/ApiPackageContents.tsx index 2358587c87..160b0e1f63 100644 --- a/packages/ui/app/src/api-page/ApiPackageContents.tsx +++ b/packages/ui/app/src/api-page/ApiPackageContents.tsx @@ -2,6 +2,7 @@ import { FdrAPI } from "@fern-api/fdr-sdk"; import { EMPTY_ARRAY } from "@fern-ui/core-utils"; import { memo, useMemo } from "react"; import { FernErrorBoundary } from "../components/FernErrorBoundary"; +import { useFeatureFlags } from "../contexts/FeatureFlagContext"; import { ResolvedPackageItem, ResolvedTypeDefinition, @@ -35,6 +36,7 @@ const UnmemoizedApiPackageContents: React.FC = ({ anchorIdParts, breadcrumbs = EMPTY_ARRAY, }) => { + const { isApiScrollingDisabled } = useFeatureFlags(); const { items } = apiDefinition; const subpackageTitle = isResolvedSubpackage(apiDefinition) ? apiDefinition.title : undefined; const currentBreadcrumbs = useMemo( @@ -53,7 +55,9 @@ const UnmemoizedApiPackageContents: React.FC = ({ showErrors={showErrors} endpoint={endpoint} breadcrumbs={currentBreadcrumbs} - isLastInApi={isLastInParentPackage && idx === items.length - 1} + isLastInApi={ + isApiScrollingDisabled || (isLastInParentPackage && idx === items.length - 1) + } types={types} /> ), @@ -62,7 +66,9 @@ const UnmemoizedApiPackageContents: React.FC = ({ key={webhook.id} webhook={webhook} breadcrumbs={breadcrumbs} - isLastInApi={isLastInParentPackage && idx === items.length - 1} + isLastInApi={ + isApiScrollingDisabled || (isLastInParentPackage && idx === items.length - 1) + } types={types} /> ), @@ -70,7 +76,9 @@ const UnmemoizedApiPackageContents: React.FC = ({ ), @@ -80,7 +88,9 @@ const UnmemoizedApiPackageContents: React.FC = ({ types={types} showErrors={showErrors} apiDefinition={subpackage} - isLastInParentPackage={isLastInParentPackage && idx === items.length - 1} + isLastInParentPackage={ + isApiScrollingDisabled || (isLastInParentPackage && idx === items.length - 1) + } anchorIdParts={anchorIdParts} breadcrumbs={currentBreadcrumbs} /> @@ -88,7 +98,9 @@ const UnmemoizedApiPackageContents: React.FC = ({ page: (page) => ( ), })} diff --git a/packages/ui/app/src/api-page/ApiPage.tsx b/packages/ui/app/src/api-page/ApiPage.tsx index 1b1faca543..a55e090692 100644 --- a/packages/ui/app/src/api-page/ApiPage.tsx +++ b/packages/ui/app/src/api-page/ApiPage.tsx @@ -1,7 +1,6 @@ import { EMPTY_ARRAY } from "@fern-ui/core-utils"; import { useSetAtom } from "jotai"; import { useEffect } from "react"; -import { useFeatureFlags } from "../contexts/FeatureFlagContext"; import { useIsReady } from "../contexts/useIsReady"; import { ResolvedRootPackage } from "../resolver/types"; import { APIS } from "../sidebar/atom"; @@ -16,7 +15,7 @@ export declare namespace ApiPage { export const ApiPage: React.FC = ({ initialApi, showErrors }) => { const hydrated = useIsReady(); - const { isApiScrollingDisabled } = useFeatureFlags(); + // const { isApiScrollingDisabled } = useFeatureFlags(); const setDefinitions = useSetAtom(APIS); useEffect(() => { @@ -24,7 +23,7 @@ export const ApiPage: React.FC = ({ initialApi, showErrors }) => }, [initialApi, setDefinitions]); return ( -
+
= ({ initialApi, showErrors }) => anchorIdParts={EMPTY_ARRAY} /> - {isApiScrollingDisabled && ( -
- {/* */} -
- )} - {/* anchor links should get additional padding to scroll to on initial load */} {!hydrated &&
}
diff --git a/packages/ui/app/src/api-page/Breadcrumbs.tsx b/packages/ui/app/src/api-page/Breadcrumbs.tsx index 65d64380ff..4b410d5cf9 100644 --- a/packages/ui/app/src/api-page/Breadcrumbs.tsx +++ b/packages/ui/app/src/api-page/Breadcrumbs.tsx @@ -6,12 +6,12 @@ export function Breadcrumbs({ breadcrumbs }: { breadcrumbs: readonly string[] }) return null; } return ( -
- +
+ {breadcrumbs.map((breadcrumb, idx) => ( - {idx > 0 && } - {breadcrumb} + {idx > 0 && } + {breadcrumb} ))} diff --git a/packages/ui/app/src/api-page/endpoints/CodeExampleClientDropdown.tsx b/packages/ui/app/src/api-page/endpoints/CodeExampleClientDropdown.tsx index 2ce817297b..fc839044f9 100644 --- a/packages/ui/app/src/api-page/endpoints/CodeExampleClientDropdown.tsx +++ b/packages/ui/app/src/api-page/endpoints/CodeExampleClientDropdown.tsx @@ -47,7 +47,7 @@ export const CodeExampleClientDropdown: React.FC} text={selectedClientGroup?.languageDisplayName ?? selectedClient.language} size="small" - variant="outlined" + variant="minimal" mono={true} /> diff --git a/packages/ui/app/src/api-page/endpoints/EndpointContent.tsx b/packages/ui/app/src/api-page/endpoints/EndpointContent.tsx index 01872f1e37..0a40a6bec6 100644 --- a/packages/ui/app/src/api-page/endpoints/EndpointContent.tsx +++ b/packages/ui/app/src/api-page/endpoints/EndpointContent.tsx @@ -1,5 +1,5 @@ import { visitDiscriminatedUnion } from "@fern-ui/core-utils"; -import cn from "clsx"; +import cn, { clsx } from "clsx"; import { useAtom } from "jotai"; import dynamic from "next/dynamic"; import { useRouter } from "next/router"; @@ -140,7 +140,12 @@ export const EndpointContent: React.FC = ({ return clients.find((c) => c.language === selectedLanguage)?.examples[0] ?? curlExample!; }); useEffect(() => { - setSelectedClient((prev) => clients.find((c) => c.language === selectedLanguage)?.examples[0] ?? prev); + setSelectedClient((prev) => { + if (prev.language !== selectedLanguage) { + return clients.find((c) => c.language === selectedLanguage)?.examples[0] ?? prev; + } + return prev; + }); }, [clients, selectedLanguage]); const setSelectedExampleClientAndScrollToTop = useCallback( @@ -228,14 +233,14 @@ export const EndpointContent: React.FC = ({ return (
setSelectedError(undefined)} ref={viewportRef} >
diff --git a/packages/ui/app/src/api-page/endpoints/EndpointContentCodeSnippets.tsx b/packages/ui/app/src/api-page/endpoints/EndpointContentCodeSnippets.tsx index c0a63a8c52..edc4e65f1b 100644 --- a/packages/ui/app/src/api-page/endpoints/EndpointContentCodeSnippets.tsx +++ b/packages/ui/app/src/api-page/endpoints/EndpointContentCodeSnippets.tsx @@ -1,5 +1,5 @@ import { APIV1Read, FernNavigation } from "@fern-api/fdr-sdk"; -import { FernButton, FernButtonGroup, FernScrollArea } from "@fern-ui/components"; +import { FernScrollArea } from "@fern-ui/components"; import { EMPTY_OBJECT, visitDiscriminatedUnion } from "@fern-ui/core-utils"; import { ReactNode, memo, useEffect, useMemo, useRef, useState } from "react"; import { PlaygroundButton } from "../../api-playground/PlaygroundButton"; @@ -21,9 +21,8 @@ import type { CodeExample, CodeExampleGroup } from "../examples/code-example"; import { lineNumberOf } from "../examples/utils"; import { getMessageForStatus } from "../utils/getMessageForStatus"; import { WebSocketMessages } from "../web-socket/WebSocketMessages"; -import { CodeExampleClientDropdown } from "./CodeExampleClientDropdown"; -import { EndpointUrlWithOverflow } from "./EndpointUrlWithOverflow"; import { ErrorExampleSelect } from "./ErrorExampleSelect"; +import { LanguageTabs } from "./LanguageTabs"; export declare namespace EndpointContentCodeSnippets { export interface Props { @@ -130,7 +129,7 @@ const UnmemoizedEndpointContentCodeSnippets: React.FC ) : ( - {successTitle} + {successTitle} ); return ( @@ -138,54 +137,38 @@ const UnmemoizedEndpointContentCodeSnippets: React.FC - {/* TODO: Replace this with a proper segmented control component */} {selectedClientGroup != null && selectedClientGroup.examples.length > 1 && ( - - {selectedClientGroup?.examples.map((example) => ( - { - onClickClient(example); - }} - className="min-w-0 shrink truncate" - mono - size="small" - variant={example === selectedClient ? "outlined" : "minimal"} - intent={example === selectedClient ? "primary" : "none"} - > - {example.name} - +
    + {selectedClientGroup.examples.map((example) => ( +
  • + +
  • ))} - +
)} - } + title={} onClick={(e) => { e.stopPropagation(); }} actions={ - <> - {node != null && ( - - )} - {clients.length > 1 ? ( - - ) : undefined} - + node != null && ( + + ) } code={requestCodeSnippet} language={selectedClient.language} @@ -211,7 +194,13 @@ const UnmemoizedEndpointContentCodeSnippets: React.FC({ json: (value) => ( Output + ) : ( + errorSelector + ) + } onClick={(e) => { e.stopPropagation(); }} diff --git a/packages/ui/app/src/api-page/endpoints/EndpointContentLeft.tsx b/packages/ui/app/src/api-page/endpoints/EndpointContentLeft.tsx index 62170c06e5..eac627864b 100644 --- a/packages/ui/app/src/api-page/endpoints/EndpointContentLeft.tsx +++ b/packages/ui/app/src/api-page/endpoints/EndpointContentLeft.tsx @@ -223,7 +223,7 @@ const UnmemoizedEndpointContentLeft: React.FC = ({ collapseAll={errorExpandAll.setFalse} showExpandCollapse={false} > -
+
{sortBy( endpoint.errors, (e) => e.statusCode, diff --git a/packages/ui/app/src/api-page/endpoints/EndpointError.tsx b/packages/ui/app/src/api-page/endpoints/EndpointError.tsx index d940fed8ff..c478f9763d 100644 --- a/packages/ui/app/src/api-page/endpoints/EndpointError.tsx +++ b/packages/ui/app/src/api-page/endpoints/EndpointError.tsx @@ -63,7 +63,7 @@ export const EndpointError = memo(function EndpointErrorUnm onClick={onClick} >
-
{error.statusCode}
+
{error.statusCode}
{error.name != null ? titleCase(error.name) : getErrorNameForStatus(error.statusCode)}
diff --git a/packages/ui/app/src/api-page/endpoints/ErrorExampleSelect.tsx b/packages/ui/app/src/api-page/endpoints/ErrorExampleSelect.tsx index d4e1a54025..b01579524c 100644 --- a/packages/ui/app/src/api-page/endpoints/ErrorExampleSelect.tsx +++ b/packages/ui/app/src/api-page/endpoints/ErrorExampleSelect.tsx @@ -39,7 +39,7 @@ export const ErrorExampleSelect: FC> const value = `${selectedErrorIndex}:${selectedExampleIndex}`; if (errors.length === 0) { - return {children}; + return {children}; } const renderValue = () => { @@ -138,7 +138,7 @@ export const FernSelectItem = forwardRef< return ( void; + selectedClient: CodeExample; +} + +export function LanguageTabs({ clients, onClickClient, selectedClient }: LanguageTabsProps): ReactElement { + const handleChange = (event: React.ChangeEvent) => { + const selectedLanguage = event.target.value; + const client = clients.find((client) => client.language === selectedLanguage); + if (client) { + onClickClient(client.examples[0]); + } + }; + return ( + + ); +} + +// export function LanguageTabs({ clients, onClickClient, selectedClient }: LanguageTabsProps): ReactElement { +// return ( +//
+//
    +// {clients.map((client) => ( +//
  • +// +//
  • +// ))} +//
+//
+// ); +// } diff --git a/packages/ui/app/src/api-page/endpoints/StreamingEnabledToggle.tsx b/packages/ui/app/src/api-page/endpoints/StreamingEnabledToggle.tsx index f79ded8147..bdcc6d88fe 100644 --- a/packages/ui/app/src/api-page/endpoints/StreamingEnabledToggle.tsx +++ b/packages/ui/app/src/api-page/endpoints/StreamingEnabledToggle.tsx @@ -33,7 +33,7 @@ export const StreamingEnabledToggle: FC // // - // + // // // // diff --git a/packages/ui/app/src/api-page/examples/CodeSnippetExample.tsx b/packages/ui/app/src/api-page/examples/CodeSnippetExample.tsx index cbd3b835c6..c495727fd3 100644 --- a/packages/ui/app/src/api-page/examples/CodeSnippetExample.tsx +++ b/packages/ui/app/src/api-page/examples/CodeSnippetExample.tsx @@ -1,7 +1,5 @@ -import clsx from "clsx"; import { createRef, FC, useCallback, useEffect, useMemo } from "react"; import { FernErrorBoundary } from "../../components/FernErrorBoundary"; -import { useFeatureFlags } from "../../contexts/FeatureFlagContext"; import { FernSyntaxHighlighter } from "../../syntax-highlighting/FernSyntaxHighlighter"; import { ScrollToHandle } from "../../syntax-highlighting/FernSyntaxHighlighterTokens"; import { getJsonLineNumbers } from "./getJsonLineNumbers"; @@ -31,10 +29,10 @@ const CodeSnippetExampleInternal: FC = ({ jsonStartLine, scrollAreaStyle, measureHeight, - className, + // className, ...props }) => { - const { isDarkCodeEnabled } = useFeatureFlags(); + // const { isDarkCodeEnabled } = useFeatureFlags(); const codeBlockRef = createRef(); const viewportRef = createRef(); @@ -74,13 +72,7 @@ const CodeSnippetExampleInternal: FC = ({ }, [requestHighlightLines, viewportRef]); return ( - code, [code])} - {...props} - className={clsx(className, { - "dark bg-card-solid": isDarkCodeEnabled, - })} - > + code, [code])} {...props}> = ({ style={scrollAreaStyle} viewportRef={viewportRef} language={language} - fontSize="sm" + fontSize="base" highlightLines={requestHighlightLines} code={code} /> diff --git a/packages/ui/app/src/api-page/examples/TitledExample.tsx b/packages/ui/app/src/api-page/examples/TitledExample.tsx index 2d96069505..5628c28377 100644 --- a/packages/ui/app/src/api-page/examples/TitledExample.tsx +++ b/packages/ui/app/src/api-page/examples/TitledExample.tsx @@ -1,13 +1,15 @@ -import { Intent } from "@fern-ui/components"; +import { FernButton, FernTooltip, FernTooltipProvider, Intent } from "@fern-ui/components"; +import Brightness6Icon from "@mui/icons-material/Brightness6"; import cn from "clsx"; -import { forwardRef, MouseEventHandler, PropsWithChildren, ReactElement, ReactNode } from "react"; +import { atom, useAtom } from "jotai"; +import { MouseEventHandler, PropsWithChildren, ReactNode, forwardRef } from "react"; import { CopyToClipboardButton } from "../../syntax-highlighting/CopyToClipboardButton"; export declare namespace TitledExample { export interface Props { title: ReactNode; intent?: Intent; - actions?: ReactElement; + actions?: ReactNode; className?: string; copyToClipboardText?: () => string; // use provider to lazily compute clipboard text onClick?: MouseEventHandler; @@ -17,47 +19,46 @@ export declare namespace TitledExample { } } +const DARK_CODE_ENABLED = atom(false); + export const TitledExample = forwardRef>(function TitledExample( { title, intent = "none", className, actions, children, copyToClipboardText, onClick, disableClipboard = false }, ref, ) { + const [isDarkCodeEnabled, setDarkCodeEnabled] = useAtom(DARK_CODE_ENABLED); return (
-
- {typeof title === "string" ? ( -
- {title} -
- ) : ( -
{title}
- )} -
- {actions} - {!disableClipboard && } -
+
{title}
+
+ {actions} + + + } + rounded + variant="minimal" + onClick={() => setDarkCodeEnabled((prev) => !prev)} + /> + + + {!disableClipboard && }
{children} diff --git a/packages/ui/app/src/api-page/types/type-definition/FernCollapseWithButton.tsx b/packages/ui/app/src/api-page/types/type-definition/FernCollapseWithButton.tsx index a342246b4f..9f846d8e86 100644 --- a/packages/ui/app/src/api-page/types/type-definition/FernCollapseWithButton.tsx +++ b/packages/ui/app/src/api-page/types/type-definition/FernCollapseWithButton.tsx @@ -33,7 +33,7 @@ export const FernCollapseWithButton: FC = ({ e separatorText != null ? (
-
{separatorText}
+
{separatorText}
) : ( diff --git a/packages/ui/app/src/api-playground/PlaygroundButton.tsx b/packages/ui/app/src/api-playground/PlaygroundButton.tsx index 8466fd933a..dce9751c7e 100644 --- a/packages/ui/app/src/api-playground/PlaygroundButton.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundButton.tsx @@ -3,7 +3,10 @@ import { FernButton, FernTooltip, FernTooltipProvider } from "@fern-ui/component import { FC } from "react"; import { usePlaygroundContext } from "./PlaygroundContext"; -export const PlaygroundButton: FC<{ state: FernNavigation.NavigationNodeApiLeaf }> = ({ state }) => { +export const PlaygroundButton: FC<{ state: FernNavigation.NavigationNodeApiLeaf; className?: string }> = ({ + state, + className, +}) => { const { hasPlayground, setSelectionStateAndOpen } = usePlaygroundContext(); if (!hasPlayground) { @@ -26,8 +29,8 @@ export const PlaygroundButton: FC<{ state: FernNavigation.NavigationNodeApiLeaf rightIcon="play" variant="outlined" intent="primary" - size="small" - mono={true} + rounded + className={className} > Play diff --git a/packages/ui/app/src/api-playground/PlaygroundDrawer.tsx b/packages/ui/app/src/api-playground/PlaygroundDrawer.tsx index 4337cf0149..0b09962488 100644 --- a/packages/ui/app/src/api-playground/PlaygroundDrawer.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundDrawer.tsx @@ -1,10 +1,9 @@ -import { APIV1Read, FernNavigation } from "@fern-api/fdr-sdk"; +import { APIV1Read } from "@fern-api/fdr-sdk"; import { FernButton } from "@fern-ui/components"; import { EMPTY_OBJECT, visitDiscriminatedUnion } from "@fern-ui/core-utils"; // import { Portal, Transition } from "@headlessui/react"; import * as Dialog from "@radix-ui/react-dialog"; import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons"; -import { motion, useAnimate, useMotionValue } from "framer-motion"; import { atom, useAtom } from "jotai"; import { mapValues } from "lodash-es"; import { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo } from "react"; @@ -24,16 +23,15 @@ import { } from "../resolver/types"; import { PLAYGROUND_FORM_STATE_ATOM, PLAYGROUND_OPEN_ATOM, usePlaygroundContext } from "./PlaygroundContext"; import { PlaygroundEndpoint } from "./PlaygroundEndpoint"; -import { PlaygroundEndpointSelectorContent, flattenApiSection } from "./PlaygroundEndpointSelectorContent"; +import { flattenApiSection } from "./PlaygroundEndpointSelectorContent"; import { PlaygroundWebSocket } from "./PlaygroundWebSocket"; -import { HorizontalSplitPane } from "./VerticalSplitPane"; import { PlaygroundEndpointRequestFormState, PlaygroundFormDataEntryValue, PlaygroundRequestFormAuth, PlaygroundWebSocketRequestFormState, } from "./types"; -import { useVerticalSplitPane, useWindowHeight } from "./useSplitPlane"; +import { useWindowHeight } from "./useSplitPlane"; import { getDefaultValueForObjectProperties, getDefaultValueForType, getDefaultValuesForBody } from "./utils"; const EMPTY_ENDPOINT_FORM_STATE: PlaygroundEndpointRequestFormState = { @@ -84,52 +82,52 @@ interface PlaygroundDrawerProps { export const PlaygroundDrawer: FC = ({ apis }) => { const { selectionState, hasPlayground, collapsePlayground } = usePlaygroundContext(); - const windowHeight = useWindowHeight(); + // const windowHeight = useWindowHeight(); const { sidebar } = useDocsContext(); const apiGroups = useMemo(() => flattenApiSection(sidebar), [sidebar]); const matchedSection = selectionState != null ? apis[selectionState.apiDefinitionId] : undefined; - const nodeIdToApiDefinition = useMemo(() => { - const nodes = new Map(); - Object.values(apis).forEach((api) => { - api.apiDefinitions.forEach((apiDefinition) => { - nodes.set(apiDefinition.nodeId, apiDefinition); - }); - }); - return nodes; - }, [apis]); + // const nodeIdToApiDefinition = useMemo(() => { + // const nodes = new Map(); + // Object.values(apis).forEach((api) => { + // api.apiDefinitions.forEach((apiDefinition) => { + // nodes.set(apiDefinition.nodeId, apiDefinition); + // }); + // }); + // return nodes; + // }, [apis]); const types = matchedSection?.types ?? EMPTY_OBJECT; const layoutBreakpoint = useLayoutBreakpoint(); - const [height, setHeight] = usePlaygroundHeight(); - - const x = useMotionValue(layoutBreakpoint !== "mobile" ? height : windowHeight); - const [scope, animate] = useAnimate(); - - const setOffset = useCallback( - (offset: number) => { - windowHeight != null && setHeight(windowHeight - offset); - }, - [setHeight, windowHeight], - ); - - const { handleVerticalResize, isResizing } = useVerticalSplitPane(setOffset); - - useEffect(() => { - if (isResizing) { - x.jump(layoutBreakpoint !== "mobile" ? height : windowHeight, true); - } else { - if (scope.current != null) { - // x.setWithVelocity(layoutBreakpoint !== "mobile" ? height : windowHeight, 0); - void animate(scope.current, { height: layoutBreakpoint !== "mobile" ? height : windowHeight }); - } else { - x.jump(layoutBreakpoint !== "mobile" ? height : windowHeight, true); - } - } - }, [animate, height, isResizing, layoutBreakpoint, scope, windowHeight, x]); + // const [height, setHeight] = usePlaygroundHeight(); + + // const x = useMotionValue(layoutBreakpoint !== "mobile" ? height : windowHeight); + // const [scope, animate] = useAnimate(); + + // const setOffset = useCallback( + // (offset: number) => { + // windowHeight != null && setHeight(windowHeight - offset); + // }, + // [setHeight, windowHeight], + // ); + + // const { handleVerticalResize, isResizing } = useVerticalSplitPane(setOffset); + + // useEffect(() => { + // if (isResizing) { + // x.jump(layoutBreakpoint !== "mobile" ? height : windowHeight, true); + // } else { + // if (scope.current != null) { + // // x.setWithVelocity(layoutBreakpoint !== "mobile" ? height : windowHeight, 0); + // void animate(scope.current, { height: layoutBreakpoint !== "mobile" ? height : windowHeight }); + // } else { + // x.jump(layoutBreakpoint !== "mobile" ? height : windowHeight, true); + // } + // } + // }, [animate, height, isResizing, layoutBreakpoint, scope, windowHeight, x]); const [isPlaygroundOpen, setPlaygroundOpen] = useAtom(PLAYGROUND_OPEN_ATOM); const [globalFormState, setGlobalFormState] = useAtom(PLAYGROUND_FORM_STATE_ATOM); @@ -324,53 +322,37 @@ export const PlaygroundDrawer: FC = ({ apis }) => { showError={true} reset={resetWithoutExample} > - + + setPlaygroundOpen(false)} + /> { e.preventDefault(); }} - asChild > - - {layoutBreakpoint !== "mobile" ? ( - <> -
-
-
-
-
-
- - } size="large" rounded variant="minimal" /> - - - ) : ( - renderMobileHeader() - )} - {layoutBreakpoint === "mobile" || layoutBreakpoint === "sm" || layoutBreakpoint === "md" ? ( - renderContent() - ) : ( - + {/*
- - - {renderContent()} - - )} - +
+
+
+
+
*/} + + } size="large" rounded variant="minimal" /> + + + ) : ( + renderMobileHeader() + )} + {renderContent()} diff --git a/packages/ui/app/src/api-playground/PlaygroundEndpointContent.tsx b/packages/ui/app/src/api-playground/PlaygroundEndpointContent.tsx index 193ddd02cc..83aeca8723 100644 --- a/packages/ui/app/src/api-playground/PlaygroundEndpointContent.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundEndpointContent.tsx @@ -1,12 +1,4 @@ -import { - FernAudioPlayer, - FernButton, - FernButtonGroup, - FernCard, - FernTabs, - FernTooltip, - FernTooltipProvider, -} from "@fern-ui/components"; +import { FernAudioPlayer, FernButton, FernCard, FernTabs, FernTooltip, FernTooltipProvider } from "@fern-ui/components"; import { Loadable, visitLoadable } from "@fern-ui/loadable"; import { DownloadIcon, PaperPlaneIcon } from "@radix-ui/react-icons"; import cn from "clsx"; @@ -57,6 +49,9 @@ export const PlaygroundEndpointContent: FC = ({ const { domain } = useDocsContext(); const { isSnippetTemplatesEnabled } = useFeatureFlags(); const [requestType, setRequestType] = useAtom(requestTypeAtom); + useEffect(() => { + setRequestType("curl"); + }, [setRequestType]); const scrollAreaRef = useRef(null); const [scrollAreaHeight, setScrollAreaHeight] = useState(0); @@ -110,11 +105,11 @@ export const PlaygroundEndpointContent: FC = ({ ); const requestCard = ( - -
- Request + +
+ Request - + {/* setRequestType("curl")} size="small" @@ -142,7 +137,7 @@ export const PlaygroundEndpointContent: FC = ({ > Python - + */} @@ -177,9 +172,9 @@ export const PlaygroundEndpointContent: FC = ({ ); const responseCard = ( - -
- Response + +
+ Response {response.type === "loaded" && (
diff --git a/packages/ui/app/src/api-playground/PlaygroundEndpointForm.tsx b/packages/ui/app/src/api-playground/PlaygroundEndpointForm.tsx index c7897164cc..1ebe3cce3e 100644 --- a/packages/ui/app/src/api-playground/PlaygroundEndpointForm.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundEndpointForm.tsx @@ -175,7 +175,7 @@ export const PlaygroundEndpointForm: FC = ({
Headers
- + = ({
Path Parameters
- + = ({
Query Parameters
- + = ({
{titleCase(formData.name)}
- +
    {formData.properties.map((property) => visitDiscriminatedUnion(property, "type")._visit({ @@ -302,7 +302,7 @@ export const PlaygroundEndpointForm: FC = ({
    Body
    - + = ({
    Body Parameters
    - + = ({
    Optional Body
    - + = ({ return (
    - +
    Body
    diff --git a/packages/ui/app/src/api-playground/PlaygroundEndpointPath.tsx b/packages/ui/app/src/api-playground/PlaygroundEndpointPath.tsx index 379817ad4d..324af95432 100644 --- a/packages/ui/app/src/api-playground/PlaygroundEndpointPath.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundEndpointPath.tsx @@ -33,7 +33,7 @@ export const PlaygroundEndpointPath: FC = ({ }) => { return (
    -
    +
    {method != null && } {environment?.baseUrl} diff --git a/packages/ui/app/src/api-playground/PlaygroundSecretsModal.tsx b/packages/ui/app/src/api-playground/PlaygroundSecretsModal.tsx index f3f948f3f8..744f32eabd 100644 --- a/packages/ui/app/src/api-playground/PlaygroundSecretsModal.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundSecretsModal.tsx @@ -50,7 +50,7 @@ export const PlaygroundSecretsModal: FC = ({ onClos const [value, setValue] = useState(""); const modal = ( - + } onClick={onClose} />

    Secrets

      diff --git a/packages/ui/app/src/api-playground/PlaygroundWebSocketSessionForm.tsx b/packages/ui/app/src/api-playground/PlaygroundWebSocketSessionForm.tsx index 3e8979a89d..9e458493d7 100644 --- a/packages/ui/app/src/api-playground/PlaygroundWebSocketSessionForm.tsx +++ b/packages/ui/app/src/api-playground/PlaygroundWebSocketSessionForm.tsx @@ -111,7 +111,7 @@ export const PlaygroundWebSocketSessionForm: FC( multiple={type === "fileArray"} /> (function AbsolutelyPositionedAnchor({ href, - smallGap = false, + // smallGap = false, }) { const { copyToClipboard, wasJustCopied } = useCopyToClipboard(() => window.location.origin + hrefToString(href)); @@ -53,10 +52,7 @@ export const AbsolutelyPositionedAnchor = memo href={href} shallow={true} replace={true} - className={cn({ - "-ml-10": !smallGap, - "-ml-8": smallGap, - })} + className="-ml-8" onClick={copyToClipboard} tabIndex={-1} > diff --git a/packages/ui/app/src/components/Chip.tsx b/packages/ui/app/src/components/Chip.tsx index 2857c05d5e..c5e973056b 100644 --- a/packages/ui/app/src/components/Chip.tsx +++ b/packages/ui/app/src/components/Chip.tsx @@ -29,7 +29,7 @@ export const Chip = ({ name, description = undefined, small }: ChipProps): React "t-default bg-tag-default hover:bg-tag-default-hover cursor-default font-mono text-xs flex items-center", { ["py-1 px-1.5 rounded-md h-5"]: small, - ["py-1 px-2 rounded-lg h-6"]: !small, + ["py-1 px-2 rounded-md h-6"]: !small, }, )} style={{ diff --git a/packages/ui/app/src/custom-docs-page/FeedbackFormDialog.tsx b/packages/ui/app/src/custom-docs-page/FeedbackFormDialog.tsx index 72a6bca571..d99e463c84 100644 --- a/packages/ui/app/src/custom-docs-page/FeedbackFormDialog.tsx +++ b/packages/ui/app/src/custom-docs-page/FeedbackFormDialog.tsx @@ -17,7 +17,7 @@ export const FeedbackFormDialog: FC = ({ trigger, conte side="bottom" sideOffset={8} className={clsx( - "z-50 border-default w-[calc(100vw-32px)] sm:w-96 rounded-lg border bg-white/50 p-4 shadow-xl backdrop-blur-xl dark:bg-background/50", + "z-50 border-default w-[calc(100vw-32px)] sm:w-96 rounded-md border bg-white/50 p-4 shadow-xl backdrop-blur-xl dark:bg-background/50", "will-change-[transform,opacity] data-[state=open]:data-[side=top]:animate-slide-down-and-fade data-[state=open]:data-[side=right]:animate-slide-left-and-fade data-[state=open]:data-[side=bottom]:animate-slide-up-and-fade data-[state=open]:data-[side=left]:animate-slide-right-and-fade", className, )} diff --git a/packages/ui/app/src/custom-docs-page/FeedbackPopover.tsx b/packages/ui/app/src/custom-docs-page/FeedbackPopover.tsx index 601f34f5f2..407f620a54 100644 --- a/packages/ui/app/src/custom-docs-page/FeedbackPopover.tsx +++ b/packages/ui/app/src/custom-docs-page/FeedbackPopover.tsx @@ -168,7 +168,7 @@ export const FeedbackPopover = forwardRef import("../search/SearchDialog").then(({ SearchDialog }) => SearchDialog), { ssr: true, }); - export const Docs: React.FC = memo(function UnmemoizedDocs({ logoHeight, logoHref }) { - const { layout, colors, currentVersionId } = useDocsContext(); + const { layout, currentVersionId } = useDocsContext(); const openSearchDialog = useOpenSearchDialog(); const { isInlineFeedbackEnabled } = useFeatureFlags(); @@ -54,54 +53,33 @@ export const Docs: React.FC = memo(function UnmemoizedDocs return ( -
      - {(layout?.disableHeader !== true || ["mobile", "sm", "md"].includes(layoutBreakpoint)) && ( - - )} - -
      - -
      + +
      + -
      - {navbarLinksSection} + -
      - {colors.dark && colors.light && } + - {searchService.isAvailable && ( - { - e.stopPropagation(); - openSearchDialog(); - }} - icon={} - intent="none" - variant="minimal" - rounded={true} - size="large" - className="hidden sm:inline" - /> - )} + - { - e.stopPropagation(); - e.preventDefault(); - if (isMobileSidebarOpen) { - closeMobileSidebar(); - } else { - openMobileSidebar(); - } - }} - icon={ - isMobileSidebarOpen ? ( - - ) : ( - - ) - } - intent={isMobileSidebarOpen ? "primary" : "none"} - variant={isMobileSidebarOpen ? "filled" : "minimal"} - rounded={true} - size="large" - /> -
      +
      ); diff --git a/packages/ui/app/src/docs/HeaderContainer.tsx b/packages/ui/app/src/docs/HeaderContainer.tsx index b734fc6884..f47f9c8121 100644 --- a/packages/ui/app/src/docs/HeaderContainer.tsx +++ b/packages/ui/app/src/docs/HeaderContainer.tsx @@ -47,7 +47,7 @@ export const HeaderContainer: FC = ({ isMobileSidebarOpen, return (
      = ({ isMobileSidebarOpen, } >
      -
      +
      {renderBackground()}
      = ({ logoHeight const { colors, resolveFile, versions } = useDocsContext(); const logoImageHeight = logoHeight ?? DEFAULT_LOGO_HEIGHT; - const imageClassName = "max-h-full object-contain"; + const imageClassName = "max-h-full object-contain -ml-[0.75px]"; const renderLogoContent = () => { if (colors == null) { @@ -71,8 +71,8 @@ export const HeaderLogoSection: React.FC = ({ logoHeight }; return ( -
      -
      +
      +
      {logoHref != null ? ( {renderLogoContent()} diff --git a/packages/ui/app/src/docs/HeaderTabs.tsx b/packages/ui/app/src/docs/HeaderTabs.tsx index 633eb420b1..6c7870a9d1 100644 --- a/packages/ui/app/src/docs/HeaderTabs.tsx +++ b/packages/ui/app/src/docs/HeaderTabs.tsx @@ -1,4 +1,3 @@ -import { RemoteFontAwesomeIcon } from "@fern-ui/components"; import { ReactElement } from "react"; import { FernLink } from "../components/FernLink"; import { useDocsContext } from "../contexts/docs-context/useDocsContext"; @@ -7,23 +6,17 @@ import { getSidebarTabHref } from "../util/getSidebarTabHref"; export function HeaderTabs(): ReactElement { const { tabs, currentTabIndex } = useDocsContext(); return ( -