Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/pages/playground.tsx → src/pages/playground/app.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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 location = useLocation()
Expand Down
257 changes: 257 additions & 0 deletions static/playground/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="Open the Tailcall GraphQL playground after entering an API endpoint." />
<meta name="theme-color" content="#0b1612" />
<link rel="canonical" href="https://tailcall.run/playground/" />
<link rel="icon" href="/images/favicon.ico" />
<title>Playground | Tailcall</title>
<style>
:root {
color-scheme: dark;
--background: #07110d;
--panel: #101c17;
--panel-strong: #152620;
--border: #284439;
--text: #f4fff9;
--muted: #bed0c7;
--accent: #a7f56f;
--accent-strong: #74db4a;
}

* {
box-sizing: border-box;
}

body {
margin: 0;
min-height: 100vh;
background: var(--background);
color: var(--text);
font-family:
Inter,
ui-sans-serif,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
}

main {
min-height: 100vh;
display: grid;
place-items: center;
padding: 32px 20px;
}

.shell {
width: min(920px, 100%);
}

.brand {
display: inline-flex;
align-items: center;
gap: 10px;
margin-bottom: 44px;
color: var(--muted);
font-size: 15px;
font-weight: 700;
}

.mark {
width: 32px;
height: 32px;
border-radius: 8px;
background: var(--accent);
color: #061109;
display: grid;
place-items: center;
font-size: 18px;
font-weight: 900;
}

.hero {
max-width: 780px;
}

h1 {
margin: 0;
color: var(--text);
font-size: clamp(42px, 7vw, 82px);
line-height: 0.96;
font-weight: 800;
}

p {
margin: 24px 0 0;
max-width: 620px;
color: var(--muted);
font-size: 19px;
line-height: 1.55;
}

form {
margin-top: 36px;
display: grid;
grid-template-columns: 1fr auto;
gap: 12px;
width: min(720px, 100%);
}

label {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

input,
button {
min-height: 54px;
border-radius: 8px;
font: inherit;
}

input {
width: 100%;
border: 1px solid var(--border);
background: var(--panel);
color: var(--text);
padding: 0 16px;
outline: none;
}

input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(167, 245, 111, 0.2);
}

button {
border: 0;
background: var(--accent);
color: #061109;
padding: 0 22px;
font-weight: 800;
cursor: pointer;
}

button:hover {
background: var(--accent-strong);
}

.empty-link {
display: inline-flex;
margin-top: 18px;
color: var(--accent);
font-weight: 700;
text-decoration: none;
}

.empty-link:hover {
color: var(--accent-strong);
}

.note {
margin-top: 34px;
display: inline-flex;
max-width: 720px;
border: 1px solid var(--border);
background: var(--panel-strong);
border-radius: 8px;
padding: 14px 16px;
color: var(--muted);
font-size: 14px;
line-height: 1.45;
}

@media (max-width: 640px) {
main {
align-items: start;
padding-top: 42px;
}

.brand {
margin-bottom: 34px;
}

h1 {
font-size: 44px;
line-height: 1.02;
}

p {
font-size: 17px;
}

form {
grid-template-columns: 1fr;
}

button {
width: 100%;
}
}
</style>
</head>
<body>
<main>
<section class="shell" aria-labelledby="playground-title">
<a class="brand" href="/">
<span class="mark" aria-hidden="true">T</span>
Tailcall
</a>

<div class="hero">
<h1 id="playground-title">GraphQL Playground</h1>
<p>
Enter an endpoint to open the full Tailcall playground. The interactive editor loads only after an endpoint
is provided.
</p>

<form id="playground-form" action="/playground/app/" method="get">
<label for="endpoint">GraphQL endpoint</label>
<input
id="endpoint"
name="u"
type="url"
inputmode="url"
autocomplete="url"
placeholder="https://api.example.com/graphql"
/>
<button type="submit">Open Playground</button>
</form>

<a class="empty-link" href="/playground/app/">Open without endpoint</a>

<div class="note">Endpoint links using ?u= keep working and move directly into the interactive app.</div>
</div>
</section>
</main>

<script>
;(() => {
const params = new URLSearchParams(window.location.search)
const endpoint = params.get("u")
const input = document.getElementById("endpoint")

if (input && endpoint) {
input.value = endpoint
}

if (endpoint) {
const appUrl = new URL("/playground/app/", window.location.origin)
appUrl.searchParams.set("u", endpoint)
window.location.replace(appUrl)
}
})()
</script>
</body>
</html>
Loading