-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathindex.tsx
More file actions
109 lines (99 loc) · 3.87 KB
/
index.tsx
File metadata and controls
109 lines (99 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"use client"
import { useRef, useState } from "react"
import { useInView } from "motion/react"
import dynamic from "next/dynamic"
import { clsx } from "clsx"
import { Button } from "@/app/conf/_design-system/button"
import { SectionLabel } from "@/app/conf/_design-system/section-label"
import InfoIcon from "@/app/conf/_design-system/pixelarticons/info.svg?svgr"
import {
HowItWorks_Schema,
HowItWorks_Query,
HowItWorks_Result,
} from "@/components/code-blocks"
import { HowItWorksListItem } from "./how-it-works-list-item"
import { PlayButton } from "./play-button"
import { Kbd } from "../../../_design-system/kbd"
const InteractiveEditor = dynamic(() => import("./interactive-editor"), {
ssr: false,
})
const TRY_IT_OUT_URL = "https://graphql.org/swapi-graphql"
export function HowItWorks() {
const sectionRef = useRef<HTMLElement>(null)
// todo: we could technically consider loading the chunk on hover or focus,
// just so people scrolling through the page don't download CodeMirror
const inView = useInView(sectionRef)
const [interacted, setInteracted] = useState(false)
return (
<section
ref={sectionRef}
className="gql-container gql-section xl:py-20"
// this is mostly for Playwright, we're not getting a hydration warning normally
suppressHydrationWarning
>
<SectionLabel className="mb-6">How it works</SectionLabel>
<h2 className="typography-h2 mb-6 lg:mb-16">A GraphQL Query</h2>
<div className="relative">
{/* eslint-disable-next-line tailwindcss/no-custom-classname*/}
<ol className="gql-radial-gradient list-none gap-px max-lg:before:absolute max-lg:before:inset-x-0 max-lg:before:-top-2 max-lg:before:bottom-[98%] max-lg:before:bg-[rgb(var(--nextra-bg))] max-md:bg-gradient-to-r max-md:from-transparent max-md:via-neu-400 max-md:to-transparent lg:grid lg:grid-cols-3">
<HowItWorksListItem
text="Describe your data"
code={<HowItWorks_Schema />}
/>
<HowItWorksListItem
text="Ask for what you want"
icon={<PlayButton disabled={inView} />}
code={<HowItWorks_Query />}
/>
<HowItWorksListItem
text="Get predictable results"
code={<HowItWorks_Result />}
/>
</ol>
{inView && (
<ol
// this is rendered *on top* of the static version to avoid layout shift
className="max-lg:before pointer-events-none absolute inset-0 list-none gap-px [counter-set:list-item_1] *:pointer-events-auto max-lg:before:absolute max-lg:before:inset-x-0 max-lg:before:-top-2 max-lg:before:bottom-[98%] max-lg:before:bg-[rgb(var(--nextra-bg))] max-sm:top-[191px] sm:max-lg:top-[214px] lg:grid lg:grid-cols-3 lg:[&>:first-child]:col-start-2"
onKeyDown={() => {
if (!interacted) setInteracted(true)
}}
>
<InteractiveEditor />
</ol>
)}
</div>
<FigureInfo
className={clsx("transition-opacity", interacted ? "opacity-0" : "")}
/>
<Button className="mx-auto mt-8 w-fit lg:mt-16" href={TRY_IT_OUT_URL}>
Try GraphiQL
</Button>
</section>
)
}
function FigureInfo({ className }: { className?: string }) {
return (
<div
className={clsx(
"typography-body-sm mx-auto mt-12 flex w-fit gap-2 text-neu-800 hover-none:hidden dark:text-neu-600",
className,
)}
>
<InfoIcon className="size-4 shrink-0 translate-y-[2.25px]" />
<p className="text-neu-800">
Press <Kbd>Ctrl</Kbd>
<Kbd className="ml-0.5">Space</Kbd> to open the completions menu,{" "}
<MetaKey />
<Kbd>Enter</Kbd> to run the query.
</p>
</div>
)
}
function MetaKey() {
return (
<>
<Kbd className="mx-0.5 hidden [.mac_&]:inline-flex">⌘</Kbd>
<Kbd className="mx-0.5 [.mac_&]:hidden">Ctrl</Kbd>
</>
)
}