From b9b61e5e5de7c05dfc11538681b50f31bc44a375 Mon Sep 17 00:00:00 2001 From: Christayc <93091189+Christayc@users.noreply.github.com> Date: Sun, 31 May 2026 13:51:24 -0600 Subject: [PATCH] Improve playground Lighthouse loading --- src/components/playground/GraphiQLPanel.tsx | 55 +++++ src/components/playground/Playground.tsx | 58 +---- src/components/playground/index.tsx | 1 - .../{playground.tsx => playground/app.tsx} | 10 +- static/playground/index.html | 204 ++++++++++++++++++ 5 files changed, 274 insertions(+), 54 deletions(-) create mode 100644 src/components/playground/GraphiQLPanel.tsx rename src/pages/{playground.tsx => playground/app.tsx} (66%) create mode 100644 static/playground/index.html diff --git a/src/components/playground/GraphiQLPanel.tsx b/src/components/playground/GraphiQLPanel.tsx new file mode 100644 index 000000000..33401df9a --- /dev/null +++ b/src/components/playground/GraphiQLPanel.tsx @@ -0,0 +1,55 @@ +import React, {useMemo} from "react" +import {GraphiQL} from "graphiql" +import type {Fetcher} from "@graphiql/toolkit" +import {createGraphiQLFetcher} from "@graphiql/create-fetcher" +import {CookiePreferenceCategory, playgroundAdsConversionId} from "@site/src/constants" +import {analyticsHandler, sendConversionEvent} from "@site/src/utils" +import {useCookieConsent} from "@site/src/utils/hooks/useCookieConsent" +import "graphiql/graphiql.css" +import "../../css/graphiql.css" + +type GraphiQLPanelProps = { + apiEndpoint: string +} + +const emptyGraphiqlStorageObject = { + getItem: (): null => null, + setItem: (): void => undefined, + removeItem: (): void => undefined, + clear: (): void => undefined, + length: 0, +} + +const GraphiQLPanel = ({apiEndpoint}: GraphiQLPanelProps) => { + const {getCookieConsent} = useCookieConsent() + const cookieConsent = getCookieConsent() + + const graphQLFetcher: Fetcher = (graphQLParams, opts) => { + analyticsHandler("GraphQL", "tc_fetch_query", apiEndpoint) + sendConversionEvent(playgroundAdsConversionId) + + const fetcher = createGraphiQLFetcher({url: apiEndpoint}) as unknown as Fetcher + return fetcher(graphQLParams, opts) + } + + const graphiqlStorage = useMemo(() => { + if ( + cookieConsent?.accepted && + (!cookieConsent?.preferences || cookieConsent?.preferences?.includes(CookiePreferenceCategory.PREFERENCE)) + ) { + return undefined + } + + return emptyGraphiqlStorageObject + }, [cookieConsent]) + + return ( + + + <> + + + ) +} + +export default GraphiQLPanel diff --git a/src/components/playground/Playground.tsx b/src/components/playground/Playground.tsx index d077327b4..45c49b8d7 100644 --- a/src/components/playground/Playground.tsx +++ b/src/components/playground/Playground.tsx @@ -1,12 +1,7 @@ -import React, {useEffect, useMemo, useState} from "react" -import {GraphiQL} from "graphiql" -import {analyticsHandler, isValidURL, sendConversionEvent} from "@site/src/utils" -import {CookiePreferenceCategory, playgroundAdsConversionId} from "@site/src/constants" -import "graphiql/graphiql.css" -import "../../css/graphiql.css" -import {type FetcherParams, FetcherOpts} from "@graphiql/toolkit" -import {useCookieConsent} from "@site/src/utils/hooks/useCookieConsent" -import {createGraphiQLFetcher} from "@graphiql/create-fetcher" +import React, {Suspense, lazy, useEffect, useState} from "react" +import {isValidURL} from "@site/src/utils" + +const GraphiQLPanel = lazy(() => import("./GraphiQLPanel")) const useDebouncedValue = (inputValue: string, delay: number) => { const [debouncedValue, setDebouncedValue] = useState(inputValue) @@ -33,9 +28,6 @@ const Playground = () => { ) const [inputValue, setInputValue] = useState(initialApiEndpoint.toString()) - const {getCookieConsent} = useCookieConsent() - const cookieConsent = getCookieConsent() - const debouncedApiEndpoint = useDebouncedValue(inputValue, 500) const apiEndpointInputClasses = `border border-solid border-tailCall-border-light-500 rounded-lg font-space-grotesk h-11 w-[100%] p-SPACE_04 text-content-small outline-none focus:border-x-tailCall-light-700` @@ -46,37 +38,7 @@ const Playground = () => { } }, [debouncedApiEndpoint]) - const graphQLFetcher = async (graphQLParams: FetcherParams, opts?: FetcherOpts) => { - if (apiEndpoint.toString().trim() === "") { - return Promise.resolve({}) - } - analyticsHandler("GraphQL", "tc_fetch_query", apiEndpoint.toString()) - sendConversionEvent(playgroundAdsConversionId) - - const fetcher = createGraphiQLFetcher({url: apiEndpoint.toString()}) - return fetcher(graphQLParams, opts) - } - - const emptyGraphiqlStorageObject = { - getItem: (): null => null, - setItem: (): void => undefined, - removeItem: (): void => undefined, - clear: (): void => undefined, - length: 0, - } - - const graphiqlStorage = useMemo(() => { - if ( - cookieConsent?.accepted && - (!cookieConsent?.preferences || cookieConsent?.preferences?.includes(CookiePreferenceCategory.PREFERENCE)) - ) { - // Defaults to local storage - return undefined - } - - // Block storing graphiql data in local storage if user denies cookie consent - return emptyGraphiqlStorageObject - }, [cookieConsent]) + const endpointUrl = apiEndpoint.toString().trim() return (
@@ -93,11 +55,11 @@ const Playground = () => { />
- - - <> - - + {endpointUrl !== "" && ( + + + + )}
)} diff --git a/src/components/playground/index.tsx b/src/components/playground/index.tsx index 846c15cf5..93ca9b63e 100644 --- a/src/components/playground/index.tsx +++ b/src/components/playground/index.tsx @@ -1,6 +1,5 @@ import React from "react" import Playground from "./Playground" -import Announcement from "@site/src/components/shared/Announcement" const PlaygroundPage = (): JSX.Element => { return ( diff --git a/src/pages/playground.tsx b/src/pages/playground/app.tsx similarity index 66% rename from src/pages/playground.tsx rename to src/pages/playground/app.tsx index e38dbc11c..fed5b012b 100644 --- a/src/pages/playground.tsx +++ b/src/pages/playground/app.tsx @@ -1,15 +1,15 @@ import React, {useEffect} from "react" import ReactGA from "react-ga4" import Layout from "@theme/Layout" -import PlaygroundPage from "../components/playground" +import PlaygroundPage from "../../components/playground" import {useLocation} from "@docusaurus/router" -import {PageDescription, PageTitle} from "../constants/titles" +import {PageDescription, PageTitle} from "../../constants/titles" -const Playground = () => { +const PlaygroundApp = () => { const location = useLocation() useEffect(() => { - ReactGA.send({hitType: "pageview", page: location.pathname, title: "Playground Page"}) + ReactGA.send({hitType: "pageview", page: location.pathname, title: "Playground App Page"}) }, []) return ( @@ -19,4 +19,4 @@ const Playground = () => { ) } -export default Playground +export default PlaygroundApp diff --git a/static/playground/index.html b/static/playground/index.html new file mode 100644 index 000000000..8f08ec0f2 --- /dev/null +++ b/static/playground/index.html @@ -0,0 +1,204 @@ + + + + + + + Tailcall Playground + + + + +
+
+
+ > + Tailcall +
+

GraphQL Playground

+

+ Connect to a GraphQL endpoint without loading the full editor until you are ready. +

+
+ + + +
+ +
+
+ + +